الإشعارات الدائنة
يُصدر POST /v1/credit-notes إشعاراً دائناً على بنود من فاتورة مبيعات صادرة، في طلب واحد. لا توجد مرحلة مسودة، والإشعار الدائن بعد إصداره لا يُلغى. وترجع البضاعة المشمولة بالإشعار إلى المخزون.
الحقول المطلوبة
كل طلب يرسل invoiceId و reason و lines، ومعها الـ Header Idempotency-Key مثل أي طلب POST:
{
"invoiceId": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e",
"reason": "refund",
"lines": [{ "itemId": "7c8d9e0f-1a2b-4c3d-8e4f-5a6b7c8d9e0f", "quantity": 1 }],
"refund": { "paymentMethodId": "5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9" }
}
يأخذ الإشعار الفرع والعميل والأسعار من الفاتورة. وكل بند يحدد منتجاً مُباعاً في تلك الفاتورة، مرة واحدة فقط، بكمية quantity عددها صحيح ولا تزيد على المتبقي من هذا المنتج. وتُحسب الوحدة بحصتها مما احتسبته الفاتورة للمنتج. وفي الفاتورة الصادرة عن طريق الـ API يُقرَّب كل بند إلى الهللة بالطريقة التي تحسب بها الهيئة إجمالي الإشعار، لذلك قد يزيد مجموع الإشعارات على الوحدات واحدةً واحدة بهللة عن إشعار واحد عليها معاً. ولهذا يُسمح للإشعار على هذه الفاتورة بأن يزيد على المتبقي منها بهللة عن كل بند صدر قبله في إشعار سابق، وبهللة واحدة على الأقل، حتى يمكن دائماً إصدار الإشعار على آخر الوحدات.
الرد كاملاً موضح في مرجع الـ API.
تُرسل قيمة reason إلى الهيئة سبباً للإشعار:
reason | متى تستخدمها |
|---|---|
cancellation | إلغاء البيع كله أو جزء منه |
refund | إرجاع منتجات أو خدمات وإعادة المبلغ للعميل |
informationChange | تصحيح بيانات خاطئة في الفاتورة |
ويقبل notes حتى 500 حرف ويُطبع على الإشعار. ويقبل referenceId حتى 100 حرف، ولا يتكرر في أي فاتورة أو إشعار آخر لدى التاجر.
إرجاع المبلغ
مع refund يُرجع إجمالي الإشعار عن طريق refund.paymentMethodId، من خزينة طريقة الدفع هذه في فرع الفاتورة:
- طريقة الدفع التي تخدم خزينتها فرعاً آخر فقط تُرفض (
422 payment_method_not_in_branch). - لا يزيد المبلغ المرجع على ما حُصّل على الفاتورة، مطروحاً منه ما أُرجع منها سابقاً (
422 refund_exceeds_collected).
وبدون refund يُخصم الإجمالي من المبلغ المستحق على العميل، فتنقص قيمة amountDue في فاتورة المبيعات بمقداره دون أن تقل عن 0، وما يزيد على ذلك يبقى رصيداً دائناً للعميل. ولا يكون ذلك إلا لعميل يمكن أن يُحفظ له رصيد:
- العميل من نوع شركة يمكن له ذلك دائماً.
- العميل الفرد لا يحمل رصيداً، فلا يكون ذلك له إلا في حدود المستحق على الفاتورة. وإذا زاد الإشعار على ذلك فأرسل
refund(400 invalid_parameterعلىrefund). - الفاتورة التي ليس لها عميل يجب إرسال
refundمعها (400 invalid_parameterعلىrefund).
وهذا ينطبق أيضاً على البيع المدفوع ببطاقة في نقطة البيع: بدون refund يذهب الإشعار إلى رصيد العميل، ولا يُرجع أي مبلغ إلى البطاقة.
يظهر المبلغ المرجع في الرد في refund.amount، وتكون قيمة refund هي null إذا ذهب الإشعار إلى رصيد العميل.
الحد الأقصى للإشعار
مجموع الإشعارات على الفاتورة لا يتجاوز إجماليها، أياً كانت القناة. فالاسترجاع من نقطة البيع أو من لوحة التحكم، ومرتجعات المبيعات، والإشعارات الصادرة عن طريق الـ API، كلها تُحسب من الإجمالي نفسه ومن الكمية المتبقية من كل منتج. والإشعار الذي يتجاوز المتبقي يرجع له 422 credit_exceeds_invoice:
- تكون قيمة
paramهيlines[i].quantityإذا طلب البند كمية أكثر من المتبقي من منتجه. - وتكون
linesإذا كان إجمالي الإشعار أكثر من المتبقي على الفاتورة.
وإذا وصل إشعاران على الفاتورة نفسها في اللحظة نفسها فإنهما يصدران واحداً بعد الآخر، فيُتحقَّق من الثاني مقابل ما بقي بعد الأول. وإذا استمر إصدار الأول أكثر من 30 ثانية، كأن ينتظر رد الهيئة، يرجع للثاني 409 invoice_busy، فأعد إرساله.
هيئة الزكاة والضريبة والجمارك
نوع الإشعار لدى الهيئة هو نوع فاتورته نفسها:
- الفاتورة الضريبية (standard):
- تعتمد الهيئة الإشعار قبل الرد.
- إذا رفضته لا يُحفظ أي شيء، ويرجع
422 zatca_rejectedمع رسائل الهيئة فيzatcaErrors. - إذا تأخر رد الهيئة يرجع
201بقيمةpendingفيzatca.status، ثم تعيد كسور إرساله لاحقاً، فتصبحcleared، أوrejectedمع رسائل الهيئة فيzatca.errors. وفي الحالتين يبقى الإشعار صادراً. - الفاتورة التي لم تعتمدها الهيئة بعد لا يصدر عليها إشعار (
409 invoice_not_clearedعلىinvoiceId). أعد المحاولة عندما تصبح قيمةzatca.statusهيclearedفيGET /v1/sales-invoices/{id}، وهذا الطلب يحتاج صلاحيةsales_invoices:read. ولا يُحفظ أي رد4xx، لذلك يمكن أن تستخدم إعادة المحاولة المفتاحIdempotency-Keyنفسه.
- الفاتورة المبسطة (simplified): يُبلَّغ بالإشعار للهيئة بعد الرد. وتبقى قيمة
zatca.statusهيpendingحتى يتم التبليغ، ثم تصبحreported، أوrejectedمع رسائل الهيئة فيzatca.errors.
والفاتورة التي رفضتها الهيئة لا يصدر عليها إشعار عن طريق الـ API (422 invoice_not_creditable)، فيجب أن يصحح التاجر البيع أولاً.
ويرجع GET /v1/credit-notes/{id}/pdf و GET /v1/credit-notes/{id}/xml ملفات الإشعار:
- الإشعار الضريبي (standard) يرجع ملفاه
409 invoice_not_clearedحتى تعتمده الهيئة، ودائماً إذا رفضته. - الإشعار المبسط (simplified) يكون ملف PDF الخاص به جاهزاً فوراً، أما ملف XML فيرجع
409 invoice_not_clearedحتى تقبل الهيئة التبليغ، ودائماً إذا رفضته.
حالات الرفض
| الخطأ | متى يرجع |
|---|---|
422 referenced_resource_not_found | الفاتورة غير موجودة أو في فرع لا يملك مفتاحك صلاحية عليه، أو طريقة الدفع في refund غير موجودة أو معطّلة، ويحدد param الحقل |
422 invoice_not_creditable | الفاتورة ليست فاتورة مبيعات صادرة، أو مستوردة، أو رفضتها الهيئة |
409 invoice_not_cleared على invoiceId | الفاتورة ضريبية ولم تعتمدها الهيئة بعد |
400 invalid_parameter على lines[i].itemId | المنتج غير مُباع في هذه الفاتورة |
422 credit_exceeds_invoice | كمية البند أكثر من المتبقي من المنتج، أو الإجمالي أكثر من المتبقي على الفاتورة |
400 invalid_parameter على refund | لم يُرسل refund، والعميل لا يمكن أن يُحفظ له الإشعار رصيداً |
422 payment_method_not_in_branch | خزينة طريقة الدفع في refund تخدم فرعاً آخر فقط |
422 refund_exceeds_collected | المبلغ المرجع أكثر مما حُصّل على الفاتورة |
422 used_subscription_not_refundable | الفاتورة لاشتراك استُخدمت منه زيارات |
422 refund_method_not_supported | دُفعت الفاتورة ببطاقة عبر المتجر الإلكتروني للتاجر، ولا يمكن بدء استرجاع إلى البطاقة عن طريق الـ API |
422 loyalty_refund_blocked | تعذّر إصدار الإشعار بسبب منصة الولاء: إما أن النقاط أو الأختام المكتسبة من الفاتورة استُخدمت، أو تعذّر الوصول إلى منصة الولاء، أو لم تصلها الفاتورة بعد، والرسالة توضح السبب. أعد المحاولة مرة واحدة بعد دقائق، فإن رُفض مرة أخرى يمكن للتاجر إصداره من لوحة التحكم حيث يستطيع المشرف تجاوز الرفض |
409 reference_id_taken | قيمة referenceId مستخدمة لفاتورة أو إشعار آخر، ويحمل existingId معرّفه فقط إذا كان إشعاراً دائناً يملك مفتاحك صلاحية قراءته |
409 invoice_busy على invoiceId | طلب آخر على الفاتورة نفسها استمر أكثر من 30 ثانية، فأعد إرسال الطلب |
422 zatca_rejected | رفضت الهيئة إشعار الفاتورة الضريبية، ولم يُحفظ أي شيء، ورسائل الهيئة في zatcaErrors |
422 credit_note_not_issued | رفضته قاعدة ليس لها كود خاص، والرسالة توضح القاعدة |
إذا رُفض الطلب فلا يصدر أي إشعار ولا يُحفظ أي شيء.
قراءة الإشعارات الدائنة
يعرض GET /v1/credit-notes كل إشعار دائن صادر في فروع المفتاح، أياً كانت القناة التي أصدرته، ومنها الاسترجاع من نقطة البيع أو من لوحة التحكم، ويوضح createdVia القناة. ويمكن التصفية بـ invoiceId و customerId و branchId و referenceId و issuedAfter و issuedBefore و zatcaStatus.
ولا تظهر في القائمة مرتجعات المبيعات والإشعارات الدائنة التي تُنشأ من شاشات المحاسبة في لوحة التحكم، مع أنها تُحسب من المتبقي على الفاتورة.
وتكون قيمة refund.paymentMethodId هي null إذا لم يحدد الاسترجاع طريقة دفع، وهو الغالب في الاسترجاع من نقطة البيع: فقد أُرجع المبلغ من صندوق الفرع نفسه، أو إلى البطاقة التي دُفعت بها الفاتورة. والاسترجاع من نقطة البيع الموزع بين النقد والبطاقة يظهر استرجاعاً واحداً بمجموع المبلغين.
والاسترجاع الذي صدر قبل أن تُسجَّل أسباب الإشعارات تكون فيه قيمة reason هي cancellation، وهو السبب الذي أُرسل به إلى الهيئة.