Skip to content

v16 handles tax differently than v15 #255

Description

@dvdl16
  v15 (get_item_details.py:768): get_item_tax_map(company, item_tax_template, ...) builds the map only from the Item Tax Template. The document's own taxes rows never enter it, so two rows sharing "VAT - SC" can't collide — the "On
  Net Total" row keeps rate 15. 
  
  v16 (get_item_details.py:850-854): the signature changed to get_item_tax_map(doc=..., tax_template=...) and it now seeds the map from doc.taxes (item_tax_map[account_head] = rate, last-write-wins) before layering the template on
  top. That's the new line that lets the Actual shipping row (rate None) clobber the VAT row's 15 to 0.

  Reference summary

  ┌──────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  │                          │                                                                                                         │
  ├──────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Trigger                  │ update_item_tax_map → get_item_tax_map(doc=self.doc, ...) — taxes_and_totals.py:143-149                 │
  ├──────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Root cause               │ get_item_tax_map last-write-wins on account_head — erpnext/stock/get_item_details.py:852-854 (v16 only) │
  ├──────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Where the 0 is read back │ _get_tax_rate returns the poisoned item_tax_map["VAT - SC"] = 0 — taxes_and_totals.py:384-388           │
  ├──────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Net effect               │ "On Net Total" VAT row computes at rate 0 in calculate_taxes (line 616), never reaching 15              │
  ├──────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ v15 contrast             │ get_item_tax_map(company, item_tax_template) — template-only, no doc.taxes — get_item_details.py:768    │
  └──────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  
  The mechanism I originally stated ("v16 zeros the computed row when accounts collide") was directionally right but wrong about how — it's not a post-hoc zeroing, it's the per-item rate map being poisoned to 0 before computation.
  The fix implication is the same as before (don't emit a second "VAT - SC" row), but now we know any fix that keeps two rows on one account is futile on v16 — the duplicate account itself is what breaks it.


● There are two line-item-tax paths and shipping always uses f_n_f_tax_account:
  - Template path (enable_tax_lines_sync && not use_actual_tax_type): VAT account is inside the sales_taxes_and_charges_template rows.
  - Actual path (use_actual_tax_type): VAT account is wc_server.tax_account.
  

● The collision only breaks the template path (not use_actual_tax_type), because that's the only path that produces a computed "On Net Total" row. In actual-tax mode every line is
  "Actual" (rate unused), so duplicate accounts there are harmless. So the v16 requirement only needs to apply when a tax template is in use.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions