Commit Graph

59089 Commits

Author SHA1 Message Date
Mihir Kandoi
b4aae9dea1 fix(crm): render Lead Details address consistently across engines
The Lead Details report concatenated address_line1 and address_line2 with
CONCAT_WS. An unfilled optional Data field is stored as '' on MariaDB but as
NULL on PostgreSQL; CONCAT_WS keeps the empty string (leaving a trailing
", ") on MariaDB while Postgres drops the NULL, so the same lead rendered a
different address on each engine.

Wrap both parts in NULLIF(part, '') so empty values are treated as NULL on
both engines: the report now produces the same clean address (no trailing
separator) everywhere.
2026-06-23 08:58:30 +05:30
Mihir Kandoi
295dec24db fix(stock): group get_picked_batches by batch and warehouse
get_picked_batches summed Serial-and-Batch-Entry qty while selecting bare
batch_no and warehouse with no GROUP BY. PostgreSQL rejects this outright:

    column "tabSerial and Batch Entry.batch_no" must appear in the GROUP BY clause

MariaDB does not error but collapses every picked row into a single result -
the grand-total qty pinned to one arbitrary batch - so the caller, which keys
the result by (batch_no, warehouse) to subtract already-picked stock, under-counts
whenever more than one batch is picked.

Add GROUP BY batch_no, warehouse so the query returns one correct row per batch
on both engines (this corrects the MariaDB result, not just Postgres validity).
2026-06-23 08:58:29 +05:30
Mihir Kandoi
ff737df55f Merge pull request #56336 from mihir-kandoi/pg-lint-distinct-orderby
ci(postgres): flag get_all(distinct=True, order_by=...) in the static checker
2026-06-22 23:42:11 +05:30
Mihir Kandoi
50c4ee4ccb Merge pull request #56334 from mihir-kandoi/pg-irs1099-payer-tiebreak
fix(regional): deterministic IRS-1099 payer-address pick across engines
2026-06-22 23:32:53 +05:30
Mihir Kandoi
ad237e5ec5 ci(postgres): flag get_all(distinct=True, order_by=...) in the static checker
frappe's db_query SILENTLY drops ORDER BY for distinct queries on Postgres (the ORDER BY
column must appear in the SELECT-DISTINCT list), so `get_all/get_list(distinct=True,
order_by="<col>")` is a no-op there and the result comes back unordered — the root cause of
the Sales Register, Purchase Register and Sales Analytics ordering fixes. Add an AST rule to
.github/helper/postgres_compat.py that flags this (literal order_by only; an empty order_by=""
suppression and a dynamic/variable order_by are not flagged). `# pg-ok` escape hatch as usual.

Grandfather the three pre-existing low-impact sites the rule surfaces (paging/iteration order
only, not data): job_card operation autocomplete, inventory_dimension config list, and a
work_order test loop.
2026-06-22 23:22:52 +05:30
Mihir Kandoi
fadad2d1c4 fix(regional): deterministic IRS-1099 payer-address pick across engines
get_payer_address_html picks one company address with ORDER BY (Postal DESC, Billing DESC)
LIMIT 1 and no column tie-break. When a company has two addresses of the same address_type
the two CASE keys tie, so the LIMIT-1 row is implementation-defined and MariaDB and PostgreSQL
can return a different address.name — i.e. a different payer address on the rendered IRS-1099
form for identical data.

Add a final .orderby(address.name), mirroring the sibling get_street_address_html in the same
file (which already carries the "deterministic LIMIT-1 tie-break across engines" order). The
pick is now the lexicographically-smallest name on both engines.
2026-06-22 23:13:29 +05:30
Mihir Kandoi
f026d1dac8 Merge pull request #56329 from mihir-kandoi/pg-sales-analytics-order
fix(selling): deterministic Sales Analytics order-type row order on both engines
2026-06-22 20:02:27 +05:30
Mihir Kandoi
a1ed913eba fix(selling): deterministic order-type row order in Sales Analytics on both engines
get_teams fetched distinct order_types with get_all(distinct=True, order_by="order_type").
frappe drops ORDER BY for distinct queries on postgres (db_query), so the order_by is a
no-op there and the report's order-type leaf rows are not guaranteed any order on PG
(PostgreSQL only sorts them incidentally via its DISTINCT plan). Sort in python with
key=str.casefold instead, matching MariaDB's case-insensitive collation and guaranteeing
an identical, stable order on both engines (same pattern as the Sales/Purchase Register
account-column fix). Add a test locking the sorted order-type row order.
2026-06-22 19:42:37 +05:30
Mihir Kandoi
3ed305c75c Merge pull request #56330 from mihir-kandoi/pg-queries-locate-case
fix(controllers): case-insensitive employee/lead/bom search ranking on Postgres
2026-06-22 19:30:02 +05:30
Mihir Kandoi
da4cf77d97 Merge pull request #56328 from mihir-kandoi/pg-pos-item-group-escape
fix(pos): restore item-group filtering broken by double-escaped names
2026-06-22 19:23:58 +05:30
Raffael Meyer
13f9130d42 fix: hide redundant company currency fields on transactions (#54691) 2026-06-22 15:37:29 +02:00
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
32216bd75b fix(pos): return raw Item Group names from get_item_groups (double-escape regression)
The Postgres-portability change moved the POS item-group filters to the query builder
(item.item_group.isin(...)) and frappe.get_all(["name","in",...]), which escape values
once. get_item_groups() still pre-escaped each name with frappe.db.escape(), so the
names were escaped TWICE -> `item_group IN ('''Products''')`, matching nothing. Any POS
Profile that restricts item groups returned ZERO items, on both MariaDB and Postgres.

Return raw names; the parameterized callers escape them correctly. (get_parent_item_group
also returned the quoted literal before this fix.) Add a regression test: a POS Profile
restricted to an item group must still surface that group's items — it returns 0 before
the fix and passes after, on both engines.
2026-06-22 19:00:35 +05:30
Nabin Hait
d694ad9428 Merge pull request #56293 from nabinhait/fix-lead-name-none-email
fix(lead): don't crash deriving lead name when only ignore_mandatory is set
2026-06-22 18:17:16 +05:30
Nabin Hait
a120bf8363 Merge pull request #56286 from nabinhait/ci-patch-test-no-workers-during-migrate
ci: don't run background workers during patch-test migrate
2026-06-22 17:05:15 +05:30
Nabin Hait
d48cffd1a5 Merge pull request #56303 from nabinhait/test-blanket-order-multirow
test(blanket_order): cover over-ordering aggregated across rows
2026-06-22 17:04:35 +05:30
Mihir Kandoi
624844d52f Merge pull request #56308 from mihir-kandoi/gh55802
fix: submittable product bundle issues
2026-06-22 16:15:59 +05:30
Nishka Gosalia
c24fc063fc Merge pull request #56309 from nishkagosalia/migrating-document-naming-setting
fix: Removing the document naming series dialog and moving to framework
2026-06-22 16:07:08 +05:30
Nabin Hait
43d2c7335d refactor(lead): name the loops in remove_link_from_prospect
The outer and inner loops both used 'd'; name them linked_prospect and lead
so the prospect/lead iteration reads clearly. No behaviour change.
2026-06-22 15:59:26 +05:30
Nabin Hait
8f69697212 fix(lead): don't crash deriving lead name when only ignore_mandatory is set
set_lead_name fell through to email_id.split('@') when a lead had no name,
company or email but ignore_mandatory was set (e.g. data import), raising
AttributeError on a None email. Only derive from email when one exists; the
lead name is then left blank, as intended for that path.
2026-06-22 15:59:25 +05:30
Nabin Hait
3f832d4ee0 Merge pull request #56247 from nabinhait/commission-rate-data-to-percent
fix(selling): make commission_rate a Percent field on Sales Person and Sales Team
2026-06-22 15:56:30 +05:30
Mihir Kandoi
d48a1e0d16 fix: address product bundle review comments 2026-06-22 15:53:52 +05:30
nishkagosalia
aa7402b1e3 fix: removing the document naming series dialog and moving to framework 2026-06-22 15:46:15 +05:30
Mihir Kandoi
a218b8db8c fix: submittable product bundle issues 2026-06-22 15:40:16 +05:30
rohitwaghchaure
9b8c363bed feat: capitalize full actual charge on stock items only for Purchase Invoice (#56223)
* feat: capitalize full actual charge on stock items only for Purchase Invoice

Extends #56102 (Purchase Receipt) to the Purchase Invoice GL: an actual
valuation charge (e.g. Freight) flagged 'Allocate Full Amount to Stock Items'
is fully capitalized onto stock/asset items only; when unchecked, only the
stock items' share of a spread-across-all-items charge is capitalized.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test: aggregate GL rows per account in PI freight test

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 15:39:10 +05:30
Mihir Kandoi
23bbcca97e Merge pull request #56306 from frappe/codex/fix-address-portal-row
fix: link portal address rows to web form
2026-06-22 15:29:20 +05:30
Mihir Kandoi
5008b82f90 fix: link portal address rows to web form 2026-06-22 15:19:40 +05:30
Nabin Hait
9436ab7f19 Merge pull request #56294 from frappe/chore/subcontracting-test-coverage
test: Subcontracting coverage; fix service-cost mismatch by PO item
2026-06-22 15:08:34 +05:30
Nabin Hait
c38bab7e5e Merge pull request #56302 from nabinhait/test-coupon-code-validation
test(coupon_code): cover coupon validation and usage-count edges
2026-06-22 15:07:10 +05:30
Mihir Kandoi
eafb0019bf Merge pull request #56300 from mihir-kandoi/fix-party-specific-item
fix: party specific item doesnt work if there are 2 suppliers with sa…
2026-06-22 14:57:09 +05:30
Nabin Hait
943c6d210a fix: only rewrite commission_rate rows the column change can't cast
The previous string comparison (str(raw) != str(cleaned)) rewrote every
whole-number row ('20' vs '20.0'), turning a targeted cleanup into a
full-table rewrite on Sales Team. Skip rows already holding a plain numeric
string and only fix NULL / empty / non-numeric / percent-sign values.
2026-06-22 14:28:29 +05:30
Nabin Hait
0b1d06d46d fix: handle percent-sign commission rates in migration patch
Values like "20%" or "20 %" parse to 0 via flt, which would wipe a real
rate. Strip a trailing percent sign before parsing so they migrate as 20.
2026-06-22 14:28:29 +05:30
Nabin Hait
2fe0601a2e fix(selling): make commission_rate a Percent field on Sales Person and Sales Team
commission_rate was a free-text Data field on the Sales Person master and the
Sales Team child, storing percentages as strings. Convert both to Percent.

A pre_model_sync patch sanitizes the existing values first (empty / NULL /
non-numeric -> 0, others normalised via flt) so the Data -> Percent column
change casts cleanly under strict SQL mode, where Percent is a NOT NULL
decimal column. The patch is idempotent and avoids db-specific SQL so it works
on both MariaDB and Postgres.
2026-06-22 14:28:28 +05:30
Nabin Hait
c5ff32aa2f refactor: tidy update_coupon_code_count
Drop the dead 'if coupon:' guard (get_doc would have thrown) and collapse the
duplicate increment branches into a single exhausted-check plus increment.
No behaviour change.
2026-06-22 14:27:16 +05:30
Mihir Kandoi
7d205c89ea test: add test case 2026-06-22 14:26:28 +05:30
Nabin Hait
8cb94ebedb test: avoid needless submit in SCO validation tests
Use do_not_submit=1 for the service-item and reserve-warehouse validation
tests; they only exercise in-memory validation methods, so submitting the
Subcontracting Order is unnecessary.
2026-06-22 14:25:34 +05:30
Nabin Hait
afed7884d4 test(blanket_order): cover over-ordering aggregated across rows
The over-order check sums the same item across multiple order rows. Add a
test where one item is split into two Sales Order rows against the same
blanket order and together exceed its quantity.
2026-06-22 14:23:41 +05:30
Nabin Hait
bcd850c808 Merge pull request #56240 from nabinhait/test-sales-commission-contribution
test(sales_order): cover sales partner commission and sales-team contribution
2026-06-22 14:20:47 +05:30
Nabin Hait
eaab71a99e test(coupon_code): cover coupon validation and usage-count edges
Add tests for the previously-untested branches of validate_coupon_code
(not-yet-valid, expired, maximum-use exhausted) and update_coupon_code_count
(releasing a use on cancel, and rejecting use beyond the maximum). Both
functions are now fully covered.
2026-06-22 14:20:41 +05:30
Nabin Hait
324f72ce4d Merge pull request #56156 from nabinhait/refactor-so-reservation
refactor(sales_order): simplify create_stock_reservation_entries
2026-06-22 14:18:08 +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
Nabin Hait
b4c9827318 Merge pull request #56295 from nabinhait/test-lead-coverage
test(lead): cover lead details and prospect sync/unlink
2026-06-22 14:05:35 +05:30
Nabin Hait
95b82eeba8 Merge pull request #56290 from nabinhait/test-opportunity-lost-flow
test(opportunity): improve coverage (lost flow, auto-close, item details, prospect sync)
2026-06-22 14:05:06 +05:30
Nabin Hait
b26c09ce8a Merge pull request #56238 from frappe/chore/supplier-scorecard-test-coverage
test: Supplier Scorecard coverage + fix standing/on-time shipment bugs
2026-06-22 14:04:18 +05:30
Nabin Hait
19ba681e16 Merge pull request #56296 from nabinhait/opportunity-auto-close-default-days
fix(crm): drive opportunity auto-close days from CRM Settings, not a hardcoded fallback
2026-06-22 14:04:00 +05:30
Nabin Hait
1b3cde9d44 fix: minor fix in test
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-06-22 13:23:02 +05:30
Nabin Hait
daee9cc89c test(sales_order): cover sales partner commission and sales-team contribution
The parent Commission section (Sales Partner commission) and the Sales Team
table (Sales Person contribution) drive separate logic in
SellingController.calculate_commission / calculate_contribution. Add
integration tests on Sales Order:
- sales partner commission: total_commission = eligible amount * rate / 100,
  and the commission-rate 0..100 bound;
- sales-person allocated_amount tracks amount_eligible_for_commission
  (grant_commission gated), not gross net_total, plus the incentive math;
- the allocated-percentage must-total-100 throw;
- rejection of a disabled sales person.
2026-06-22 13:23:02 +05:30
Nabin Hait
ee0635246f refactor(sales_order): simplify create_stock_reservation_entries
The method (cyclomatic complexity C/14) mixed packed-item separation, SRE
creation and packed-item reservation. Extract _extract_packed_item_details,
_packed_items_to_reserve and _reserve_packed_items (verbatim moves). Drops
C/14 -> A/3; no C-rank function remains in the module. No behaviour change
(stock-reservation, product-bundle and pick-list reservation suites green).
2026-06-22 13:21:31 +05:30
ruthra kumar
4ba1f5214e Merge pull request #55488 from Shllokkk/authorise-set-status
fix: add validation and tests for set_status
2026-06-22 13:19:52 +05:30
Nabin Hait
fc0dee5730 Merge pull request #56291 from frappe/chore/rfq-sq-test-coverage
test: RFQ + Supplier Quotation coverage; fix broken SQ expiry task
2026-06-22 13:10:19 +05:30