Commit Graph

3482 Commits

Author SHA1 Message Date
rohitwaghchaure
9b0e1b61f2 fix: precision issue causing COGS in inter transfer PR (#56420) 2026-06-24 09:50:22 +00:00
Mihir Kandoi
e4e6e52a4d Revert "fix(controllers): case-insensitive employee/lead/bom search ranking on Postgres" 2026-06-23 22:02:17 +05:30
Mihir Kandoi
df6437c49d Merge pull request #56335 from aerele/fix/skip-over-allowance-for-non-stock-items
fix: skip over-allowance qty validation for non-stock items
2026-06-23 19:14:42 +05:30
pandiyan
553b55b2f0 fix: skip qty over-allowance check for non-stock items only 2026-06-23 11:00:15 +05:30
Mihir Kandoi
75030bab0f Merge pull request #56341 from mihir-kandoi/pg-audit6-hard-errors 2026-06-23 10:02:06 +05:30
Mihir Kandoi
bde630b888 fix(controllers): cast idx to varchar in child-row picker for Postgres
get_filtered_child_rows searched child rows by row number with table.idx.like(...). idx is an integer column; frappe maps .like() to ILIKE on Postgres, which has no bigint ILIKE operator ('operator does not exist: bigint ~~* unknown'). Cast idx to string via frappe's Cast_ with 'varchar': a bare CAST(idx AS CHAR) is character(1) on Postgres and silently truncates a two-digit idx (11 -> '1'), dropping the row; CAST(idx AS VARCHAR) keeps the full value, and on MariaDB Cast_ rewrites to CONCAT(idx, '') matching the previous implicit coercion. MariaDB output unchanged. The test builds an order with >10 rows and searches row 11 (fails on Postgres with a char(1) cast).
2026-06-23 09:13:50 +05:30
Mihir Kandoi
dc4eee49cc fix(stock): make the batch-number picker Postgres-correct
The batch-number link picker (get_batch_no) had two Postgres-only defects in
both of its query builders (get_batches_from_stock_ledger_entries and
get_batches_from_serial_and_batch_bundle):

1. GROUP BY. They group by Stock Ledger Entry / Serial-and-Batch-Entry columns
   while selecting un-aggregated Batch-master columns (manufacturing_date,
   expiry_date, search fields). PostgreSQL only accepts that when the Batch
   primary key is in the GROUP BY, so the picker raised GroupingError. Adding
   batch_table.name (equal to the grouped batch_no via the join) keeps the
   group count - and the MariaDB result - unchanged while making it valid.

2. CONCAT over nullable dates. "MFG-"/"EXP-" labels were built with
   Concat("MFG-", manufacturing_date). When the date is NULL, MariaDB CONCAT
   returns NULL but Postgres CONCAT drops the NULL and yields a bare "MFG-"/
   "EXP-". Guard each with Case().when(date.isnotnull(), ...) so a missing date
   is NULL on both engines (matching MariaDB, fixing Postgres).

Both leave MariaDB output unchanged. test_get_batch_no_search_returns_batches
exercises both builders directly and asserts no bare "MFG-"/"EXP-" leaks;
reverting either fix makes it fail on Postgres.
2026-06-23 09:04:43 +05:30
Mihir Kandoi
98e8d5690e fix(controllers): case-insensitive search ranking in employee/lead/bom queries on Postgres
employee_query, lead_query and bom() ranked autocomplete results with a bare
Locate(txt, col) in ORDER BY. frappe maps Locate -> strpos on Postgres, which is
case-sensitive, while MariaDB's LOCATE against a column uses the column's
case-insensitive collation. So the search-dropdown ordering diverged between engines for
mixed-case matches (row count/membership unchanged — the WHERE .like() is already ILIKE).

Wrap both Locate operands in Lower(), matching the sibling item_query/get_project_name
handlers in the same file: a no-op on MariaDB, and case-insensitive (MariaDB-faithful) on
Postgres. The existing test_queries suite stays green on both engines.
2026-06-22 19:01:18 +05:30
Mihir Kandoi
98f5116a09 fix: party specific item doesnt work if there are 2 suppliers with same item 2026-06-22 14:10:45 +05:30
Mihir Kandoi
b129daedc8 refactor(subcontracting): dedup validate_manufacture consumption checks
The `skip_transfer` and transfer branches of `validate_manufacture` ran the
same per-item validation loop — look the row up or throw "not a part of",
check overconsumption, guard against duplicates, record — differing only in
the data source (SCIO Received Item vs Work Order Item), the available-qty
basis, the source-warehouse check (skip_transfer only) and the message text.

Split each branch into a small method that builds a normalised
`{item_code: {consumed_qty, available_qty}}` lookup, and share the loop via
`_validate_customer_provided_consumption`. Branch-specific throw messages are
passed as callbacks so the user-facing strings (and their translations) are
unchanged, and the order in which checks fire is preserved. Also drops the
unused `name` column from the skip_transfer query.

Adds a test for the non-skip-transfer manufacture flow (Material Transfer for
Manufacture -> Manufacture), which exercises the Work Order branch that the
existing suite — all of whose manufacture tests set skip_transfer=1 — never
covered. Full subcontracting-inward suite passes on MariaDB and PostgreSQL.
2026-06-22 09:18:45 +05:30
Mihir Kandoi
23f1fc6235 refactor(subcontracting): use f-string for fg reference search filter
`get_fg_reference_names` built its LIKE filter with old-style
`"%%%s%%" % txt`. Use an f-string (`f"%{txt}%"`) for readability; the value
is still passed as a parameterised filter, so behaviour is unchanged.
2026-06-22 08:00:15 +05:30
Mihir Kandoi
19466b24b0 perf(subcontracting): compute child idx once per insert loop
Each new child row was given `idx=frappe.db.count(...) + 1`, issuing a count
query per inserted row across three insert loops (received items on receipt,
self-procured RM on manufacture, secondary items on manufacture). Compute the
starting index once before each loop and increment a local counter, producing
the same idx sequence with a single count query.
2026-06-22 08:00:15 +05:30
Mihir Kandoi
63c5dccb4b fix(subcontracting): guard empty raw-material list before strict zip
`update_inward_order_received_items_for_manufacture` unpacks
`zip(*item_code_wh.keys(), strict=True)`. When the manufacture entry has no
raw-material rows (all rows are finished/secondary/scrap), `item_code_wh` is
empty and the unpack raises `ValueError: not enough values to unpack`.

Return early when there are no such rows, mirroring the `if secondary_items:`
guard already present in `update_inward_order_secondary_items`.
2026-06-22 08:00:15 +05:30
Mihir Kandoi
8218875733 refactor(subcontracting): fetch customer_warehouse only when needed
In `validate_manufacture`, `customer_warehouse` is read only inside the
`skip_transfer` branch but was fetched unconditionally, wasting a lookup on
the non-skip-transfer path. Move it inside the branch that uses it.
2026-06-22 08:00:15 +05:30
Mihir Kandoi
e422c4d2ab perf(subcontracting): hoist Work Order Item lookup out of transfer loop
`validate_material_transfer` ran the `Work Order Item` query and rebuilt
`wo_item_dict` inside the per-item loop, even though both depend only on
`self.work_order`. For an entry with N customer-provided rows that meant N
identical queries. Build the lookup once before the loop.

`validate_manufacture` already builds the analogous dict once up front, so
this also aligns the two methods.
2026-06-22 08:00:15 +05:30
Mihir Kandoi
a342db38de refactor(subcontracting): drop redundant scio_item_name check
In `update_inward_order_item`, the walrus assignment `scio_item_name :=` is
already part of the truthy `if` condition, so the nested `if scio_item_name:`
is always true. Remove it and dedent the body.
2026-06-22 08:00:15 +05:30
Mihir Kandoi
57f5186dff refactor(subcontracting): hoist ValueWrapper import to module level
`validate_delivery_on_save` imported `pypika.terms.ValueWrapper` inside its
per-item loop, re-running the import on every iteration. Move it to the
module-level imports.
2026-06-22 08:00:15 +05:30
Mihir Kandoi
8fc7cb0117 refactor(subcontracting): drop unused format arg in overconsumption message
The "exceeds quantity available" throw in `validate_manufacture` passes a
third positional arg (`item.transfer_qty`), but the message only has `{0}`
and `{1}` placeholders, so `str.format` silently discards it. Remove the
dead argument; no behaviour change.
2026-06-22 08:00:15 +05:30
Mihir Kandoi
48d49cdcd2 fix(subcontracting): fix format placeholders in FG warehouse validation message
`validate_manufacture` builds its "Target Warehouse for Finished Good must
be same as Finished Good Warehouse ..." message with placeholders `{1}` and
`{2}`, but only passes two positional args (indices 0 and 1). `str.format`
raises `IndexError: Replacement index 2 out of range` instead of rendering
the message, so a user who sets the wrong FG target warehouse gets an opaque
traceback rather than the intended validation error.

Renumber the placeholders to `{0}` and `{1}` to match the args.
2026-06-22 08:00:14 +05:30
Mihir Kandoi
8f1c703871 fix(controllers): keep Supplier trends one row per supplier + add regression tests
The earlier parity fix aggregated the non-key descriptive columns for the Item
and Customer based-on paths but left Supplier grouping by all three selected
columns (supplier, supplier_name, supplier_group). supplier_name is a stored
per-transaction field, so historical purchase docs holding a divergent value for
the same supplier would split one supplier into multiple rows — diverging from
the original MariaDB output, which grouped by t1.supplier only.

Aggregate supplier_name with Max() and keep only supplier + the FD master column
supplier_group in GROUP BY, restoring one row per supplier on both engines.

Add regression tests for the Supplier (purchase) and Customer (sales) paths that
assert a single row per key even when stored descriptive fields diverge; both
fail on the pre-fix multi-column GROUP BY and pass after the fix, on MariaDB and
Postgres.
2026-06-22 00:58:56 +05:30
Mihir Kandoi
dbd1388b40 fix(controllers): keep Sales/Purchase Trends one row per based-on key (MariaDB parity)
#56192 made the trends queries Postgres-strict-GROUP-BY-valid by widening based_on_group_by
to include the selected descriptive columns. For Item it added t2.item_name, for Customer
t1.territory (and customer_name) — but item_name is an editable per-line field and territory an
editable per-document field, not functionally dependent on the item_code/customer key. On MariaDB
(ONLY_FULL_GROUP_BY off) this SPLITS the single row per key into one row per distinct
(key, item_name)/(key, territory), so a customer transacting across two territories (or an item
with an edited item_name) now shows duplicate rows with fractured per-period subtotals.

Group by the KEY only and aggregate the non-key descriptive columns with Max(): one row per
based-on key (identical to the pre-#56192 MariaDB output) and still Postgres-valid. Supplier
columns are master-joined / fetch-locked (functionally dependent) so they stay unchanged.
2026-06-21 22:38:30 +05:30
Mihir Kandoi
dd2f3d42a5 Merge pull request #56231 from mihir-kandoi/pg-rfq-transaction-list
fix(controllers): fix supplier-RFQ portal list query (wrong column + Postgres DISTINCT)
2026-06-21 10:35:33 +05:30
Mihir Kandoi
404d4413b5 Merge pull request #56228 from nishkagosalia/st-71960
fix: disarding stock entry fix
2026-06-21 10:16:42 +05:30
Mihir Kandoi
a7d9078bf4 fix(controllers): fix supplier-RFQ portal list query (wrong column + Postgres DISTINCT)
rfq_transaction_list had two defects introduced when it was converted to the query
builder:

1. `party.supplier == party[0]` compared supplier to a column literally named "0"
   (a stray index on the DocType, not the intended `parties[0]` value). This renders
   as `supplier = \`0\`` / `supplier = "0"` and errors on BOTH engines
   (MariaDB: Unknown column '0'; Postgres: column "0" does not exist), so the
   supplier portal RFQ list was completely broken.
2. SELECT DISTINCT ordered by `creation`, which is not in the select list. Postgres
   rejects this ("for SELECT DISTINCT, ORDER BY expressions must appear in select list").

Compare against `parties[0]` and add `creation` to the select list.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 10:14:42 +05:30
nishkagosalia
debe1855c6 fix: disarding stock entry fix 2026-06-21 09:54:20 +05:30
Mihir Kandoi
598864f0be fix(controllers): make update_variant_attribute_values Postgres-valid (drop UPDATE..JOIN)
update_variant_attribute_values (propagates renamed Item Attribute Values to
variant items) used a qb UPDATE ... JOIN. Postgres has no UPDATE..JOIN syntax,
so renaming an Item Attribute Value errored on Postgres.

Rewrite as a correlated UPDATE that restricts to variant items via a subquery
on the parent (item_variant_table.parent.isin(variant Items)) instead of
joining the Item table. MariaDB behaviour is unchanged.

Covered by the existing test_item.test_rename_attribute_value_updates_variants
and test_swapped_attribute_value_renames_update_variants, which errored on
Postgres before and now pass on both engines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 09:46:43 +05:30
Mihir Kandoi
51448a2bda Merge pull request #56217 from mihir-kandoi/pg-controllers-buying-itemvariant-trends
refactor(controllers): buying_controller + item_variant + trends Postgres validity
2026-06-21 07:58:38 +05:30
Mihir Kandoi
d707fb541d Merge pull request #56216 from mihir-kandoi/pg-controllers-queries
refactor(controllers): queries.py search handlers raw SQL → qb (Postgres)
2026-06-21 07:55:35 +05:30
Mihir Kandoi
025f0db7d7 Merge pull request #56215 from mihir-kandoi/pg-controllers-budget-subcon
fix(controllers): budget GROUP BY + subcontracting bool-OR Postgres validity
2026-06-21 07:52:00 +05:30
Mihir Kandoi
0d8abba0d8 Merge pull request #56214 from mihir-kandoi/pg-controllers-return-stock
refactor(controllers): sales/purchase return + stock_controller raw SQL → qb/ORM (Postgres)
2026-06-21 07:51:13 +05:30
Mihir Kandoi
af2f53bee1 refactor(controllers): convert make_variant_item_code lookup to query builder
make_variant_item_code used a raw frappe.db.sql left join over Item Attribute /
Item Attribute Value. Convert to frappe.qb. The attribute_value comparison
casts the param with cstr() so Postgres does not error on `varchar = numeric`
for numeric attributes (where that side is irrelevant, since numeric_values == 1
already satisfies the OR). MariaDB-identical.

Surgical re-apply: develop's get_attribute_value_renames /
update_variant_attribute_values helpers and the Case import are preserved.
Covered by test_item_variant on both engines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 06:02:29 +05:30
Mihir Kandoi
08f39c5345 refactor(controllers): convert BuyingController raw SQL lookups to ORM
- Asset Movement deletion: raw implicit-join select -> frappe.get_all on
  Asset Movement Item (pluck="parent").
- validate_item_type: raw `name in (...)` select -> frappe.get_all with an
  `in` filter (pluck="item_code").

Both are engine-portable, MariaDB-identical. Surgical re-apply: develop's
actual-tax distribution rewrite (distribute_actual_tax_amount / get_tax_details)
is preserved (the staging branch predated it).

validate_item_type runs on every Purchase Receipt validation (covered by
test_asset.test_purchase_asset on both engines); the Asset Movement deletion
is covered by the asset cancellation flow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 06:02:29 +05:30
Mihir Kandoi
957f9d866a refactor(controllers): convert queries.py search handlers to qb/ORM (Postgres)
Convert eight raw frappe.db.sql search handlers to frappe.qb / frappe.qb.get_query
(which applies user-permission match conditions): employee_query, lead_query,
tax_account_query, bom, warehouse_query, get_batch_numbers, get_purchase_receipts
and get_purchase_invoices. Removes the MySQL-only get_match_cond/get_filters_cond
string building and ifnull usage.

The genuine Postgres break is get_project_name: it used CustomFunction("IF")
which emits a literal IF() (invalid on Postgres). Switch it to Case().

Surgical re-apply (not a whole-file port): develop's case-insensitive
Lower() ordering in item_query and get_project_name is preserved (the staging
branch reverted it), item_query is otherwise left untouched, and the Lower
import is retained.

Existing test_queries tests cover the converted handlers and now pass on
Postgres (test_project_query errors on develop). Adds smoke tests for the
three previously-untested handlers (batch numbers / purchase receipts /
purchase invoices).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 05:50:08 +05:30
Mihir Kandoi
8138f5aecd refactor(controllers): convert StockController future-SLE/GL checks to qb/ORM
- make_gl_entries_on_cancel: raw GL Entry existence select -> frappe.db.exists.
- future_sle_exists: raw GROUP BY count -> frappe.qb Count with Criterion.any,
  and get_conditions_to_validate_future_sle builds qb Criterion objects
  (warehouse == x & item_code.isin(...)) instead of escaped SQL strings.

Parity-preserving and valid on Postgres. Surgical re-apply: develop's
check_item_quality_inspection fix (`return items if doctype == "Stock Entry"
else []`) is preserved (the staging branch predated and would have reverted
it).

Adds a test asserting future_sle_exists detects a later SLE for the same
item/warehouse on both engines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 05:40:30 +05:30
Mihir Kandoi
465446bb79 refactor(controllers): convert sales/purchase return lookups to qb/ORM
validate_returned_items used a raw frappe.db.sql with a string-built column
list (and a separate Packed Item select); get_already_returned_items used a
raw GROUP BY sum. Convert both to frappe.get_all / frappe.qb (Sum(Abs(...))
with an explicit groupby). The qb GROUP BY mirrors the original
`group by item_code, <field>`, so it is parity-preserving (not a behaviour
change) and valid on Postgres.

Surgical re-apply: develop's `is_debit_note = 0` credit-note fix in
make_return_doc is preserved (the staging branch predated and would have
reverted it).

Adds a test (Delivery Note -> sales return) exercising validate_returned_items
and get_already_returned_items on both engines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 05:40:30 +05:30
Mihir Kandoi
147a8672b4 fix(controllers): cast overproduced-qty flag to bool in subcontracting Case
The max-allowed-qty Case used `... | ValueWrapper(allow_delivery_of_overproduced_qty)`
where the flag is an int (0/1). Postgres rejects `OR <integer>` ("argument of
OR must be type boolean"). Wrap it in bool() so the literal renders as
true/false. MariaDB behaviour is unchanged.

Surgical: only the bool() wrap is applied; develop's weighted-average rate
logic and the internal/whitelisted status-helper split are left intact (the
staging branch predated both).

Covered by test_subcontracting_inward_order.test_over_production_delivery,
which now passes on Postgres and is unchanged on MariaDB.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 05:28:12 +05:30
Mihir Kandoi
f95e32a581 fix(controllers): make budget requested-amount aggregate Postgres-valid
The Material Request requested-amount query selects
`Sum(stock_qty - ordered_qty) * mri.rate` -- an implicit aggregate with no
GROUP BY, where mri.rate is neither grouped nor aggregated. MariaDB
arbitrary-picks the rate; Postgres rejects it ("must appear in the GROUP BY
clause"). Wrap the rate in Max(mri.rate) so the SELECT is a pure aggregate.

Behaviour note: for matched MR items with differing rates, Max() picks the
highest (vs MariaDB's arbitrary single rate). The underlying Sum(qty) * rate
is a pre-existing single-rate aggregation; this preserves it under the
accepted arbitrary-pick convention.

Covered by erpnext.accounts.doctype.budget.test_budget
.test_monthly_budget_crossed_for_mr, which now passes on Postgres (it errors
on develop) and is unchanged on MariaDB.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 05:28:11 +05:30
Mihir Kandoi
c4d2228b36 refactor(controllers): convert website_list_for_contact currency lookup to ORM
get_list_context built the enabled-currency symbol map with a raw
frappe.db.sql select. Convert to frappe.get_all (as_list). MariaDB-identical.

Adds a test asserting the currency-symbol map is built and contains a known
enabled currency, on both engines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 05:18:58 +05:30
Mihir Kandoi
083858d450 refactor(controllers): make StatusUpdater Postgres-valid (ifnull→coalesce, raw SQL→qb)
- Replace MySQL-only `ifnull(...)` with `coalesce(...)` in the two
  source/second-source percentage subqueries that remain raw (they
  interpolate dynamic table/field names).
- zero_amount_refdocs: raw `sql_list` → `frappe.get_all(pluck="name")`.
- update_billing_status: two raw `ifnull(sum(qty), 0)` selects → frappe.qb
  `Sum`; an empty result yields None and flt(None) == 0, matching the old
  ifnull behaviour.

Behaviour is unchanged on MariaDB. The percentage path (coalesce subquery)
is exercised by test_selling_controller's Sales Order -> Delivery Note
per_delivered test on both engines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 05:10:19 +05:30
Mihir Kandoi
f793027800 refactor(controllers): convert SellingController delivered-qty lookups to qb/ORM
get_already_delivered_qty used two raw frappe.db.sql sums (Delivery Note
Item, and Sales Invoice Item joined to Sales Invoice) and
get_so_qty_and_warehouse used a raw select. Convert to frappe.qb (Sum) and
frappe.db.get_value. Engine-portable and MariaDB-identical.

Adds a test (Sales Order -> partial Delivery Note) that asserts
per_delivered, exercising get_already_delivered_qty / get_so_qty_and_warehouse
(and the StatusUpdater percentage path) on both engines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 05:10:17 +05:30
rohitwaghchaure
8479a8b4d3 Merge pull request #56102 from rohitwaghchaure/feat-allocate-full-amount-to-stock-items
feat: allocate full actual charge to stock items only (e.g. Freight)
2026-06-19 18:05:18 +05:30
Rohit Waghchaure
9e15e52847 feat: allocate full actual charge to stock items only (e.g. Freight)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 16:35:45 +05:30
Mihir Kandoi
02f7cba20a Merge pull request #55920 from ljain112/fix-scio-customer-material-avg-rate
fix: update weighted average rate calculation to consider returned and consumed quantities
2026-06-19 14:47:16 +05:30
barredterra
0e244dd83a fix(stock): update variant attributes on value rename
(cherry picked from commit c7acd88742)
2026-06-18 17:05:40 +00:00
barredterra
4806b82add fix(stock): propagate renamed attribute values to variant items
(cherry picked from commit 27d574dad5)

# Conflicts:
#	erpnext/stock/doctype/item_attribute/item_attribute.py
2026-06-18 17:05:40 +00:00
Mihir Kandoi
c4e1fe274b Merge pull request #56055 from aerele/fix/support-71415
fix: disable is_debit_note while creating credit note
2026-06-18 22:23:39 +05:30
Mihir Kandoi
cfa6d286ad fix(postgres): other-class parity fixes (case-folding & null-ordering) for merged queries
Parity sweep findings in queries already merged in develop:

- pos_invoice.py: serial_no return-match matched case-sensitively on Postgres (case-insensitive
  on MariaDB). Replaced the get_all or_filters lookup with a qb query that case-folds both sides
  via Lower() (no-op on MariaDB).
- controllers/queries.py + pick_list.py: the Locate()-based relevance ranking in link-query
  ORDER BY is case-sensitive on Postgres (Strpos) vs case-insensitive on MariaDB (Locate), so
  autocomplete order differed. Lower() both arguments so the ranking matches on both engines.
- crm/lead_conversion_time.py: "first contact" used ORDER BY communication_date LIMIT 1 read by
  index; a NULL date sorts first on MariaDB but last on Postgres, changing the result. Added
  `communication_date IS NOT NULL` so both engines return the earliest real contact date.

Verified on MariaDB and Postgres: test_pick_list 40/40, test_pos_invoice 26/26 on both engines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 20:36:30 +05:30
pandiyan
279c8dea06 fix: disable is_debit_note while creating credit note 2026-06-17 18:35:10 +05:30
Mihir Kandoi
4ba042c7c7 fix(postgres): compare Check fields with == 1 in accounts controller CASE/condition
disable_rounded_total and is_pos are smallint Check fields; postgres rejects
using them as bare boolean conditions in CASE WHEN / bitwise-AND, so compare
explicitly against 1. No-op on MariaDB.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 16:09:00 +05:30
ruthra kumar
59a69fc497 refactor(test): broken test case in accounts controller 2026-06-17 10:22:00 +05:30