Commit Graph

2740 Commits

Author SHA1 Message Date
Soham Kulkarni
3eaea74a51 Merge pull request #56656 from sokumon/revamp-workspaces
chore: exporting workspaces with sidebars
2026-07-02 05:39:24 +05:30
Nikhil Kothari
bbc4d2ccab feat: capture user persona during setup (#56705) 2026-07-01 11:51:15 +00:00
sokumon
088b8ff69b fix: remove roles from home workspace 2026-07-01 14:22:43 +05:30
rohitwaghchaure
58e5755780 fix: manufacturing variance for standard cost valuation (#56684) 2026-07-01 14:04:14 +05:30
Venkatesh
3b0e1fbb79 fix: remove translation for filter (#56629)
Co-authored-by: SowmyaArunachalam <sowmyaarunachalam57@gmail.com>
2026-06-30 14:52:11 +02:00
sokumon
55afd95b20 fix: remove duplicate links from export 2026-06-30 17:24:58 +05:30
sokumon
5a32866b93 chore: export more workspaces 2026-06-30 17:00:54 +05:30
Mihir Kandoi
bd57e43446 fix(setup): scope regional-tax-settings rollback to a savepoint (review)
from_detailed_data inserts tax templates/accounts before update_regional_tax_settings in the same transaction; a full frappe.db.rollback() on regional-setup failure discarded those templates while the wizard continued. Take a savepoint before the regional call and roll back only to it.
2026-06-30 12:17:38 +05:30
Mihir Kandoi
44458b0ba5 fix(setup): rollback before logging in update_regional_tax_settings (Postgres)
Regional tax-template setup writes docs; on failure the except calls frappe.log_error with no rollback -> InFailedSqlTransaction on Postgres. Full rollback before log_error. No-op on MariaDB.
2026-06-29 22:42:49 +05:30
Mihir Kandoi
8c0b4a99cf fix(setup): rollback before logging in install_country_fixtures (Postgres)
Regional fixture setup writes docs; on failure the except calls frappe.log_error before frappe.throw with no rollback -> InFailedSqlTransaction on Postgres. Full rollback before log_error. No-op on MariaDB.
2026-06-29 22:42:48 +05:30
Mihir Kandoi
91dae91769 fix(setup): deterministic tiebreaker in get_exchange_rate Currency Exchange lookup (Postgres)
get_exchange_rate orders Currency Exchange by 'date desc' LIMIT 1 with no unique tiebreaker. Currency Exchange autoname {date}-{from}-{to}-{purpose} allows multiple same-date rows (different purpose) for one currency pair; on the no-purpose-filter path all match, so MariaDB and Postgres can return a different exchange_rate for the same inputs. Add 'name desc' so both engines pick the same row. MariaDB row count unchanged.
2026-06-29 22:25:39 +05:30
Mihir Kandoi
56a7ee6346 fix: delete Lead-linked Addresses on transaction deletion
The lead/address cleanup pre-escaped each address name before passing the
list into a query-builder .isin() filter, which escapes again. The
double-escaping produced `name IN ('''Addr''')`, matching nothing, so
Lead-linked Addresses were never deleted on either MariaDB or Postgres.

Pass the raw list straight into .isin() so the builder escapes once.
2026-06-29 15:10:24 +05:30
rohitwaghchaure
6c38856f65 feat: Standard Valuation Rate (#56570)
* feat: standard rate valuation

* fix: greptile comments

* fix: PPV account should be mandatory for standard cost valuation
2026-06-28 20:35:01 +05:30
Mihir Kandoi
0583349ae4 test: convert aggregate/pluck/positional raw SQL to ORM
A deeper re-audit (with an adversarial skeptic) of the queries left raw
in the prior commit found more that have exact ORM equivalents:

- scalar SUM/MAX  -> frappe.qb + Sum/Max .run()[0][0]
- SUM ... GROUP BY -> frappe.qb .groupby().select(Sum().as_()) run(as_dict)
- name IN (values) -> get_all(filters={'f': ['in', ...]})
- sql_list(select col) -> get_all(pluck='col')
- bulk UPDATE ... = NULL/value -> frappe.db.set_value(filters, field, val)
- positional as_list reads -> get_all(..., as_list=True) (+ sorted())

Note: get_value(dt, filters, 'sum(x)') and get_all(fields=['sum(x)'])
are rejected by frappe ('SQL functions are not allowed as strings'), so
aggregates go through frappe.qb. get_all(as_list=True) returns a tuple
(not a list), so consumers that mutate use sorted().

All affected test modules pass on MariaDB.
2026-06-26 11:34:31 +05:30
Mihir Kandoi
27a7ec82c2 Merge pull request #56471 from mihir-kandoi/messages/setup
chore: rewrite user-facing messages in setup module
2026-06-25 17:54:53 +05:30
Mihir Kandoi
d451eddac2 chore: rewrite user-facing JS messages in Setup module
Conservative cleanup of frappe.throw/msgprint messages per the message style
guide; meaning, severity, and .format() arguments are unchanged:

- index bare {} placeholders as {0}/{1}/... so translators can reorder
- move f-strings / .format() / concatenation out of _() (they break gettext
  extraction and never translate)
- wrap translatable dynamic values (DocType/Select labels) in _()
- fix grammar and colloquialisms
- drop no-op _() wrapping runtime-built strings

Part of #53976.
2026-06-25 17:37:59 +05:30
Mihir Kandoi
4b8b52b908 chore: rewrite user-facing messages in Setup module
Conservative cleanup of frappe.throw/msgprint messages per the message style
guide; meaning, severity, and .format() arguments are unchanged:

- index bare {} placeholders as {0}/{1}/... so translators can reorder
- move f-strings / .format() / concatenation out of _() (they break gettext
  extraction and never translate)
- wrap translatable dynamic values (DocType/Select labels) in _()
- fix grammar and colloquialisms
- drop no-op _() wrapping runtime-built strings

Part of #53976.
2026-06-25 17:36:55 +05:30
Mihir Kandoi
460b8c5d8d refactor: parse native JSON request args in setup/doctype/terms_and_conditions/terms_and_conditions.py
Use frappe.parse_json instead of json.loads so the whitelisted endpoints
accept native JSON types (list/dict/bool) in addition to JSON strings.
2026-06-24 20:37:34 +05:30
Mihir Kandoi
76705dd736 refactor: parse native JSON request args in setup/doctype/holiday_list/holiday_list.py
Use frappe.parse_json instead of json.loads so the whitelisted endpoints
accept native JSON types (list/dict/bool) in addition to JSON strings.
2026-06-24 20:37:34 +05:30
Mihir Kandoi
78f38970c1 refactor: parse native JSON request args in setup/doctype/department/department.py
Use frappe.parse_json instead of json.loads so the whitelisted endpoints
accept native JSON types (list/dict/bool) in addition to JSON strings.
2026-06-24 20:37:34 +05:30
Mihir Kandoi
8bd8b28207 fix: exclude virtual child doctypes from deletion in transaction deletion record 2026-06-24 14:57:35 +05:30
Mihir Kandoi
abe9e8becc fix(setup): use the stored lower-case fieldname in the Sales Person lookup (Postgres)
deactivate_sales_person looks up `frappe.db.get_value("Sales Person",
{"Employee": employee})`. The Sales Person field is `employee` (lower case);
the lookup runs with ignore_permissions, so the capital-cased key reaches the
query as the column `"Employee"`. PostgreSQL matches quoted identifiers
case-sensitively and errors:

    column "Employee" does not exist

MariaDB resolves `Employee` to the `employee` column regardless of case, so
using the stored `{"employee": employee}` selects the same row on MariaDB and
is valid on PostgreSQL.
2026-06-23 18:45:27 +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
Mihir Kandoi
bac4f1de52 fix(postgres): savepoint bank-account creation during company setup
create_bank_account() inserts a bank Account and swallows DuplicateEntryError
('bank account same as a CoA entry'). On Postgres the failed insert aborts the
transaction, so the rest of company setup ran against a poisoned transaction.
Take a savepoint and roll back to it in the handler. No-op on MariaDB.
2026-06-21 15:48:37 +05:30
Mihir Kandoi
8a5f659681 test(postgres): make test-helper SQL Postgres-valid across the suite
The repo-wide query audit fixed runtime/source queries, but test files carry their
own raw SQL helpers that were never swept and only fail when the suite runs on
Postgres. Port the staging branch's already-green fixes for them:

- timestamp(posting_date, posting_time) (raw + qb Timestamp) -> posting_datetime /
  CombineDatetime (test_stock_ledger_entry, test_stock_balance, test_utils)
- HAVING <select-alias> -> qb .having(<expr>) (test_asset_capitalization, test_purchase_order)
- capital-cased identifiers ("Status", "Name") -> lowercase (test_delivery_note,
  test_purchase_order, test_employee)
- raw GL/SLE select helpers -> frappe.get_all / qb, with order-independent
  comparisons where account ordering is collation-dependent across engines
  (test_purchase_invoice, test_sales_invoice, test_payment_entry, test_asset,
  test_purchase_receipt, test_payment_request, test_repost_accounting_ledger,
  test_journal_entry)

All changes are test-only and behaviour-identical on MariaDB (lowercase column names
resolve the same; posting_datetime == timestamp(posting_date, posting_time); HAVING on
the expression is the same computation). Verified: the heavy modules pass on both
MariaDB and Postgres, and MariaDB output is unchanged.
2026-06-21 14:05:49 +05:30
Mihir Kandoi
a1f7bf8195 Merge pull request #56210 from mihir-kandoi/pg-authcontrol-boot
refactor(postgres): Authorization Control + startup boot raw SQL → qb/ORM
2026-06-21 07:44:55 +05:30
Mihir Kandoi
52d7f56922 refactor(setup): make Authorization Control Postgres-valid (ifnull→coalesce, raw SQL→qb)
authorization_control.py used MySQL-only `ifnull()` in its raw rule
lookups (invalid on Postgres) and several raw `frappe.db.sql` selects.

- Replace every `ifnull(...)` with the portable `coalesce(...)` in the
  rule-lookup statements that remain raw (they interpolate dynamic
  conditions and rely on Frappe's Postgres backtick translation).
- Convert the user/role based_on lookups in validate_approving_authority
  and the four value-based lookups in get_value_based_rule to frappe.qb
  (Coalesce, isin, and a fresh Employee-designation subquery per use).

Behaviour is unchanged on MariaDB; the queries now run on Postgres.

Adds a test (no test file existed): a not-authorized case that exercises
the based_on + coalesce rule lookups (run as a non-admin user, since
Administrator implicitly holds every role), and a get_value_based_rule
call that exercises all four query-builder lookups.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 04:55:59 +05:30
Shllokkk
f83a80de48 Merge pull request #56155 from aerele/fix/party-type-filter-v16
fix: fetch party types based on account type in journal entry
2026-06-21 00:02:02 +05:30
Mihir Kandoi
96d4c48357 refactor(postgres): port Setup/Utilities/Templates/Regional queries to the query builder
Convert raw `frappe.db.sql` in the Setup, Utilities, Templates and Regional
areas to `frappe.qb` / the ORM so the same code runs on MariaDB and Postgres.
Behaviour is preserved on MariaDB; the conversions also make these paths valid
under Postgres' stricter SQL (GROUP BY, case-sensitivity, reserved words).

Conversions of note (behaviour kept identical to the MariaDB original):
- email_digest: ToDo ordering replicated with a CASE that mirrors MySQL
  `field(priority,'High','Medium','Low')` (unknown/NULL -> 0, sorts first),
  NULL-date-first and a `name` tie-break for a deterministic LIMIT.
- company.get_all_transactions_annual_history: the cross-DocType UNION + GROUP BY
  is replaced by one grouped query per DocType merged with a Counter, so two
  different DocTypes sharing a transaction_date still collapse into one bucket.
- templates/utils.send_message: contact lookup wraps both sides in LOWER() to
  keep MariaDB's case-insensitive email match on case-sensitive Postgres.
- regional/irs_1099 & uae_vat_201: address ranking and emirate aggregation
  rebuilt with CASE/aggregate selects that satisfy Postgres GROUP BY, with a
  deterministic tie-break on the LIMIT-1 address lookups.
- utilities/product.get_item_codes_by_attributes: numeric attribute values are
  cast with cstr() so Postgres doesn't reject `varchar = numeric`.

Tests (run on both MariaDB and Postgres, --lightmode):
- New: company merge test, authorization_rule duplicate-check, youtube report,
  templates/utils, and utilities/templates page reports (partners, rfq,
  material_request_info, product, utilities __init__).
- Existing suites kept green: company, email_digest, transaction_deletion_record,
  irs_1099, uae_vat_201.

Deferred (tracked separately):
- setup/doctype/authorization_control.py still has raw `.format()` SELECTs;
  left for its own PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 14:37:50 +05:30
S Sakthivel Murugan
6f225920d0 fix: fetch party types based on account type in journal entry and refactor SQL to query builder 2026-06-19 13:05:35 +05:30
ruthra kumar
6e62750c2f refactor(tests): reuse persistent master data instead of creating company per test
Replace per-test company creation in setUp() with persistent master data
from BootStrapTestData. Add Test PCV Company to test_records.json so it
becomes a persistent fixture rather than a throwaway created per test run.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 08:12:54 +05:30
Diptanil Saha
faadc1620b fix(company): replaced "this company" with company name on delete transactions dialog (#56021) 2026-06-17 02:11:08 +05:30
Mihir Kandoi
992015424b Merge pull request #55978 from aerele/driver-permission
fix: update system manager permissions
2026-06-16 20:36:01 +05:30
nareshkannasln
501c8087cb fix: update system manager permissions 2026-06-16 16:08:52 +05:30
ruthra kumar
8db4d2705a refactor(test): dont create master data in setUp 2026-06-16 08:03:47 +05:30
diptanilsaha
abb579e2db fix(get_exchange_rate): using get_single_value to fetch disabled value from currency_exchange_settings 2026-06-15 13:52:34 +05:30
diptanilsaha
138f683a68 test: fixed currency exchange test for frankfurter v2 api 2026-06-15 13:52:27 +05:30
diptanilsaha
479f9f63c9 fix: use frankfurter v2 by default for new install 2026-06-15 13:52:06 +05:30
Raghav Ruia
87d26a2d67 fix: show company name in delete transactions confirmation dialog
Display the actual company name in bold within the confirmation dialog
label so users immediately know which company they must type to confirm,
reducing the risk of accidental data loss.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 09:45:55 +05:30
rohitwaghchaure
bd60a9be90 Merge pull request #55849 from rohitwaghchaure/fixed-permissions-for-whitelist-functions
fix: permission for whitelist functions
2026-06-13 18:36:46 +05:30
Rohit Waghchaure
a64466561f fix: permission for whitelist functions 2026-06-13 17:45:37 +05:30
sokumon
90aba582ec chore: export workspaces with new schema 2026-06-12 13:08:48 +05:30
Mihir Kandoi
64175bdb3e fix: skip unchanged employee user status sync 2026-06-11 21:34:43 +05:30
Mihir Kandoi
4fed04c6c7 fix: sync employee user status after save 2026-06-11 20:58:35 +05:30
pandiyan
73d1852773 fix: show user disable audit log 2026-06-11 13:48:41 +05:30
Ankush Menat
ba936eefab fix: Add authorization checks on internal functions (#55709) 2026-06-08 14:49:32 +05:30
Diptanil Saha
0ba2961103 fix: updated role based permission for terms and conditions doctype (#55674) 2026-06-06 11:44:08 +00:00
Khushi Rawat
5aab5502f0 feat: add side-by-side defaults comparison view in item defaults grid (#55017)
* feat: add side-by-side defaults comparison view in item defaults grid

* fix: coderabbit suggested changes

* fix: change label of the fields

* fix: description design
2026-06-05 15:43:57 +05:30
Nabin Hait
51fee2d602 Merge pull request #55327 from nabinhait/erpnext-refactoring
refactor: ERPNext file structure refactoring [WIP]
2026-06-03 21:53:18 +05:30
Nabin Hait
53dfef8030 Merge branch 'develop' of https://github.com/frappe/erpnext into erpnext-refactoring 2026-06-03 15:20:49 +05:30