Skip to content

fix: Update the retentions#160

Merged
maniamartial merged 6 commits into
developfrom
fix/retention
Jun 4, 2026
Merged

fix: Update the retentions#160
maniamartial merged 6 commits into
developfrom
fix/retention

Conversation

@maniamartial

@maniamartial maniamartial commented May 18, 2026

Copy link
Copy Markdown
Contributor
  1. Retention GL was always added on submit
    make_retention_gl_entry ran whenever retention fields were filled in.

  2. Customer GL was never reduced
    make_customer_gl_entry always debited the full grand_total, because nothing reliably lowered it for posting.

  3. Broken server logic
    The old set_grand_total_with_retention hook only patched tax calculation after ERPNext had already recalculated totals, and it never ran that calculation again. So on every save, grand_total was reset to the full tax total and retention was never subtracted server-side.

What we changed (in one sentence)

We stopped trying to shrink grand_total (so ZATCA still sees the full amount), and instead:

  • Customer GL debits grand_total − retention
  • Outstanding is grand_total − retention for payments
  • Retention GL still debits the held amount

Now both sides of the journal add up to 22,698.20 while ZATCA keeps reporting the full invoice total.

@maniamartial

Copy link
Copy Markdown
Contributor Author

ZATCA Integration – Changes Summary (24 May 2026)

1. Foreign Company Buyers (Non–Saudi Arabia)

Problem

Foreign company customers could not submit invoices without Saudi VAT or registration details, even though ZATCA export rules do not require them.

Changes

  • Added is_foreign_customer() and validate_company_buyer_identification() in common_util.py.
  • For foreign companies:
    • Saudi VAT is optional
    • Registration scheme is optional
    • Registration number is optional
  • Saudi companies remain unchanged and still require:
    • VAT / tax_id, or
    • both registration scheme and registration number

XML Behaviour

  • Buyer VAT is omitted when the buyer country is not Saudi Arabia.
  • PartyIdentification is only included when both registration scheme and registration number are provided.

Note

ZATCA may still return warning BR-KSA-81 when:

  • Buyer VAT (BT-48) is missing, and
  • Other Buyer ID (BT-46) is not included.

Invoice clearance can still succeed with a warning.

Additional Fix

Fixed Saudi building-number validation in get_buyer_information():

  • "sa""SA"

2. BR-KSA-81 Follow-Up (Reverted)

Attempted

  • Export flag on KSA-2 (0100100)
  • Automatic OTH buyer ID generation
  • Warning alert for missing foreign IDs

Result

Reverted after BR-KSA-81 warnings during clearance.

Retained

Only the foreign-customer validation relaxation from Section 1 was kept.


3. Sales Retention Recalculation When Line Items Change

Problem

Retention amount updated when the retention percentage changed, but not when item quantities, rates, or totals changed.

Cause

set_retention_amount only ran on percentage change.

Changes

sales_invoice.js

  • Added automatic recalculation:
    calculate  sync_retention_amount  set_retention_amount

set_retention_amount

  • Uses:
    net_total × percentage / 100
  • Updates base retention amount when exchange rate exists.

Loop Protection

  • Added:
    frm._updating_retention

sales_invoice.py

  • Added:
    sync_retention_from_percentage()
    on validate/save/API flows.

hooks.py

Validate hook order:

  1. sync_retention_from_percentage
  2. set_base_retention_amount
  3. adjust_outstanding_for_retention

Behaviour

  • Percentage-based retention now follows line and total changes automatically.
  • Manual amount-only retention remains unchanged.

4. Invoice Line Amounts in ZATCA XML

(BR-KSA-EN16931-11, BR-DEC-23, BR-S-08)

Problem

Invoices with:

  • multiple quantities, or
  • rates with more than 2 decimals

generated XML inconsistencies between:

  • BT-131 (line net amount)
  • BT-146 (unit price)

This triggered warnings such as:

  • BR-KSA-EN16931-11
  • BR-DEC-23
  • BR-S-08

Changes

File:

generate_final_xml.py

Section:

item_data

New Logic

  • Unit price is rounded to 2 decimals.
  • Line net amount is calculated as:
    qty × unit_price
    rounded to 2 decimals.

This ensures:

BT-131 = BT-129 × BT-146

Reconciliation

  • Total line amounts are reconciled against ERPNext totals.
  • Any rounding difference is applied to the final eligible line.

VAT Handling

  • VAT and rounding amounts are now derived from the adjusted line net amounts.
  • All monetary line fields are written using 2 decimal places.

@maniamartial maniamartial merged commit d14d160 into develop Jun 4, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant