Compare commits

..

882 Commits

Author SHA1 Message Date
rohitwaghchaure
06ffe52d6e Merge pull request #54681 from rohitwaghchaure/fixed-support-66529
fix: incorrect expense account book in purchase return
2026-05-01 08:12:31 +05:30
Raffael Meyer
c120cc7ed1 fix: add missing fields in set_currency_labels (#54689) 2026-05-01 03:54:14 +02:00
Raffael Meyer
25be38e23c fix: Backfill not_applicable on Item Tax Template Details for German companies (#54682) 2026-04-30 19:21:24 +00:00
Rohit Waghchaure
2a720e7008 fix: incorrect expense account book in purchase return 2026-04-30 20:36:20 +05:30
Raffael Meyer
f38eca9124 fix: mark item tax templates as not applicable (#54673)
* fix: mark item tax templates as not applicable

For new German charts of accounts, mark accounts for different tax rates as *Not Applicable* in **Item Tax Templates**.

* fix: wrong applicable rate 19 in template 7
2026-04-30 11:44:08 +00:00
rohitwaghchaure
ad89f88c93 Merge pull request #54664 from rohitwaghchaure/fixed-support-66924
fix: show in and out qty in the stock ledger report for stock recos
2026-04-30 14:13:42 +05:30
Trusted Computer
78f654765d fix: correct titles set to {customer_name} or {supplier_name} text strings (#54656) 2026-04-30 10:28:14 +02:00
Hemil-Sangani
231dd1856f fix(project): use user.email for invitations and skip disabled users. (#54561)
* fix(project): use user.email for invitations and skip disabled users.

* Update erpnext/projects/doctype/project/project.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix(project): remove duplicate loop causing indentation error

* fix(project): resolve pre-commit hook failure

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-04-30 07:53:32 +00:00
Rohit Waghchaure
da081254a6 fix: show in and out qty in the stock ledger report for stock recos 2026-04-30 13:16:13 +05:30
Raffael Meyer
c543d15f3c feat: copy terms attachments to transactions (#53403) 2026-04-29 21:14:58 +00:00
Khushi Rawat
ddf0e35009 Merge pull request #54658 from khushi8112/skip-rescheduling-for-fully-depreciated-asset-sale
fix: skip depreciation rescheduling when asset is fully depreciated on sale
2026-04-30 02:34:10 +05:30
khushi8112
88b82383f5 fix: skip rescheduling only for asset being disposed 2026-04-30 02:11:57 +05:30
khushi8112
c4155b6c81 fix: skip depreciation rescheduling when asset is fully depreciated on sale 2026-04-30 02:01:57 +05:30
Mihir Kandoi
a04c028522 fix: correct project filter in buying doctypes (#54644) 2026-04-29 11:27:47 +00:00
diptanilsaha
5c5a5361bc fix(payment_entry): convert the date args to string type before escaping in get_outstanding_reference_documents (#54639) 2026-04-29 16:38:57 +05:30
Mihir Kandoi
060defcc2b fix: dont show serial/batch button when PR is submitted (#54642) 2026-04-29 16:36:31 +05:30
Mihir Kandoi
d0d8cff48f fix: py error on sales forecast doctype (#54641)
fix: py error on sales forecase doctype
2026-04-29 10:49:05 +00:00
Nishka Gosalia
844f3dbc0b feat(ux): Naming series dialog (#54554) 2026-04-29 14:45:10 +05:30
Khushi Rawat
43937acd8b fix(UX): Item master form cleanup (#54538)
* fix: UI improvements for item form

* fix: add descriptions and tooltips to all checkboxes

* feat: show toast notification when item price is created

* fix: do not use selling rate for opening stock entry

* fix: add descriptions and tooltips to item default fields

* fix(test): give valuation rate for opening stock entry creation

* fix: moving naming series toggle before the return

* refactor: more changes in the form UI
2026-04-29 14:44:55 +05:30
Mihir Kandoi
503b5bf140 perf: max recursion depth error in serial no (#54629) 2026-04-29 08:34:08 +00:00
rohitwaghchaure
3542087003 Merge pull request #54567 from barredterra/sn-ledger-status
fix: show correct status in Serial No Ledger
2026-04-29 12:42:54 +05:30
Pandiyan P
d68801e73a fix(selling): blanket order ordered qty recalculation on sales order status change (#54593) 2026-04-29 11:57:40 +05:30
Nishka Gosalia
addec3aa8f Merge pull request #53295 from aerele/project-not-copied-from-first-item-row 2026-04-29 11:38:07 +05:30
MochaMind
b001884f9d fix: sync translations from crowdin (#54607) 2026-04-29 01:52:16 +05:30
Ravibharathi
d1a80d40c4 fix: avoid double reduction of pe reference outstanding (#54193)
Co-authored-by: diptanilsaha <diptanil@frappe.io>
2026-04-29 01:46:55 +05:30
Ravibharathi
a8030c9713 fix: filter overdue purchase order items by company (#54099) 2026-04-29 00:58:01 +05:30
Mihir Kandoi
54f20de7e3 fix: duplicate entries being shown in batch exists in future transact… (#54604)
fix: duplicate entries being shown in batch exists in future transactions msg
2026-04-28 16:28:53 +00:00
diptanilsaha
f8893b04d5 refactor(sms_center): replaced raw SQL queries with Query Builder (#54600) 2026-04-28 15:15:46 +00:00
Lakshit Jain
1bade56e37 Merge pull request #54362 from frappe/ignore-opening-check
fix: filter opening entries after closing voucher
2026-04-28 18:43:25 +05:30
Lakshit Jain
a2b96799ff Merge pull request #54517 from vorasmit/exclude-pcv
fix: always exclude pcv entries except for closing account head
2026-04-28 18:42:42 +05:30
Smit Vora
d0f0e38e8d Merge pull request #54479 from Abdeali099/cash-flow-fixes 2026-04-28 17:30:32 +05:30
Smit Vora
590f2ffe28 test: include both accounts to test sum = 0 2026-04-28 16:45:26 +05:30
diptanilsaha
084c7f72f0 fix(get_stock_balance): validate inventory dimension fieldnames (#54587) 2026-04-28 16:41:22 +05:30
Smit Vora
84aa54c540 test: pcv is excluded from PL accounts 2026-04-28 16:30:02 +05:30
Smit Vora
5fc3ca1d4b test: opening entries after period closing 2026-04-28 16:02:32 +05:30
diptanilsaha
d62fa3c464 fix(payment_entry): escape arguments on invoice and order fetching sql queries (#54582) 2026-04-28 15:55:45 +05:30
diptanilsaha
07337ba9da chore(sidebar): moved Inactive Customers from CRM to Selling Workspace Sidbar (#54578) 2026-04-28 09:31:51 +00:00
Mihir Kandoi
2088a01c19 fix: update status of quotation in patch (#54577) 2026-04-28 09:20:41 +00:00
ravibharathi656
68cc518497 fix: copy project to new item row from parent 2026-04-28 13:10:48 +05:30
Sudharsanan Ashok
6f9089dd5b fix(manufacturing): remove conversion factor for stock qty (#54525) 2026-04-28 10:45:54 +05:30
Vinay Mishra
63edd5ddc6 fix: negative quantity check in validate_item_qty (#54559)
Fix negative quantity check in validate_item_qty

When saving a Blanket Order with a blank qty field in the items table, the following error is raised:

TypeError: '<' not supported between instances of 'NoneType' and 'int'

Root cause: The validate_item_qty method compares d.qty < 0 directly. When the qty field is left empty, its value is None, and Python cannot compare None with an integer.

Fix
Wrap d.qty with flt(), which safely converts None (and any non-numeric value) to 0.0 before the comparison.

# Before
if d.qty < 0:

# After
if flt(d.qty) < 0:
2026-04-28 05:12:49 +00:00
barredterra
2b3e047143 fix: show correct status in Serial No Ledger 2026-04-27 21:41:38 +02:00
barredterra
cb2e6e1e2e refactor: extract SN status logic 2026-04-27 21:41:12 +02:00
MochaMind
37e3493ec4 fix: sync translations from crowdin (#54520) 2026-04-27 20:53:04 +02:00
Mihir Kandoi
601581d6f8 fix: debit credit not equal in purchase transactions for multi currency (#54456) 2026-04-27 20:30:41 +05:30
ruthra kumar
837cdc9cc3 Merge pull request #54509 from ruthra-kumar/hide_toggleable_fields
fix: hide feature flag controlled fields on install
2026-04-27 14:43:11 +05:30
Mihir Kandoi
5281d60f2d fix: correct display depends on condition (#54548) 2026-04-27 09:07:36 +00:00
Mihir Kandoi
0aadd1e3a5 fix: make inv dimen reqd only in delivery note (#54546) 2026-04-27 08:28:55 +00:00
Pandiyan P
60a6b38c31 fix(stock): remove validation for transfer_qty field (#54542) 2026-04-27 06:56:30 +00:00
Mihir Kandoi
be2a4b7b2a refactor: quality inspection item query (#54511) 2026-04-27 10:45:25 +05:30
MochaMind
5c839f60e4 chore: update POT file (#54536) 2026-04-26 18:55:27 +02:00
rohitwaghchaure
6e77a45c05 Merge pull request #54514 from aerele/fix/incoming-rate-issue
fix(stock): set incoming rate as zero for outward sle
2026-04-26 10:06:35 +05:30
rohitwaghchaure
2a6ddc7f67 Merge pull request #54530 from aerele/fix/support-#66029
fix(stock): show item code in serial and batch selector dialog
2026-04-26 10:04:41 +05:30
Sudharsanan11
fee5bcadb2 fix(stock): add stock entry in batch master connection 2026-04-26 00:05:19 +05:30
Sudharsanan11
f572bc51e1 fix(stock): show item code in serial and batch selector dialog 2026-04-26 00:05:19 +05:30
Nishka Gosalia
fba33b7e7a refactor(UX): selling settings form (#54412)
refactor(UX): Selling settings form cleanup
2026-04-25 15:27:32 +05:30
diptanilsaha
ebca389136 fix(PCV): set correct filters of from_date and to_date on General Ledger Report on clicking Ledger button (#54522) 2026-04-25 00:03:38 +05:30
Smit Vora
c94b8c41f3 chore: comment 2026-04-24 19:32:00 +05:30
mahsem
e517eeaaa2 feat: danish_bosnian_address_template (#54093) 2026-04-24 14:54:37 +02:00
Khushi Rawat
c3931d4e29 Merge pull request #53843 from Shllokkk/ap-print-format
feat: Accounts Payable print template revamp and print format introduction
2026-04-24 17:51:45 +05:30
Khushi Rawat
0b9fdcd8cd Merge pull request #53870 from Shllokkk/arap-summary-print-formats
feat: AR and AP summary reports print template revamp and print format introduction
2026-04-24 17:42:52 +05:30
Khushi Rawat
b4e941835b Merge pull request #53822 from Shllokkk/ar-print-format
feat: Accounts Receivable print template revamp and print format introduction
2026-04-24 17:41:13 +05:30
Khushi Rawat
9132f0fc4a Merge pull request #53762 from Shllokkk/gl-print-format
feat: General ledger print template revamp and print format introduction
2026-04-24 17:39:45 +05:30
Sudharsanan11
ce37530e70 fix(stock): set incoming rate as zero for outward sle 2026-04-24 17:29:13 +05:30
ruthra kumar
889fdf2f11 fix: hide feature flag controlled fields on install 2026-04-24 17:13:36 +05:30
Smit Vora
5518e8c99f Merge pull request #54480 from ljain112/fix-change-customer 2026-04-24 13:19:32 +05:30
Smit Vora
419b9b3279 Merge pull request #54476 from ljain112/fix-tds-threshhold
fix: ensure tax withholding entries respect date range of category
2026-04-24 13:18:25 +05:30
Khushi Rawat
a9e6f8efd8 Merge pull request #53314 from aerele/budget-validation-on-cancel
fix: skip budget validation when cancelling GL entries
2026-04-24 12:14:09 +05:30
Mihir Kandoi
0e20e35842 fix: preserve inventory dimensions when raw materials are reset (#54440)
* fix: preserve inventory dimensions when raw materials are reset

* test: add test case
2026-04-23 17:16:12 +00:00
Raffael Meyer
b4107b8fd5 test(Code List): check content, not filename (#54490) 2026-04-23 15:40:22 +00:00
Raffael Meyer
a165b240a7 fix(edi): hardcode "Code List" DocType in importer (#54488) 2026-04-23 13:48:18 +00:00
Abdeali Chharchhodawala
f6639db0e9 feat: enhance account category with root type (#53190) 2026-04-23 17:34:37 +05:30
Abdeali Chharchhodawala
c35221852a feat: Add XLSX styling support to custom financial report templates (#52612) 2026-04-23 17:15:41 +05:30
Abdeali Chharchhoda
3854d2cbf6 chore: minor fix 2026-04-23 17:13:01 +05:30
Sudharsanan Ashok
ab19b16fe2 fix(stock): show available qty in warehouse link field (#54474) 2026-04-23 17:08:54 +05:30
Abdeali Chharchhoda
1fd6c3ba1a fix: update account identification to avoid using name_field in financial statements 2026-04-23 17:05:33 +05:30
Abdeali Chharchhoda
4274c2aba3 fix: add filter labels and required filters for financial report validation 2026-04-23 16:29:38 +05:30
Abdeali Chharchhoda
79d6a51e1e fix: update fiscal year filter to use mandatory_depends_on instead of reqd 2026-04-23 15:54:42 +05:30
ljain112
4eb9107e22 fix: update type hint for get_item_tax_template function 2026-04-23 15:50:03 +05:30
Abdeali Chharchhoda
5a915cb45e fix: ensure fiscal year is checked before validating date filters in financial statements 2026-04-23 15:43:20 +05:30
Smit Vora
b8c3765b85 Merge pull request #54449 from vorasmit/tds-reports-refactor
refactor: tax witholding report
2026-04-23 14:57:31 +05:30
ljain112
9ead8d4e3f fix: ensure tax withholding entries respect date range of category 2026-04-23 13:35:46 +05:30
Raffael Meyer
7f8fa7cf5e ci: test correctness pattern (#54186) 2026-04-22 22:00:42 +02:00
rohitwaghchaure
fd4cedf5e4 Merge pull request #54471 from rohitwaghchaure/fixed-delivery-schedule
fix: delivery schedule in the sales order
2026-04-22 22:02:15 +05:30
Rohit Waghchaure
435db260ee fix: delivery schedule in the sales order 2026-04-22 21:36:51 +05:30
Mihir Kandoi
f5357c233d fix: py error on stock ageing report (#54467) 2026-04-22 19:45:12 +05:30
diptanilsaha
0d2da6d86c ci: fix timezone for python mariadb tests (#54464) 2026-04-22 17:46:28 +05:30
Smit Vora
0349e7a0b8 fix: always exclude pcv entries except for closing account head 2026-04-22 16:09:42 +05:30
Smit Vora
7ae91cac01 fix: summing of values could be zero even if values exist 2026-04-22 13:27:36 +05:30
Smit Vora
b925469c4d fix: add party type for dynamic link support 2026-04-22 12:06:38 +05:30
Smit Vora
f0ea20e579 refactor: make report extensible by regional apps 2026-04-22 12:04:35 +05:30
ruthra kumar
3faeb1609b Merge pull request #54447 from ruthra-kumar/test_remove_raw_sql_delete_on_setup
refactor(test): remove explicit sql delete calls
2026-04-22 11:12:59 +05:30
ruthra kumar
b16dd3f2dd refactor(test): remove explicit sql delete calls 2026-04-22 10:33:25 +05:30
MochaMind
ffae7e42d3 fix: sync translations from crowdin (#54454) 2026-04-22 00:26:57 +05:30
Smit Vora
b5550f747e test: None is better than zero, as no values exist 2026-04-21 19:33:29 +05:30
Shllokkk
f6adef45bf Merge pull request #54307 from aerele/fix/populate_project_from_pe
fix(accounts): fetch project name from payment entry to journal entry
2026-04-21 18:57:45 +05:30
Smit Vora
07b023a934 refactor: updated key for withholding_date 2026-04-21 18:45:26 +05:30
Smit Vora
53666974a3 refactor: better label for entity type 2026-04-21 18:29:50 +05:30
Smit Vora
c3e7f7f02f refactor: how data is built 2026-04-21 18:04:02 +05:30
ruthra kumar
75a068aea8 Merge pull request #54446 from ruthra-kumar/wrong_type_hint_in_pos
fix: incorrect type hint
2026-04-21 17:56:01 +05:30
Smit Vora
6dca96b423 refactor: use consistent report column names 2026-04-21 17:28:56 +05:30
Smit Vora
f6eb844d20 Merge pull request #54422 from ljain112/fix-test-tds-report 2026-04-21 17:21:40 +05:30
Smit Vora
6d727c90b6 Merge pull request #54272 from ljain112/parrenttype 2026-04-21 17:20:56 +05:30
Smit Vora
d8fc9444ea Merge pull request #54344 from ljain112/project-filter-ar-ap 2026-04-21 17:15:37 +05:30
Mihir Kandoi
e65b9fc2ae fix: sales order is not valid when creating WO from MR from PP (#54435) 2026-04-21 09:47:02 +00:00
ruthra kumar
1995fcfdd8 fix: incorrect type hint 2026-04-21 13:57:12 +05:30
MochaMind
c2590c174d fix: sync translations from crowdin (#54358) 2026-04-21 09:24:40 +05:30
diptanilsaha
11fc3e5495 refactor: Sales Partner Commission Summary and Sales Partner Transaction Summary report (#54268) 2026-04-21 03:12:22 +00:00
Khushi Rawat
0edee23e53 Merge pull request #54131 from khushi8112/journal-entry-custom-remark-toggle
feat: use single remark field with custom remark toggle
2026-04-21 00:45:46 +05:30
Ravibharathi
f9232b209c Merge pull request #54415 from aerele/fix/clear-condions-table
fix: clear conditions table when calculate_based_on is set to Fixed
2026-04-20 19:22:25 +05:30
ravibharathi656
d6bb0ae093 fix: clear shipping rule conditions for fixed shipping rule 2026-04-20 19:01:37 +05:30
sarathibalamurugan
d73920be12 fix: clear conditions table when calculate_based_on is set to Fixed 2026-04-20 19:01:37 +05:30
ljain112
6545bcbbd9 refactor: fix test cases in tax withholding details report 2026-04-20 18:15:10 +05:30
Nihantra C. Patel
bc8f63b6dd Merge pull request #54419 from Nihantra-Patel/fix-default-letterhead-report-validation
fix: set letter_head_for letterhead and remove unknown letterhead from report
2026-04-20 17:25:51 +05:30
diptanilsaha
f4e77f63dd test(BootStrapTestData): create sales_partner test data while bootstrapping (#54416) 2026-04-20 11:41:02 +00:00
Nihantra Patel
a2ec597e3d fix: set letter_head_for for letterhead 2026-04-20 16:58:35 +05:30
diptanilsaha
6c51e4cd1f fix(pos_invoice_item): fetch grant_commission from item_code (#54413) 2026-04-20 11:21:10 +00:00
rohitwaghchaure
f89448709f Merge pull request #54350 from rohitwaghchaure/feat-backflush-based-on-in-bom
feat: backflush based on in BOM
2026-04-20 16:36:36 +05:30
Rohit Waghchaure
877d99c5a5 feat: backflush based on in BOM 2026-04-20 16:02:18 +05:30
ruthra kumar
1614d33e5c Merge pull request #54406 from ruthra-kumar/remove_dead_test_code
refactor(test): move contact and address creation to bootstrap
2026-04-20 14:16:04 +05:30
ruthra kumar
336be9d820 refactor(test): set instance variables before calling utility method 2026-04-20 13:53:03 +05:30
rohitwaghchaure
742c5f1822 Merge pull request #53708 from aerele/fetch_item_tax_template
fix: fetch get_item_tax_template while update items
2026-04-20 12:17:22 +05:30
rohitwaghchaure
0a8c195ab9 Merge pull request #54378 from rohitwaghchaure/exclude-group-warehouse
fix: exclude group warehouse in the report
2026-04-20 11:38:21 +05:30
Deepesh Garg
53d7c9fd9c Merge pull request #53756 from iamkhanraheel/fix/hr-default_role_permission
fix(hrms): default permission for HR roles
2026-04-20 11:20:12 +05:30
ruthra kumar
7f021fb705 refactor(test): move create_test_contact_and_address to bootstrap 2026-04-20 11:07:20 +05:30
ruthra kumar
e2b554e151 chore(test): remove dead test code 2026-04-20 10:37:31 +05:30
MochaMind
c1a469478d chore: update POT file (#54402) 2026-04-19 14:02:58 +02:00
Ahmed AbuKhatwa
d61b5fd5f6 fix(dashboard-trends): set default fiscal year and company before val… (#54339)
* fix(dashboard-trends): set default fiscal year and company before validating filters Ensure  and  are populated with default values

* fix(dashboard-trends): ensure fiscal_year and company are properly set before validation to avoid empty filter issues

* Update erpnext/controllers/trends.py

---------

Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2026-04-19 08:10:44 +00:00
Mihir Kandoi
28f3429a54 fix: recalculate operating costs if workstation type is changed (#54390)
* fix: recalculate operating costs if workstation type is changed

* fix: do not overwrite op costs on every save
2026-04-19 07:43:48 +00:00
yasmine ben ismail
af98963fa8 fix(readme): correct HTML issues and improve accessibility (#54267)
- Fix invalid width attribute (80xp → 80px)
- Remove invalid nested <p> tag in centered header section
- Add missing alt attribute to hero image for accessibility
- Improve external link security by recommending rel="noopener noreferrer"
2026-04-19 07:40:00 +00:00
Jaganath-Tridots
82438d6c72 Fix : None handling in pricing rule free item quantity calculation (#54375)
* fix(pricing_rule): handle None qty in transaction_qty calculation

* Update erpnext/accounts/doctype/pricing_rule/utils.py

---------

Co-authored-by: Jagan <jagan@DESKTOP-HPDMQ06.localdomain>
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2026-04-19 07:39:39 +00:00
Ravibharathi
1c65cc1088 fix: validate south africa company in vat audit report (#54030)
* fix: validate south africa company in vat audit report

* fix: use qb to get invoice data

* fix: validate company region in south africa vat settings
2026-04-19 13:06:15 +05:30
Nishka Gosalia
23768ae0a5 fix: Disallow negative rates in Purchase invoice (#54254) 2026-04-19 12:55:05 +05:30
yasmine ben ismail
3d87f3c070 fix(contributing): fix typos, grammar, and inconsistent casing (#54384) 2026-04-19 07:18:12 +00:00
yasmine ben ismail
43e5dfc3ca Revise feature request template for clarity and structure (#54386)
* Revise feature request template for clarity and structure

- Updated `about` field to mention "enhancement"
- Fixed typo: "many many requests" → "many requests"
- Fixed typo: "urgent need to" → "urgent need of"
- Added "Before Submitting" checklist to reduce duplicate issues
- Improved problem statement placeholder with a role-based example
- Added Environment section for ERPNext and Frappe version info

* chore: fix case

---------

Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2026-04-19 07:17:22 +00:00
yasmine ben ismail
e6f17e0447 Fix typos and enhance phrasing in README (#54387)
Fixed typo: "80xp" → "80px" in logo image tag
- Fixed typo: "many many requests" → "many requests"
- Fixed capitalization: "Javascript" → "JavaScript"
- Fixed capitalization: "Learning and community" → "Learning and Community"
- Fixed capitalization: "Open-Source ERP system" → "Open-Source ERP System"
- Fixed capitalization: "Frappe user" → "Frappe user"
- Fixed broken documentation link to use consistent URL
- Added missing Oxford commas
- Added missing "the" before "create-site"
- Improved phrasing: "with peace of mind" → "reliably and securely"
- Improved phrasing: "ad-hoc activities" → "other daily operations"
- Improved phrasing: "already set up sandbox" → "pre-configured sandbox"
- Improved phrasing: "It takes care of" → "It handles"
2026-04-19 07:15:49 +00:00
Mihir Kandoi
d6b379b936 fix: use qty instead of stock qty dropship gross profit report (#54389) 2026-04-19 06:40:59 +00:00
Mihir Kandoi
40bcaa7bc3 fix: dropship logic should come above non stock logic in gross profit… (#54383)
fix: dropship logic should come above non stock logic in gross profit report
2026-04-18 16:16:26 +00:00
Rohit Waghchaure
31fe6a378c fix: exclude group warehouse in the report 2026-04-18 17:41:53 +05:30
Mihir Kandoi
3ef6c24f07 fix: zero valuation rate popup on SI (#54376) 2026-04-18 11:44:49 +00:00
Pandiyan P
b93f2350ee fix: fetch item tax template from item group when creating item (#54258) 2026-04-18 11:58:33 +05:30
Lakshit Jain
453fe376ab feat: add support for 'not applicable' tax in item tax templates (#50898)
* feat: add support for 'not applicable' tax in item tax templates

* refactor: remove unused imports

* fix: import NOT_APPLICABLE_TAX in get_item_tax_map function

* fix: add item wise tax details for not applicable taxes

* test: added test case for `not_applicable`

* fix: do not create item wise tax details for not applicable tax

* fix: ensure tax rate is set to 0 for not applicable tax rows

* refactor: changes as per review

* test: update selling settings

* test: correct settings

* fix: return both net and current tax amounts for not applicable tax
2026-04-18 11:34:36 +05:30
vorasmit
3c8a066484 fix: filter opening entries in first year in custom financial statement 2026-04-17 22:27:48 +05:30
rohitwaghchaure
b0fd152896 Merge pull request #54355 from aerele/fix/support-65791
fix(manufacturing): handle empty list in query builder
2026-04-17 21:21:29 +05:30
rohitwaghchaure
0359a3ed0b Merge pull request #54354 from rohitwaghchaure/fixed-negative-batch-report
fix: negative batch report showing same batch-warehouse multiple times
2026-04-17 21:10:47 +05:30
sarathibalamurugan
9eeb819106 test: add test for project name in exchange gain loss entry 2026-04-17 18:44:44 +05:30
sarathibalamurugan
d9b255b952 fix(accounts): fetch project name from payment entry to journal entry 2026-04-17 18:43:50 +05:30
Jatin3128
ba01d66c24 fix: changed qty validation from qty field to stock_qty (#54352) 2026-04-17 13:13:13 +00:00
Pandiyan37
9e5d94c1e6 fix(manufacturing): handle empty list in query builder 2026-04-17 18:26:34 +05:30
Rohit Waghchaure
700572980d fix: negative batch report showing same batch-warehouse multiple times 2026-04-17 18:21:57 +05:30
iamkhanraheel
2018a90ad8 fix: default company perms for HR manager 2026-04-17 17:13:51 +05:30
Nishka Gosalia
9ecbf57a84 Merge pull request #54074 from nishkagosalia/gh-53442 2026-04-17 16:09:44 +05:30
iamkhanraheel
d26cd69fe5 fix: remove unwanted perm for HR user role 2026-04-17 15:39:42 +05:30
MochaMind
be711eacde fix: sync translations from crowdin (#54334) 2026-04-17 11:49:12 +02:00
ljain112
0cad511136 test: add test with project not in payment entry 2026-04-17 15:18:57 +05:30
nishkagosalia
eb89903dec fix: Table row in dialog should not have delete row option 2026-04-17 15:16:40 +05:30
Nishka Gosalia
6ee4b46be0 Merge pull request #54345 from nishkagosalia/batch-form-cleanup 2026-04-17 15:13:57 +05:30
nishkagosalia
de747fe625 refactor(UX): Batch Form Cleanup 2026-04-17 14:31:42 +05:30
ljain112
d51dbf5254 fix: add project filter to accounts payable and receivable reports 2026-04-17 14:00:01 +05:30
rohitwaghchaure
f555183ab6 Merge pull request #54342 from rohitwaghchaure/fixed-reqd-fg_warehouse
fix: make Target Warehouse mandatory on UI for WO
2026-04-17 13:23:39 +05:30
Rohit Waghchaure
2a8267e10a fix: make Target Warehouse mandatory on UI 2026-04-17 13:17:06 +05:30
Mihir Kandoi
5f4641e55b fix: hide operations field in bom creator if phantom (#54336) 2026-04-16 15:36:14 +00:00
Mihir Kandoi
cac7a358dd feat: make fg phantom-able in bom creator (#54332) 2026-04-16 13:25:54 +00:00
ruthra kumar
ee50767e42 Merge pull request #54327 from ruthra-kumar/setup_default_for_repost_on_fresh_install
fix(test): missing repost allowed defaults
2026-04-16 16:02:18 +05:30
ruthra kumar
257865deb2 fix(test): missing repost allowed defaults 2026-04-16 15:36:15 +05:30
Mihir Kandoi
e04a2e6da2 refactor: add category field to uom (#54290) 2026-04-16 09:03:12 +00:00
Venkatesh
97efd51fb8 feat: add option to create production plan from sales order (#53662)
Co-authored-by: sudarsan2001 <frankel9675@gmail.com>
2026-04-16 13:49:28 +05:30
ruthra kumar
40012f6617 Merge pull request #54301 from ruthra-kumar/merge_repost_settings_to_accounts_settings
refactor(ux): merge repost settings to accounts settings
2026-04-16 12:08:50 +05:30
ruthra kumar
6a04c159ca refactor: delete redundent repost setting 2026-04-16 11:35:23 +05:30
ruthra kumar
940d3cfe0a refactor: limit reposting to only supported doctypes 2026-04-16 11:35:23 +05:30
ruthra kumar
ece85c770f refactor: remove redundant field from filter 2026-04-16 11:35:23 +05:30
ruthra kumar
3093409933 refactor(ux): better error message 2026-04-16 11:35:23 +05:30
ruthra kumar
b8207d5ed1 refactor(test): use new source for repost setting 2026-04-16 11:35:23 +05:30
ruthra kumar
d5c58277cb refactor: move allowed doctypes to accounts settings
- dropped 'allowed' field
2026-04-16 11:35:20 +05:30
ruthra kumar
ff2d536943 Merge pull request #54172 from Shllokkk/acc-dimension-fix
fix: move make_dimension_in_accounting_doctypes from after_insert to on_update
2026-04-16 11:05:51 +05:30
ruthra kumar
2f4bb23125 Merge pull request #52923 from aerele/fix/taxable-amount-conversion-rate
fix(taxes_and_totals): apply conversion_rate to taxable_amount in get_itemised_tax
2026-04-16 10:52:13 +05:30
Dharanidharan2813
2e577ed25b fix(taxes_and_totals): apply conversion_rate to taxable_amount in get_itemised_tax 2026-04-16 10:30:20 +05:30
MochaMind
2e1d426c78 fix: sync translations from crowdin (#54312) 2026-04-15 16:11:43 +00:00
NaviN
9e9c8a07a7 Merge pull request #54306 from aerele/fix/expand_details_in_customer_quick_entry
fix: non-collapsible in customer quick entry
2026-04-15 17:26:13 +05:30
PKSowmiya05
53e120269d fix: non-collapsible in customer quick entry 2026-04-15 17:17:51 +05:30
ruthra kumar
89ebf48544 refactor: merge reposting settings to accounts settings 2026-04-15 16:31:02 +05:30
ruthra kumar
4198dd643d refactor(company): don't force set service expense account on save (#54275) 2026-04-15 15:33:39 +05:30
Smit Vora
ab61a757e3 Merge pull request #54241 from ljain112/fix-rounded-total 2026-04-15 15:23:14 +05:30
ruthra kumar
299e141cee refactor(test): set dependant value in company master 2026-04-15 12:29:29 +05:30
Mihir Kandoi
af6974893b fix: add portal user ownership check to supplier quotation (#54298) 2026-04-15 11:21:08 +05:30
rohitwaghchaure
0969ec4186 Merge pull request #54279 from rohitwaghchaure/fixed-banner-for-serial-batch
fix: banner to enable serial / batch feature
2026-04-14 23:14:30 +05:30
Vishnu Priya Baskaran
ce2670b252 Revert "fix: sync paid and received amount" (#54238) 2026-04-14 22:16:00 +05:30
MochaMind
b083121421 fix: sync translations from crowdin (#54259) 2026-04-14 16:46:06 +02:00
iamkhanraheel
41103a0622 fix: default perm for HR manager & HR user 2026-04-14 18:30:41 +05:30
Rohit Waghchaure
08e8cc8575 fix: banner to enable serial / batch feature 2026-04-14 18:26:35 +05:30
Sudharsanan Ashok
b6b7e8e2f6 fix(stock): remove float precision to fix precision issue (#54284) 2026-04-14 16:42:17 +05:30
Mihir Kandoi
1cc2b159dd fix: handle multi uom conversion factor for manufacture entry (#54285) 2026-04-14 10:43:47 +00:00
Mihir Kandoi
5ff2ae5a83 fix: fetch correct expense account for operations in stock entry (#54278) 2026-04-14 09:55:07 +00:00
Mihir Kandoi
ea0d53e2f3 fix: add drop ship logic in gross profit report (#54220) 2026-04-14 09:29:01 +00:00
ruthra kumar
927f40b296 refactor(company): don't force set service expense account on save 2026-04-14 14:46:46 +05:30
Mihir Kandoi
f37bf62824 fix: wrong operation time calculation (#53796) 2026-04-14 14:42:02 +05:30
ljain112
3aeb7d6b01 fix(purchase_register): filter tax rows by parenttype in invoice tax map query 2026-04-14 12:31:10 +05:30
Raffael Meyer
8a72d7fafe fix(edi): restrict Code List imports to files and trusted backend URLs (#54137) 2026-04-13 21:44:24 +05:30
Sudharsanan Ashok
2f025272d7 fix(stock): update bin to zero when no previous sle exists (#54236) 2026-04-13 21:04:14 +05:30
rohitwaghchaure
488747eb5d Merge pull request #54257 from rohitwaghchaure/fixed-github-65007
fix: not able to submit the PO
2026-04-13 19:43:34 +05:30
Rohit Waghchaure
1e43c37452 fix: not able to submit the PO 2026-04-13 17:10:37 +05:30
ljain112
e2ac476587 chore: spelling mistake 2026-04-13 16:51:20 +05:30
Khushi Rawat
6c5788dfba Merge pull request #54190 from khushi8112/company-address-permission-check
fix: add permission validation when prompting company details for incomplete letterhead data
2026-04-13 15:24:04 +05:30
Nishka Gosalia
aa9d35b28a Merge pull request #54249 from nishkagosalia/gh-53595 2026-04-13 15:21:30 +05:30
khushi8112
84e5272f5d fix: append row level user remarks in gl map 2026-04-13 15:15:52 +05:30
khushi8112
697f521e14 feat: use single remark field with custom remark toggle 2026-04-13 15:15:45 +05:30
Khushi Rawat
c805324a99 Merge pull request #54244 from khushi8112/journal-entry-get-against-jv-sql-injection
fix: replace raw SQL with qb in get_against_jv to prevent SQL injection
2026-04-13 15:12:49 +05:30
nishkagosalia
3e2b40ad4a refactor(UX): Stock ledger serial and batch number fields 2026-04-13 14:47:22 +05:30
khushi8112
c133f7156d fix: replace raw SQL with qb in get_against_jv to prevent SQL injection 2026-04-13 14:47:21 +05:30
Sudarshan
a9bb3e2315 fix: make operation mandatory when any sub operation row is added (#54245) 2026-04-13 07:38:22 +00:00
Khushi Rawat
577a7591c7 Merge pull request #54176 from khushi8112/payment-entry-list-reconciliation-indicator
feat: show reconciled/unreconciled indicator in list view
2026-04-13 12:13:23 +05:30
ljain112
f8d278b733 fix: reset base_rounded_total when rounded_total resets 2026-04-13 11:48:08 +05:30
ruthra kumar
451e4fbb21 Merge pull request #54237 from ruthra-kumar/bold_group_accounts
refactor: boldface for group accounts in financial statements
2026-04-13 11:40:23 +05:30
ruthra kumar
545e9e069a refactor: boldface for group accounts in financial statements 2026-04-13 11:16:49 +05:30
MochaMind
3617a9b674 fix: sync translations from crowdin (#54234) 2026-04-12 19:11:36 +02:00
MochaMind
39d93f35e0 chore: update POT file (#54228) 2026-04-12 10:12:49 +00:00
Shllokkk
44e0b36093 fix: minor changes in print templates 2026-04-12 13:14:24 +05:30
Shllokkk
915fcc0166 fix: minor changes in print template 2026-04-12 13:07:41 +05:30
Shllokkk
e3019c827c fix: minor changes in print template 2026-04-12 13:00:51 +05:30
MochaMind
a76336e3d9 fix: sync translations from crowdin (#54181) 2026-04-11 21:07:20 +02:00
Shllokkk
e8d08df044 fix: changes to gl print template 2026-04-11 23:06:01 +05:30
mgicking-bmi
3e5d18c5c4 Fix(selling): enable selling_settings creation through fixtures (#54177) 2026-04-11 05:12:00 +00:00
Mihir Kandoi
2f5fa3b207 fix: batch/serial should use parent's posting datetime for naming (#54206) 2026-04-10 18:59:16 +00:00
Sambhav Saxena
1dcfd9174f Fix(bom): refetch the rate of item when 'source_from_supplier' is updated (#54187) 2026-04-10 18:12:13 +00:00
rohitwaghchaure
1e64f392bb Merge pull request #54182 from nishkagosalia/st-64901-2
fix: account change in warehouse
2026-04-10 19:41:14 +05:30
nishkagosalia
777d9161cc fix: account change in warehouse 2026-04-10 18:54:43 +05:30
Praveenkumar Dhanasekar
887d2a8379 fix: update return value in workstation list view indicator (#54198) 2026-04-10 16:49:05 +05:30
Mihir Kandoi
9cdfe74de6 fix: remove unneccessary function for serial no status updation (#54191) 2026-04-10 10:36:42 +00:00
Trusted Computer
bd9427623f refactor: bring back titles on sales transactions and make them optional and visible on purchase transactions (#52633)
* fix: correct wrong PO titles

* refactor: restore title fields to sales transaction doctypes

* refactor: change title fields to optional fields with no default in purchase transactional doctypes

* chore: re-save doctype definitions

- updates modified timestamps
- regenerates type hints

---------

Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
2026-04-10 13:09:32 +05:30
khushi8112
256a258b38 fix: add permission validation when prompting company details for incomplete letterhead data 2026-04-10 12:53:45 +05:30
iamkhanraheel
f02b3b6166 fix: default perm for HR manager & HR user 2026-04-09 19:15:45 +05:30
Mihir Kandoi
9bc5a30ea4 Revert "fix: update_nsm only in warehouse creation" (#54178) 2026-04-09 13:04:38 +00:00
khushi8112
a48a29410e fix: refresh after unreconcile 2026-04-09 18:05:39 +05:30
khushi8112
7eded60892 feat: show reconciled/unreconciled indicator in list view 2026-04-09 17:40:03 +05:30
Shllokkk
ee067e6015 fix: move make_dimension_in_accounting_doctypes from after_insert to on_update 2026-04-09 16:27:54 +05:30
Nishka Gosalia
b0e3fa3979 fix: update_nsm only in warehouse creation (#54165) 2026-04-09 10:27:22 +00:00
Khushi Rawat
514c86cf4b Merge pull request #54142 from khushi8112/blank-remarks-in-invoices
fix: Set remarks blank instead of No remarks in Sales/Purchase Invoices
2026-04-09 14:54:23 +05:30
khushi8112
56416d18d3 fix(test): Remove usage of No remark as remark in tests 2026-04-09 14:23:52 +05:30
rohitwaghchaure
90a1d32098 Merge pull request #54161 from rohitwaghchaure/fixed-posting-time-riv
fix: set default posting time in RIV
2026-04-09 13:55:44 +05:30
Rohit Waghchaure
a7ece65536 fix: set default posting time in RIV 2026-04-09 13:31:34 +05:30
Aarol D'Souza
f5dda90f26 Merge pull request #54129 from AarDG10/refactor-util-use
refactor: update reset password method name
2026-04-09 11:52:15 +05:30
mergify[bot]
f09001a25e Merge branch 'develop' into refactor-util-use 2026-04-09 05:58:56 +00:00
rohitwaghchaure
d7254bba47 Merge pull request #54132 from rohitwaghchaure/fixed-reposting-file-not-updating
fix: last SLE not updated in the file
2026-04-09 08:22:11 +05:30
Mihir Kandoi
71a17cfda9 fix: inventory dimension patch (#54147) 2026-04-09 02:26:35 +00:00
Mihir Kandoi
7f0751539b fix: inventory dimension patch (#54141) 2026-04-09 01:45:48 +00:00
Nishka Gosalia
7ef48a966a feat: Allowing operation level quality inspection check in BOM (#53859)
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2026-04-09 01:41:45 +00:00
khushi8112
2515bf3aff fix: Set remarks blank instead of No remarks in Sales/Purchase Invoices 2026-04-09 01:54:35 +05:30
diptanilsaha
d15cd08e72 refactor(lost_opportunity_report): replaced raw_sql with query builder (#54136) 2026-04-08 23:38:43 +05:30
Rohit Waghchaure
38ed425ee2 fix: last SLE not updated in the file 2026-04-08 20:43:23 +05:30
NaviN
ef454822d7 fix(sales invoice): toggle Get Items From button based on is_return and POS view (#52594) 2026-04-08 20:42:58 +05:30
Mihir Kandoi
6e44b8913e fix: inventory dimensions should not be mandatory unnecesarily (#54064) 2026-04-08 19:09:56 +05:30
Sudharsanan Ashok
9d16d06504 fix(manufacturing): check remaining qty to calculate operating cost (#53983) 2026-04-08 17:20:49 +05:30
Nishka Gosalia
31319cb6ee fix: quality inspection item code fetch perm issue (#54121)
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2026-04-08 17:20:09 +05:30
AarDG10
c4d74483e1 refactor: update reset password method name 2026-04-08 17:19:43 +05:30
Sudharsanan Ashok
086122f650 fix(stock): ignore delivery note on delivery trip on_cancel trigger (#54120) 2026-04-08 16:36:02 +05:30
rohitwaghchaure
f9e2696745 Merge pull request #54102 from rohitwaghchaure/fixed-precision-issue
fix: hardcoded precision causing decimal issues
2026-04-08 12:19:21 +05:30
Khushi Rawat
f183885829 Merge pull request #54103 from aerele/asset-movement-field-state-after-save
fix: preserve asset movement field properties after save
2026-04-08 11:57:19 +05:30
MochaMind
eb04706fee fix: sync translations from crowdin (#54105) 2026-04-07 23:12:50 +05:30
Abdeali Chharchhodawala
76a7781283 refactor: financial report template enhancements (#52687) 2026-04-07 22:18:31 +05:30
Ahmed AbuKhatwa
89560d4691 fix(promotional_scheme): toggle enable state between Buying and Selli… (#54110)
Co-authored-by: AhmedAbukhatwa <Ahmedabukhatwa1@gmail.com>
2026-04-07 21:52:24 +05:30
Rohit Waghchaure
90fd6f2e40 fix: hardcoded precision causing decimal issues 2026-04-07 19:48:18 +05:30
Vishnu Priya Baskaran
edba5f3a06 fix: sync paid and received amount (#53039) 2026-04-07 18:33:31 +05:30
mergify[bot]
6da5dff26c fix: skip validate_stock_accounts in Journal Entry when perpetual inventory is disabled (backport #53554) (backport #53558) (#54104)
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Saeed Kola <mohammedsaeedk@gmail.com>
Co-authored-by: diptanilsaha <diptanil@frappe.io>
2026-04-07 12:28:41 +00:00
ravibharathi656
4a004a2a82 fix: preserve asset movement field properties after save 2026-04-07 16:54:44 +05:30
Smit Vora
187542bfa5 Merge pull request #53964 from vorasmit/disassembly-by-se 2026-04-07 14:17:16 +05:30
Smit Vora
98dfd64f63 fix: remove unnecessary param, and use value from self 2026-04-07 13:17:22 +05:30
Shllokkk
4228885f1e fix: minor bug fixes for ar print template 2026-04-07 13:01:18 +05:30
Shllokkk
e6a32a9d02 feat: introduce print format for Accounts Receivable report 2026-04-07 13:01:18 +05:30
Shllokkk
ffc59ebc9c fix: improve design and refactor ar print template 2026-04-07 13:01:18 +05:30
Khushi Rawat
b4be235bbf Merge pull request #53394 from aerele/fix-asset-filter
fix: remove null from link_filters
2026-04-07 12:29:44 +05:30
Sakthivel Murugan S
00c94afa78 fix: task gantt popup text not visible in light theme (#53882) 2026-04-07 12:08:52 +05:30
Mihir Kandoi
17853931d6 fix: divide sub-assembly cost by qty to get per-unit rate in BOM Creator (#54090)
Co-authored-by: Ravindu Gajanayaka <ravindu2012@users.noreply.github.com>
2026-04-07 05:33:05 +00:00
Smit Vora
f13d37fbf9 test: enhance tests as per review comments 2026-04-07 10:54:34 +05:30
Smit Vora
b892139342 test: maintain sufficient stock for scrap item 2026-04-07 10:27:41 +05:30
Smit Vora
ab1fc22431 fix: set bom details on disassembly; abs batch qty 2026-04-07 10:00:30 +05:30
Smit Vora
93ad48bc1b fix: process loss with bom path disassembly 2026-04-07 09:59:54 +05:30
Amine
13cc07237e docs: fix typo, grammar and numbering in README.md (#54008) 2026-04-07 09:41:16 +05:30
mahsem
4282b9c68a fix: dif_inward_from_outward_workspace_sidebar (#54083) 2026-04-07 09:26:23 +05:30
Lakshit Jain
6d11a08cdd fix: add tax_id handling in Tax Withholding Entry (#53598)
* fix: add tax_id handling in Tax Withholding Entry

* fix: update get_tax_id_for_party to handle absence of tax_id in payment and journal entries

* fix: refactor tax_id handling in Tax Withholding Entry and Details

* test: correct function address
2026-04-06 22:27:32 +05:30
Nishka Gosalia
66780543bd fix: transactions where update stock is 0 should not create SLEs (#54035) 2026-04-06 20:25:51 +05:30
Smit Vora
ea392b2009 fix: validate work order consistency in stock entry 2026-04-06 20:08:38 +05:30
MochaMind
80272de0df fix: sync translations from crowdin (#53955) 2026-04-06 13:07:08 +00:00
Smit Vora
54342539c3 Merge pull request #53973 from vorasmit/persist-toggle 2026-04-06 17:26:19 +05:30
rohitwaghchaure
eebc0d2ad3 Merge pull request #54050 from rohitwaghchaure/fixed-github-51874
fix: GL entries for different exchange rate in the purchase invoice
2026-04-06 17:21:50 +05:30
Amine
fa814c0b71 fix: fix formatting and missing bullet point in TRADEMARK_POLICY.md (#54054) 2026-04-06 17:13:04 +05:30
Amine
83235b90d7 fix: fix incorrect issue link numbers in sponsors.md (#54055) 2026-04-06 17:12:26 +05:30
Mihir Kandoi
9b60d8e711 fix: remove title field from purchase receipt (#54051) 2026-04-06 17:09:00 +05:30
Rohit Waghchaure
a953709640 fix: GL entries for different exchange rate in the purchase invoice 2026-04-06 17:00:02 +05:30
Khushi Rawat
adea316dd2 Merge pull request #54052 from khushi8112/add-print-hide-to-fields
fix: print hide unnecessary fields
2026-04-06 16:13:26 +05:30
Deepesh Garg
77578e41e5 Merge pull request #54033 from krishna-254/fix-user-permission-error-on-status-change
fix: resolve user permission error on status change by updating user …
2026-04-06 15:49:47 +05:30
mahsem
1e90b9a148 feat: croatian_address_template (#53888) 2026-04-06 15:41:23 +05:30
Krishna Shirsath
c6695b613c fix: resolve user permission error on status change by updating user enabled status directly 2026-04-06 15:27:39 +05:30
khushi8112
8f83616b60 fix: print hide unnecessary fields 2026-04-06 14:35:15 +05:30
Sagar Vora
99da4f5147 Merge pull request #54042 from sagarvora/fix/discount-amount-validation-on-save
fix: skip discount amount validation when not saving
2026-04-06 13:00:22 +05:30
Sagar Vora
135cb5fd67 test: add test for discount amount on partial purchase receipt
Co-authored-by: ravibharathi656 <131471282+ravibharathi656@users.noreply.github.com>
2026-04-06 12:38:46 +05:30
Sagar Vora
0975583388 fix: skip discount amount validation when not saving 2026-04-06 12:33:49 +05:30
Gajendra Nishad
b9ef061911 fix: show current stock qty in Stock Entry PDF (#53761) 2026-04-06 10:50:13 +05:30
Amine
7a2759b2f0 fix: fix typos, grammar and numbering in CONTRIBUTING.md (#54027) 2026-04-06 04:25:24 +00:00
rohitwaghchaure
ccd017c737 Merge pull request #54004 from rohitwaghchaure/fixed-do-not-repost-gl
fix: do not repost GL if no change in valuation
2026-04-06 09:07:29 +05:30
Rohit Waghchaure
bb53cce228 fix: do not repost GL if no change in valuation 2026-04-05 22:54:51 +05:30
Vishnu Priya Baskaran
9417f55b7d fix: update min date based on transaction_date (#53803) 2026-04-05 20:59:13 +05:30
MochaMind
eca3ec114c chore: update POT file (#54018) 2026-04-05 15:59:23 +02:00
rohitwaghchaure
92dc95570d Merge pull request #54005 from rohitwaghchaure/fixed-github-53991
fix: screen freezes if consumed qty set in SCR
2026-04-05 13:19:49 +05:30
Pandiyan P
74b11710cc fix(manufacturing): handle null cur_dialog in BOM work order dialog (#54011) 2026-04-05 12:47:18 +05:30
ervishnucs
ad22256b2d fix: resolve item tax template from item group in update items 2026-04-05 11:16:37 +05:30
Rohit Waghchaure
dd7be2b370 fix: screen freezes if consumed qty set in SCR 2026-04-04 13:25:43 +05:30
rohitwaghchaure
f322dc9d69 Merge pull request #53994 from aerele/fix/update-sabe-stock-queue
fix(stock): update stock queue in SABE for return entries
2026-04-04 12:51:34 +05:30
kavin-114
e537896df8 test(stock): add unit test to update stock queue for return 2026-04-03 17:37:19 +05:30
kavin-114
0af8077bcc fix(stock): update stock queue in SABE for return entries 2026-04-03 17:37:05 +05:30
vorasmit
a71e8bb116 fix: use get_value 2026-04-03 16:19:43 +05:30
Mihir Kandoi
efd716e53d fix: remove reference in serial/batch when document is cancelled (#53979) 2026-04-02 07:51:20 +00:00
vorasmit
71fd18bdf9 fix: avg stock entries for disassembly from WO 2026-04-01 23:56:44 +05:30
vorasmit
3cf1ce8360 fix: manufacture entry with group_by support 2026-04-01 23:42:36 +05:30
Smit Vora
a6d41151ff test: disassembly for scrap / secondary item 2026-04-01 16:55:15 +05:30
Smit Vora
2be8313819 fix: handle disassembly for secondary / scrap items 2026-04-01 16:55:15 +05:30
Smit Vora
1693698fed test: disassembly of items with batch and serial numbers 2026-04-01 16:55:15 +05:30
Smit Vora
d32977e3a9 test: additional items in stock entry considered with disassembly 2026-04-01 16:55:15 +05:30
Smit Vora
6988e2cbbc test: disassemble with source stock entry reference 2026-04-01 16:55:15 +05:30
Smit Vora
342a14d340 test: disassembly from wo 2026-04-01 16:55:15 +05:30
Smit Vora
13b019ab8e fix: set serial and batch from source stock entry - on disassemble 2026-04-01 16:55:15 +05:30
Smit Vora
d3d6b5c660 fix: correct warehouse preference for disassemble 2026-04-01 16:55:15 +05:30
Smit Vora
2e4e8bcaa7 fix: auto-set source_stock_entry 2026-04-01 16:55:15 +05:30
Smit Vora
1ed0124ad7 fix: add support to fetch items based on manufacture stock entry; fix how it's done from work order 2026-04-01 16:55:15 +05:30
Smit Vora
6394dead72 fix: validate qty that can be disassembled from source stock entry. 2026-04-01 16:55:15 +05:30
Smit Vora
dba82720b6 fix: support creating disassembly (without link of WO) 2026-04-01 16:55:15 +05:30
Smit Vora
b64f86148c fix: custom button to disassemble manufactured stock entry with work order 2026-04-01 16:55:15 +05:30
Smit Vora
b47dfacb3e fix: set_query for source stock entry 2026-04-01 16:55:15 +05:30
Smit Vora
68e97808c5 fix: disassembly prompt with source stock entry field 2026-04-01 16:55:14 +05:30
Smit Vora
d4baa9a74a fix: create source_stock_entry to refer to original manufacturing entry 2026-04-01 16:55:13 +05:30
rohitwaghchaure
7846548a1b Merge pull request #53963 from rohitwaghchaure/fixed-github-53743
fix: hide fields related to track Semi-Finished Goods if feature has disabled
2026-04-01 16:37:13 +05:30
Shllokkk
86ee9959a2 fix: minor bugs in print templates 2026-04-01 12:32:15 +05:30
Rohit Waghchaure
399faf0ced fix: hide fields related to track Semi-Finished Goods if feature has disabled 2026-04-01 12:05:41 +05:30
Smit Vora
da778edf48 fix(ux): refresh grid to correctly persist the state of fields 2026-04-01 08:43:56 +05:30
Shllokkk
fbe5d128a8 feat: sticky column in various reports (#53960)
Co-authored-by: diptanilsaha <diptanil@frappe.io>
Co-authored-by: mihir-kandoi <kandoimihir@gmail.com>
2026-03-31 23:38:19 +05:30
Mihir Kandoi
d76ddf7271 fix: include rejected qty in tax (purchase receipt) (#53624) 2026-03-31 15:29:56 +00:00
Lakshit Jain
1e85d72127 Merge pull request #53961 from ljain112/fix-taxe-rounding
fix: ensure accurate rounding for item-wise tax and taxable amounts
2026-03-31 19:49:39 +05:30
Mihir Kandoi
ef18b5cd93 Revert "chore: initiate release twice in a week" (#53944) 2026-03-31 19:01:12 +05:30
Nishka Gosalia
7ff3dc0ac4 Merge pull request #53965 from nishkagosalia/gh-53962 2026-03-31 18:07:43 +05:30
nishkagosalia
e9e510a76e fix: Party Field only visibile when party type selected 2026-03-31 17:52:41 +05:30
ljain112
b73b161cbe test: improve test case 2026-03-31 17:46:46 +05:30
ljain112
9b37f2d95c fix: ensure accurate rounding for item-wise tax and taxable amounts 2026-03-31 17:23:01 +05:30
Khushi Rawat
f5bf95ca65 Merge pull request #53811 from khushi8112/customer-group-is-group-validation
fix: prevent selection of group type customer group in customer master
2026-03-31 16:46:25 +05:30
rohitwaghchaure
4013092271 Merge pull request #53953 from rohitwaghchaure/fixed-github-53597
fix: rejected serial no field showing even if serial / batch feature disabled
2026-03-31 16:11:12 +05:30
Rohit Waghchaure
c2f419ac3d fix: rejected serial no field showing even if serial / batch feature not enabled 2026-03-31 16:09:00 +05:30
Ejaaz Khan
eaa4f7bb55 Merge pull request #53949 from iamejaaz/sticky-erpnext-reports
feat: sticky columns in reports
2026-03-31 16:04:31 +05:30
khushi8112
75fa2b2277 fix(test): do not use is_group enabled customer group in test 2026-03-31 15:42:08 +05:30
Ejaaz Khan
df753676c6 fix: semgrep translation issue 2026-03-31 15:34:46 +05:30
Ejaaz Khan
03e4df7a1a feat: sticky columns in reports
Co-authored-by: diptanilsaha <diptanil@frappe.io>
2026-03-31 15:12:58 +05:30
Mihir Kandoi
f1529a05b2 fix: do not show inv dimension unnecessarily in stock entry (#53946) 2026-03-31 09:42:21 +00:00
ruthra kumar
f452ad3ce2 Merge pull request #53795 from ruthra-kumar/use_erpnext_testsuite_across_repo
refactor(test): enforce ERPNextTestSuite across repo
2026-03-31 15:01:58 +05:30
khushi8112
6068dc959f fix: prevent selection of group type customer group in customer master 2026-03-31 14:40:59 +05:30
Khushi Rawat
dce5e46599 Merge pull request #53939 from khushi8112/ux-improvement-for-opening-invoice-tool
fix: dynamic labels on invoice type change
2026-03-31 12:06:45 +05:30
Nishka Gosalia
0696bd2082 chore: remove inter warehouse transfer settings (#53860) 2026-03-31 11:13:26 +05:30
khushi8112
820bd15e1e fix: dynamic labels on invoice type change 2026-03-31 01:53:28 +05:30
MochaMind
e7614e2290 fix: sync translations from crowdin (#53864) 2026-03-30 18:11:38 +00:00
Ankush Menat
f97877a60a fix(UX): Store weekly off at the end of holiday list (#53833)
Perhaps these two should be stored separately too?
2026-03-30 21:28:40 +05:30
Smit Vora
28ac0effff Merge pull request #53925 from ljain112/fix-item-tax-rounding 2026-03-30 20:46:21 +05:30
ljain112
fc8437c499 test: update item-wise tax detail test for high conversion rates 2026-03-30 20:04:53 +05:30
Smit Vora
a9edd3f132 Merge pull request #53406 from ljain112/fix-item-valaution-deduct 2026-03-30 19:53:55 +05:30
Smit Vora
a18196f584 fix(taxes): improve tax calculation accuracy and update test assertions 2026-03-30 19:37:59 +05:30
diptanilsaha
7d7a1efadb fix(bank_account): added validation to fetch bank account details using get_bank_account_details (#53926) 2026-03-30 18:51:27 +05:30
ljain112
3449ab063a fix(tests): update item code and quantity in tax detail test case 2026-03-30 18:37:07 +05:30
Jatin3128
d827ab3d2e Merge pull request #53922 from Jatin3128/toggle-ps
feat(Payment Request): Added a toggle for using the payment schedule
2026-03-30 18:28:30 +05:30
Jatin3128
8ec15b537e feat(Payment Request): Added a toggle for using the payment schedule 2026-03-30 18:05:42 +05:30
ljain112
7f87a5e5c6 fix(taxes): increase rounding threshold for tax breakup calculations 2026-03-30 17:58:47 +05:30
diptanilsaha
c41730dfee fix(opening_invoice_creation_tool): sanitize summary content for dashboard (#53917) 2026-03-30 17:52:27 +05:30
diptanilsaha
fa5238ba12 fix(item_dashboard): escaping warehouse, item_code, stock_uom and item_name on get_data (#53904) 2026-03-30 09:30:51 +00:00
rohitwaghchaure
b9f26a1f31 Merge pull request #53906 from rohitwaghchaure/fixed-support-63613
fix: purchase invoice missing item
2026-03-30 14:44:37 +05:30
diptanilsaha
eda64cbd4d fix(warehouse_capacity_dashboard): removed escape from template (#53907) 2026-03-30 09:01:34 +00:00
Rohit Waghchaure
af994c1a22 fix: purchase invoice missing item 2026-03-30 14:07:31 +05:30
rohitwaghchaure
91aaabdd31 Merge pull request #53902 from rohitwaghchaure/fixed-code-cleanup-reposting
fix: item-wh reposting, code cleanup
2026-03-30 14:01:07 +05:30
Rohit Waghchaure
e0ca34ae39 fix: item-wh reposting, code cleanup 2026-03-30 13:39:24 +05:30
diptanilsaha
ddeb9775ed fix(warehouse_capacity_dashboard): escaping warehouse, item_code and company on get_data (#53894) 2026-03-30 07:46:33 +00:00
Sudharsanan Ashok
ad25c6d163 fix(stock): add warehouse filter to pick work order raw materials (#53748) 2026-03-30 13:15:48 +05:30
rohitwaghchaure
71a1dda958 Merge pull request #53799 from aerele/fix/lcv-company-validation
fix(stock): update company validation for expense account in lcv
2026-03-30 13:03:36 +05:30
Sudharsanan11
875a2e4947 fix(test): enable perpetual inventory 2026-03-30 12:16:48 +05:30
Sudharsanan Ashok
d28474a450 fix(stock): ignore qty validation for pick list (#53871) 2026-03-30 06:37:26 +00:00
Sudharsanan Ashok
f3a794384a fix(manufacturing): update the qty precision (#53874) 2026-03-29 21:51:36 +05:30
ervishnucs
97e7916b66 fix: resolve item tax template from item group in update items 2026-03-29 21:35:26 +05:30
MochaMind
893eb8c77a chore: update POT file (#53876) 2026-03-29 14:56:50 +02:00
rohitwaghchaure
0e0a7f3563 Merge pull request #53878 from rohitwaghchaure/fixed-maintain-reposting-state
fix: maintain state during reposting
2026-03-29 16:12:48 +05:30
Rohit Waghchaure
f8738a791b fix: maintain state during reposting 2026-03-29 15:53:46 +05:30
Kaushal Shriwas
6badf00313 fix: change shipment parcel dimension fields from Int to Float (#53867) 2026-03-29 06:48:51 +00:00
Shllokkk
5bbcb73808 fix: revamp print formats for accounts receivable summary and accounts payable summary reports 2026-03-29 02:02:59 +05:30
diptanilsaha
998469d5c7 refactor: setup wizard stages and demo data creation (#53866) 2026-03-29 00:43:58 +05:30
rohitwaghchaure
5c95f3347b Merge pull request #53853 from rohitwaghchaure/fixed-reposting-dependent-sles
fix: corrected logic to retry reposting if timeout occurs after dependant SLE processing
2026-03-27 21:25:44 +05:30
Rohit Waghchaure
90b9ab0bc8 fix: corrected logic to retry reposting if timeout occurs after dependent SLE processing 2026-03-27 21:04:35 +05:30
Mihir Kandoi
935eea6463 fix: invalid dynamic link filter for address doctype (#53849) 2026-03-27 12:23:58 +00:00
Shllokkk
2bf9d41797 feat: add print format for accounts payable report 2026-03-27 16:03:20 +05:30
Mihir Kandoi
6008fa710d fix: validate if quantity greater than 0 in item dashboard (#53846) 2026-03-27 10:32:35 +00:00
ruthra kumar
47bb728f65 fix: sync translations from crowdin (#53841)
* fix: Italian translations

* fix: Swedish translations
2026-03-27 15:56:27 +05:30
MochaMind
aef6c959ea fix: Swedish translations 2026-03-27 14:12:13 +05:30
MochaMind
bddc7a3e4a fix: Italian translations 2026-03-27 14:11:56 +05:30
rohitwaghchaure
54c6948174 Merge pull request #53839 from rohitwaghchaure/fixed-job-card-timer-issue
fix: timer not showing in job card
2026-03-27 13:50:14 +05:30
ruthra kumar
e45af4345f Merge pull request #53837 from ruthra-kumar/semgrep_to_prevent_test_regression
ci: semgrep to prevent test regression
2026-03-27 13:41:47 +05:30
Rohit Waghchaure
58dbb3d638 fix: timer not showing in job card 2026-03-27 13:06:34 +05:30
ruthra kumar
be4496e4ab ci: semgrep to prevent test regression 2026-03-27 12:49:28 +05:30
Shllokkk
c051536182 refactor: revamp print template for accounts payable report 2026-03-27 12:32:17 +05:30
ruthra kumar
2aecf0103a refactor(test): remove AccountsTestMixin from Sales Order 2026-03-27 12:12:48 +05:30
rohitwaghchaure
e6cac26640 Merge pull request #53812 from rohitwaghchaure/fixed-pick-correct-dependent-sle
fix: pick correct dependant sle during reposting
2026-03-27 12:12:48 +05:30
ruthra kumar
d2ee967383 refactor(test): remove AccountsTestMixin from reactivity 2026-03-27 11:56:52 +05:30
ruthra kumar
0b6546ea06 refactor(test): remove AccountsTestMixin from distributed discount 2026-03-27 11:56:30 +05:30
Rohit Waghchaure
8e8ee56e64 fix: pick correct dependant sle during reposting 2026-03-27 11:50:34 +05:30
ruthra kumar
13505ddcfb test: fixed test case (backport #53826) (#53834)
test: fixed test case

(cherry picked from commit 10f58112ae)

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2026-03-27 11:47:12 +05:30
Nishka Gosalia
5d4ac95e7a Merge pull request #53704 from nishkagosalia/gh-53512-fixes 2026-03-27 11:38:52 +05:30
ruthra kumar
2b37d7514d refactor(test): move logic from AccountsTestMixin to ERPNextTestSuite 2026-03-27 11:20:11 +05:30
Rohit Waghchaure
8368feb9df test: fixed test case
(cherry picked from commit 10f58112ae)
2026-03-27 05:49:25 +00:00
nishkagosalia
3a78af7f42 fix: test case 2026-03-27 11:11:19 +05:30
nishkagosalia
3bedc6cf7e chore: Dropping bom stock report and bom stock calculated report 2026-03-27 11:11:18 +05:30
nishkagosalia
c1874cb7d5 fix: change in functionality 2026-03-27 11:11:18 +05:30
nishkagosalia
5d088350dc feat: Bom stock analysis report 2026-03-27 11:11:18 +05:30
ruthra kumar
f3148e052c refactor(test): erpnext testsuite should be primary superclass 2026-03-27 11:00:25 +05:30
Shllokkk
d987688058 fix: support translated search in get_party_type and refactor raw sql to qb 2026-03-27 10:49:34 +05:30
ruthra kumar
c283c1c472 Merge pull request #53074 from Jatin3128/subscription-section-hide
feat: add setting to hide Subscription references across doctypes
2026-03-27 10:37:59 +05:30
ruthra kumar
6566acbe23 Merge pull request #53429 from Shllokkk/deferred-rev-fix
feat(report): add service start/end date and amount with roll-ups in deferred revenue/expense report
2026-03-27 10:30:12 +05:30
ruthra kumar
d6755c3d14 Merge pull request #53343 from Shllokkk/email-campaign-fix
fix(email_campaign): prevent unsubscribing entire campaign when email group member unsubscribes
2026-03-27 10:26:49 +05:30
Shllokkk
0d4f56bf84 refactor: table body data rendering cleanup 2026-03-26 21:56:51 +05:30
Pandiyan P
5b1fa81451 fix(accounts): set supplier name as title field in Purchase Invoice (#53710)
fix(accounts): update title field in purchase order and purchase invoice
2026-03-26 19:00:10 +05:30
Mihir Kandoi
8164d195fc fix: flaky currency exchange test (#53813) 2026-03-26 12:23:55 +00:00
iamkhanraheel
5ec66169a7 fix: default permission for HR manager role 2026-03-26 17:23:54 +05:30
Shllokkk
9660debe28 fix: improve filter details render logic to avoid showing duplicate information 2026-03-26 16:18:51 +05:30
rohitwaghchaure
f382b30b4e Merge pull request #53216 from aerele/fix/legacy-recon-in-ageing
fix(stock): handle legacy single sle recon entries
2026-03-26 15:37:21 +05:30
rohitwaghchaure
15996952f6 Merge pull request #52152 from rohitwaghchaure/refactor-reposting-feature
Refactor reposting feature
2026-03-26 15:12:20 +05:30
Rohit Waghchaure
daa2420996 refactor: storing of current status of reposting 2026-03-26 14:49:39 +05:30
Krishna Pramod Shirsath
f37b6fde72 Merge pull request #53245 from krishna-254/feat/employee-milestone-indicators
feat: employee milestone indicators
2026-03-26 13:40:20 +05:30
Mihir Kandoi
afa66e4785 fix: keep from and to time blank until added explicitly (#53798) 2026-03-26 13:05:54 +05:30
Sudharsanan11
913168e8b6 fix(stock): update company validation for expense account in lcv 2026-03-26 12:56:59 +05:30
kavin-114
7e6bbcc3fb fix(stock): handle legacy single sle recon entries 2026-03-26 12:46:06 +05:30
Krishna Shirsath
9715637c80 Merge remote-tracking branch 'origin/develop' into feat/employee-milestone-indicators 2026-03-26 10:05:23 +05:30
Mihir Kandoi
3f74733942 fix: purchase invoice for internal transfers should not require PO (#53791) 2026-03-25 16:18:51 +00:00
diptanilsaha
e136bfbb61 fix(contract_template): restrict create, write and delete access only to System Manager (#53787) 2026-03-25 14:43:45 +00:00
MochaMind
00b780362b fix: sync translations from crowdin (#53475) 2026-03-25 11:47:01 +01:00
diptanilsaha
1d202fe739 Merge pull request #53779 from diptanilsaha/template_fixes 2026-03-25 14:56:36 +05:30
diptanilsaha
bc6561cdd0 fix(templates): using correct syntax of include in projects.html 2026-03-25 14:55:05 +05:30
diptanilsaha
d9760bbf4f fix(templates): escape attachment file_url and file_name in order.html and projects.html 2026-03-25 14:46:50 +05:30
Sudharsanan Ashok
a821c6669f fix(manufacturing): update condition for base hour rate calculation (#53753) 2026-03-25 11:37:38 +05:30
Pandiyan P
d43d308e2f fix(manufacturing): apply work order status filter in job card (#53766) 2026-03-25 11:20:04 +05:30
Mihir Kandoi
90cd957d6e fix: do not check for sub assembly reference for rm of fg (#53758) 2026-03-24 17:09:49 +00:00
iamkhanraheel
7b0bfe76cc fix: default permission for HR User role 2026-03-24 19:57:42 +05:30
ruthra kumar
14a46bf920 Merge pull request #53657 from ruthra-kumar/move_commits_inside_test_guard_clause
refactor(test): move remaining commits inside test guard
2026-03-24 17:43:17 +05:30
ruthra kumar
bc2b8da597 refactor(test): process statement of acc remove commit 2026-03-24 17:21:31 +05:30
ruthra kumar
fd2b76a4d2 refactor(test): move location creation to bootstrap in asset movement 2026-03-24 17:21:31 +05:30
ruthra kumar
8fd65d7afa refactor(test): make stock entry deterministic 2026-03-24 17:21:31 +05:30
ruthra kumar
2c53cf3902 refactor(test): make asset capitalization deterministic 2026-03-24 17:21:31 +05:30
ruthra kumar
d3cf8cb851 refactor(test): make ledger merge deterministic 2026-03-24 17:21:31 +05:30
ruthra kumar
77f41e120d refactor(test): SLA move company creation to bootstrap 2026-03-24 17:21:31 +05:30
ruthra kumar
426b7db3c8 refactor(test): move webform custom dt creation to boostrap 2026-03-24 17:21:31 +05:30
ruthra kumar
934740205a refactor(test): move custom doctype data setup to bootstrap 2026-03-24 17:21:31 +05:30
ruthra kumar
4454af8efd refactor(test): move tax category custom field creation to bootstrap 2026-03-24 17:21:31 +05:30
ruthra kumar
11fb00c21d refactor(test): move trial company creation to bootstrap 2026-03-24 17:21:31 +05:30
ruthra kumar
31ce09204f refactor(test): move purchase invoice dimension setup to bootstrap 2026-03-24 17:21:31 +05:30
Nishka Gosalia
6c354895d6 Merge pull request #53738 from nishkagosalia/item-form-cleanup 2026-03-24 16:28:10 +05:30
nishkagosalia
be55082751 refactor: item master ux improvements 2026-03-24 15:55:45 +05:30
ervishnucs
a518a735f3 fix: remove null from link_filters 2026-03-24 15:43:20 +05:30
Khushi Rawat
ec003342a0 Merge pull request #53588 from khushi8112/default-print-format-for-quotation
feat: default print format for Quotation
2026-03-24 15:36:34 +05:30
Shllokkk
3ba36212b0 refactor: clean and standardize print template for general ledger report 2026-03-24 15:32:13 +05:30
khushi8112
da41057cd6 fix: add quotation print format in the list 2026-03-24 13:03:24 +05:30
khushi8112
b9083411cc fix: remove unused print format 2026-03-24 12:17:42 +05:30
khushi8112
c99cec1071 fix: add closing div tab 2026-03-24 12:17:42 +05:30
khushi8112
4307cd5b1c feat: default print format for Quotation 2026-03-24 12:17:36 +05:30
ruthra kumar
9ed072ac83 refactor(test): move company setup to bootstrap 2026-03-24 11:57:45 +05:30
ruthra kumar
342ce65401 refactor(test): move dimension setup to test data bootstrap
and remove create_dimension() and disable_dimension()
2026-03-24 11:57:43 +05:30
ruthra kumar
ed76d6699a refactor(test): move commits inside test guard clause 2026-03-24 11:57:02 +05:30
ruthra kumar
cd5b0ea5fd Merge pull request #52802 from nabinhait/workspace-cleanup-1
fix: Removed quick access link from selling workspace
2026-03-24 11:30:53 +05:30
ruthra kumar
ae8068e833 Merge pull request #53302 from Shllokkk/xxs-xxe-fix
fix: sanitize genericode import inputs and secure XML parser
2026-03-24 11:27:15 +05:30
Nabin Hait
d7c48d645a fix: Removed quick access link from selling workspace 2026-03-24 11:11:56 +05:30
ruthra kumar
107fecd4b0 Merge pull request #53730 from khushi8112/asset-location-overwritten-by-accounting-dimension
fix: skip overwriting existing asset fields with accounting dimensions
2026-03-24 11:04:59 +05:30
khushi8112
2859a143f2 fix: skip overwriting existing asset fields with accounting dimensions 2026-03-24 02:19:44 +05:30
Khushi Rawat
bd9b0185f4 Merge pull request #53680 from khushi8112/better-opening-invoice-creation-tool
fix(UX): improve party selection UX with party name field
2026-03-24 01:35:54 +05:30
Khushi Rawat
0faa261729 Merge pull request #53646 from khushi8112/default-print-format-for-rfq
feat: default print format for Request for Quotation
2026-03-24 01:34:00 +05:30
Mihir Kandoi
91da450a31 chore: remove unused imports (#53722) 2026-03-23 16:39:55 +00:00
Pandiyan P
8ebc2e38ec fix(manufacturing): close work order status when stock reservation is… (#53714)
* fix(manufacturing): close work order status when stock reservation is enabled

* chore: better syntax

---------

Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2026-03-23 16:05:00 +00:00
diptanilsaha
96c79dfe8b chore(test_item_group): removed unused function _print_tree (#53716) 2026-03-23 15:50:01 +00:00
diptanilsaha
958bb6c619 chore: skip semgrep check for db.commit in BootStrapTestData (#53715) 2026-03-23 15:39:14 +00:00
Rohit Waghchaure
20787ef5da refactor: reposting for better peformance 2026-03-23 20:36:02 +05:30
Jatin3128
226aafa8cf feat: add setting to hide Subscription references across doctypes 2026-03-23 19:49:01 +05:30
ruthra kumar
30380851d8 Merge pull request #52285 from Jatin3128/payment_entry_ref
fix(Payment Entry): split orders as per the schedules in the reference table
2026-03-23 19:36:36 +05:30
Rucha Mahabal
248ea16d96 feat(employee): Create User button and form. (#52726)
* feat(employee): Create User button and form.

* feat(employee): Add automatic user creation feature and related validations. Create User on Import.

* refactor(employee): create user function -removed useless function calls

* refactor(employee): reorganize joining and employee exit tabs at the end.

* feat(employee): Add birthdays and work anniversaries indicator in form ,list view enhancements and new empty state.

* fix: add missing type hints to whitelisted function arguments

* fix(employee): add 'set_only_once' property to 'Create User Automatically' field

* refactor(employee): remove anniversary indicator logic from employee form

* fix: move Joining section before Exit, relabel Employee Exit -> Exit

* fix: reset employee listview empty state, add import btn instead

* fix: employee user creation

- consider prefered email as default in employee creation

- remove unused user parameter from `create_user` API

- remove unnecessary validations on user ID, already checked by user doctype hooks

- set company email only if empty

* fix: only validate auto user creation before insert

* fix: uncollapse User Details section in new form

* fix: hide Create User Automatically checkbox if user is already selected

* fix: set create user perm to 1 by default + persist option while saving employee

* fix: avoid setting unnecessary fields

* fix: fallback to Personal Email for user creation just like client-side

* fix: reset User ID and make it read-only if 'Create User Automatically' is set

* test: Create User Automatically

* test(fix): set company in employee

---------

Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2026-03-23 17:47:02 +05:30
rohitwaghchaure
3f3ddf968e Merge pull request #53705 from rohitwaghchaure/fixed-support-63246
fix: batch validation for subcontracting receipt
2026-03-23 17:01:47 +05:30
Rucha Mahabal
a14f834589 test(fix): set company in employee 2026-03-23 16:52:11 +05:30
ervishnucs
03c9d16ca6 fix: fetch get_item_tax_template while update items 2026-03-23 16:45:20 +05:30
Rohit Waghchaure
b8d201658a fix: batch validation for subcontracting receipt 2026-03-23 16:29:47 +05:30
Rucha Mahabal
cc93b14154 Merge branch 'develop' into feat/employee-creation-and-lifecycle 2026-03-23 16:11:10 +05:30
Rucha Mahabal
d4ecede3c3 test: Create User Automatically 2026-03-23 16:09:58 +05:30
Asief Tejani
99d55ab8d8 docs(README): sync erpnext docker with frappe_docker repo (#53447)
Co-authored-by: diptanilsaha <diptanil@frappe.io>
2026-03-23 16:00:03 +05:30
diptanilsaha
8ea0cc90df fix: check for submit permissions instead of write permissions when updating status (#53697) 2026-03-23 15:43:33 +05:30
Rucha Mahabal
2be6bb694f fix: reset User ID and make it read-only if 'Create User Automatically' is set 2026-03-23 15:42:13 +05:30
Rucha Mahabal
31af13a5e6 fix: fallback to Personal Email for user creation just like client-side 2026-03-23 15:31:51 +05:30
Sudharsanan Ashok
41f986ff83 fix(manufacturing): update non-stock item dict (#53689) 2026-03-23 15:16:37 +05:30
khushi8112
469bb0ba4e fix: party name not updating correctly 2026-03-23 09:44:41 +00:00
khushi8112
8fd9b88cd9 fix(UX): improve party selection UX with party name field 2026-03-23 09:44:41 +00:00
Rucha Mahabal
97bb100010 fix: avoid setting unnecessary fields 2026-03-23 15:06:15 +05:30
khushi8112
6b9fb77772 fix: set default print format for when downlod pdf 2026-03-23 15:04:14 +05:30
khushi8112
2af0d9cf6c feat: default print format for Request for Quotation 2026-03-23 15:04:14 +05:30
Nishka Gosalia
75ce885684 Merge pull request #53695 from nishkagosalia/fix-type-hint-stock 2026-03-23 15:01:43 +05:30
Krishna Shirsath
3e56b8d71d fix(employee): removed milestone lable and remove unnecessary margins 2026-03-23 14:47:54 +05:30
nishkagosalia
2f72ae9afd fix: type hint in stock module 2026-03-23 14:37:46 +05:30
Nishka Gosalia
ca877ba223 Merge pull request #53649 from nishkagosalia/st-63180 2026-03-23 14:27:13 +05:30
diptanilsaha
a908bc7e92 fix(trends): added validation for period_based_on filter (#53690) 2026-03-23 14:23:42 +05:30
Rucha Mahabal
091899d0df fix: set create user perm to 1 by default + persist option while saving employee 2026-03-23 14:23:01 +05:30
Rucha Mahabal
ec3302d1c1 fix: hide Create User Automatically checkbox if user is already selected 2026-03-23 14:06:56 +05:30
Rucha Mahabal
1466df91bd fix: uncollapse User Details section in new form 2026-03-23 14:06:24 +05:30
Rucha Mahabal
ee1aa10328 fix: only validate auto user creation before insert 2026-03-23 13:37:07 +05:30
nishkagosalia
dcd0509089 chore: Adding new argument in status updater to skip qty validation 2026-03-23 13:18:26 +05:30
Rucha Mahabal
613d36a139 fix: employee user creation
- consider prefered email as default in employee creation

- remove unused user parameter from `create_user` API

- remove unnecessary validations on user ID, already checked by user doctype hooks

- set company email only if empty
2026-03-23 12:52:23 +05:30
Mihir Kandoi
7a61d6fcd5 fix: shipping rule applied twice on non stock items (#53655) 2026-03-23 06:49:39 +00:00
Mihir Kandoi
5154102468 fix: PO should not be required for internal transfers (#53681) 2026-03-23 06:32:26 +00:00
Rucha Mahabal
d99d16423a fix: reset employee listview empty state, add import btn instead 2026-03-23 11:59:05 +05:30
Rucha Mahabal
000b5b72d5 fix: move Joining section before Exit, relabel Employee Exit -> Exit 2026-03-23 11:27:00 +05:30
MochaMind
f483d9ff13 chore: update POT file (#53677) 2026-03-22 14:47:24 +01:00
rohitwaghchaure
c1c3757943 Merge pull request #53673 from rohitwaghchaure/fixed-stock-queue-not-updated
fix: stock queue for SABB
2026-03-22 13:00:28 +05:30
Rohit Waghchaure
3fcf308ed8 fix: stock queue for SABB 2026-03-22 12:06:43 +05:30
rohitwaghchaure
145a42eb30 Merge pull request #53638 from rohitwaghchaure/fixed-deadlock-issue-for-sle
fix: deadlock issue for SLE
2026-03-21 14:03:40 +05:30
Mihir Kandoi
fa35fbdb8e fix: do not overwrite expense account in stock entry (#53658) 2026-03-20 08:02:32 +00:00
diptanilsaha
8e17c722fb fix: validate permission before updating status (#53651) 2026-03-19 14:49:29 +00:00
Nishka Gosalia
ffd3e90806 Merge pull request #53645 from nishkagosalia/gh-53526 2026-03-19 18:29:00 +05:30
nishkagosalia
7f70e62c30 fix: Adding validation for operation time in BOM 2026-03-19 17:31:31 +05:30
ruthra kumar
44247f63d5 Merge pull request #53594 from ruthra-kumar/fix_failing_patch
fix: patch failure due to dependency
2026-03-19 17:30:35 +05:30
ruthra kumar
bb3cee8ef5 fix: patch failure due to dependency 2026-03-19 16:13:20 +05:30
Mihir Kandoi
fc25d83a9e fix: co by product patch for v14 migration (#53644) 2026-03-19 10:31:46 +00:00
Rohit Waghchaure
f48b03c6ec fix: deadlock issue for SLE 2026-03-19 14:31:17 +05:30
Sudharsanan Ashok
442fe9a833 fix(stock): fix email error message (#53606) 2026-03-19 07:11:41 +00:00
diptanilsaha
086fea7cf0 fix(payment_schedule): using show_alert instead of msgprint for non-selection of payment schedule (#53623) 2026-03-19 12:29:28 +05:30
Sakthivel Murugan S
256d267a3b fix: set customer details on customer creation at login (#53509) 2026-03-19 12:04:31 +05:30
Pandiyan P
0fdc1bc497 fix(stock): handle NoneType error (#53593) 2026-03-19 11:56:58 +05:30
Mihir Kandoi
71293bcf73 refactor: remove test file import in stock ageing report (#53619) 2026-03-19 11:52:57 +05:30
Mihir Kandoi
f1e36b09f9 fix: consider returned qty in subcontracting report (#53616) 2026-03-19 05:24:58 +00:00
Mihir Kandoi
743970a8c6 fix: python error in manufacture entry if transfer against is job card (#53615) 2026-03-19 04:57:37 +00:00
Sowmya
03d8a7a6af fix: ignore cost center (#53063) 2026-03-19 09:54:17 +05:30
Vishnu Priya Baskaran
31b44534df fix: check posting_date in args (#53303) 2026-03-19 09:52:37 +05:30
ruthra kumar
df7e6b7a79 Merge pull request #47910 from ruthra-kumar/ci_lightmode_runner
refactor(test): repo wide test suite refactor to achieve deterministic behaviour
2026-03-18 21:42:16 +05:30
ruthra kumar
eb143ba742 refactor(test): cleanup; remove redundant attribute 2026-03-18 20:59:39 +05:30
ruthra kumar
22c05d4b8f refactor(test): make pick list deterministic 2026-03-18 20:59:39 +05:30
ruthra kumar
7e8f9f10f3 refactor(test): make item wise sales register deterministic 2026-03-18 20:59:39 +05:30
ruthra kumar
5263386bb2 refactor(test): replace integration test case with ERPNextTestSuite 2026-03-18 20:59:39 +05:30
ruthra kumar
72d08902fd refactor(test): make purchase order deterministic 2026-03-18 20:59:39 +05:30
ruthra kumar
23d35c6cca refactor(test): make sales invoice deterministic 2026-03-18 20:59:39 +05:30
ruthra kumar
da8fcde4a8 refactor(test): make location determinisitic 2026-03-18 20:59:38 +05:30
ruthra kumar
6eea0a2299 refactor(test): make bank clearance deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
9e63c14cef refactor(test): make sales invoice deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
21b25ce96c refactor(test): hardcoded names over dynamic 2026-03-18 20:59:38 +05:30
ruthra kumar
7cad642a11 refactor(test): use JSON for company master 2026-03-18 20:59:38 +05:30
ruthra kumar
5237e58f29 refactor(test): remove explicit call to master data setup 2026-03-18 20:59:38 +05:30
ruthra kumar
e67165d6ce refactor(test): hardcoded names over dynamic ones
Much faster bootstrap without those get_doc calls
2026-03-18 20:59:38 +05:30
ruthra kumar
5a4a77f5d2 refactor: move test bootstrap to module 2026-03-18 20:59:38 +05:30
ruthra kumar
96b82624cd refactor(test): speed up setup 2026-03-18 20:59:38 +05:30
ruthra kumar
fc8fadf455 refactor(test): make stock entry deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
518800cd2f refactor(test): remove redundant before_tests 2026-03-18 20:59:38 +05:30
ruthra kumar
0f2f53cbd0 refactor(test): make process deferred accounting deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
19e03ccdde refactor(test): make bom deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
7fea5a5ca2 refactor(test): make customer deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
cb693e05bf refactor(test): tax rule; removed setUpClass, tearDownClass 2026-03-18 20:59:38 +05:30
ruthra kumar
aa998219b1 refactor(test): common make function 2026-03-18 20:59:38 +05:30
ruthra kumar
4d65cb907f refactor(test): make bom stock calculated deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
c2dea5245d refactor(test): make pos profile deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
07374b5dbc refactor(test): make pos opening entry deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
25279321ac refactor(test): make pos invoice merge log deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
0474d0c4e8 refactor(test): make pos closing deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
ec9b2f0567 refactor(test): make stock test_utils deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
6c27efeeea refactor(test): make currency exchange deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
ffca80daa5 refactor(test): make sales partner target variance deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
2c0466d637 refactor(test): make sales order analysis deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
a91ed14aec refactor(test): make uae vat audit deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
96f9fc3484 refactor(test): make uae vat 201 deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
e01e3c0a62 refactor(test): make job card deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
4777b060ba refactor(test): make opportunity summary by sales stage deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
ed099bcd85 refactor(test): make queries deterministic 2026-03-18 20:59:38 +05:30
ruthra kumar
d81fd25325 refactor(test): make item wise details deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
2eec0f704c refactor(test): make accounts controller deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
b4245e9353 refactor(test): make subcontracting controller deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
323a3dd573 refactor(test): make test mapper deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
56a5ddae8f refactor(test): make item wise inventory account deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
a3d8bb8d21 refactor(test): make distributed discount deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
18fe191929 refactor(test): make requested items order and receive deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
f4d355a0e4 refactor(test): make accounts/test/test_utils.py deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
0ef004ce48 refactor(test): make gross profit deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
47cae808c5 refactor(test): make sales payment summary deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
1689d6a9fc refactor(test): make consolidated trial balance report deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
12ae84401a refactor(test): remove redundant tearDown, tearDownClass and rollback 2026-03-18 20:59:37 +05:30
ruthra kumar
8090caa026 refactor(test): make inventory dimension deterministic
fixed flaky test 'test_inventory_dimension'

use '3' precision for test_opening_balnace
2026-03-18 20:59:37 +05:30
ruthra kumar
ff87eedd96 refactor(test): make item group deterministic
'Item Group C' follows 'Item Group B'. So `lft` will increase while
`rgt` stays the same.
2026-03-18 20:59:37 +05:30
ruthra kumar
57f94b3ac2 refactor(test): make packed item deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
3b65364828 chore: typo 2026-03-18 20:59:37 +05:30
ruthra kumar
b5db1e9e1f refactor(test): remove redundant create_asset_category 2026-03-18 20:59:37 +05:30
ruthra kumar
79c23fc6c6 refactor(test): make sales invoice deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
31718d2066 refactor(test): make item group deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
cd499d4955 refactor(test): make timesheet deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
4484863baa refactor(test): make task deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
ddcd8a03ee refactor(test): make project deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
ce50e23536 refactor(test): make maintenance schedule deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
3c904cbc5f refactor(test): make leads deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
06ddc80292 refactor(test): make purchase order deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
7da61621cc refactor(test): make asset repair deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
075fe3f668 refactor(test): make asset deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
b2242d3cce refactor(test): make loyalty point entry deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
c55628a55d refactor(test): make dunning deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
3a5869e525 refactor(test): make budget deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
bb51e3147c refactor(test): make auto match party deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
5415e2ca82 refactor(test): make bank clearance deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
e6885af96b refactor(test): remove explicit commit and dead code 2026-03-18 20:59:37 +05:30
ruthra kumar
6d86bfe2e3 refactor(test): rollback on tearDown 2026-03-18 20:59:37 +05:30
ruthra kumar
70059d1ec0 refactor(test): make irs supplier test deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
d2da518e02 refactor(test): make party specific item deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
d119e3a8e8 refactor(test): make subcontracting receipt deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
577be4f9ad refactor(test): make purchase receipt deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
8dd9ab6475 refactor(test): make stock reconciliation deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
ee8e96dbcf refactor(test): make subcontracting order deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
faaad3ae8e refactor(test): make purchase receipt deterministic 2026-03-18 20:59:37 +05:30
ruthra kumar
c5f2ef454f refactor(test): make material request deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
7224dcce26 refactor(test): make stock ledger entry deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
f758ee4adc refactor(test): make item deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
26d7900590 refactor(test): make work order deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
2d1db2e403 refactor(test): make purchase receipt deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
4111d4ee1d refactor: fix logical bug and make stock settings test deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
d8be59b1ba refactor(test): make stock entry deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
c38696157c refactor(test): make serial no deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
dab31bc36d refactor(test): make serial and batch bundle deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
d790a1d3a6 refactor(test): make pick list deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
298960bfc6 refactor(test): make packed item deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
b8437f7f22 refactor(test): make material request deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
db49e6d830 refactor(test): make LCV deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
7853b779bd refactor(test): make item price deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
23cdd82de1 refactor(test): make delivery trip deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
5c85074f54 refactor(test): make delivery note deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
8d20da91d1 refactor(test): make transaction deletion record deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
0b046647e7 refactor(test): make item group deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
9231dbbb2f refactor(test): make employee deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
0dbd10893e refactor(test): make department deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
f2a85fd134 refactor(test): make currency exchange deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
7a8ece76ea refactor(test): make test deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
8b720ffd4f refactor(test): make project deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
6e3ea35dda refactor(test): make sales order deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
a4f8920d97 refactor(test): make quotation deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
7b8e15c5b8 refactor(test): make production plan deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
464c09ed10 refactor(test): make job card tests deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
bfb8837c54 refactor(test): make bom tests deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
7b26a4c2eb refactor(test): make bom update tool tests deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
8c5276c5e1 refactor(test): make plaid settings deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
2516cdafcb refactor(test): make financial reports deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
fcee9ad778 refactor(test): make sales invoice deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
5b0c41a3f7 refactor(test): make pos invoice deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
f5e69f2602 refactor(test): better setup for loyalty point and POS Invoice 2026-03-18 20:59:36 +05:30
ruthra kumar
d69d2c374f refactor(test): pos invoice tests are almost deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
524118e108 refactor(test): make timesheet and activity type deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
b64231ce2e refactor(test): make maintenance schedule deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
1a6358ec70 refactor(test): make prospect deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
0b2dbcf30c refactor(test): make opportunity deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
3b5667c007 refactor(test): remove empty IntegrationTestCase 2026-03-18 20:59:36 +05:30
ruthra kumar
e490d5044b refactor(test): make tax withholding tests deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
87f0247f2b refactor(test): ensure new bankers rounding method is set 2026-03-18 20:59:36 +05:30
ruthra kumar
91875fdf8d refactor(test): set precision in class setup 2026-03-18 20:59:36 +05:30
ruthra kumar
3dc3b2b64e refactor(test): make sales invoice tests deterministic
- allow_negative_stock is required for test_taxes_merging_from_delivery_note
2026-03-18 20:59:36 +05:30
ruthra kumar
eb70060798 refactor(test): make purchase invoice tests deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
2edbbb6052 refactor: avoid name clash 2026-03-18 20:59:36 +05:30
ruthra kumar
c2e9a91a94 refactor(test): handle setup of Workstation Operation Component 2026-03-18 20:59:36 +05:30
ruthra kumar
81ef8655c2 refactor(tests): make asset maintenance tests deterministic 2026-03-18 20:59:36 +05:30
ruthra kumar
def64ae864 refactor(test): incorrect fieldname for abbrevation 2026-03-18 20:59:36 +05:30
ruthra kumar
379f12daee refactor(test): make asset repair tests deterministic 2026-03-18 20:59:35 +05:30
ruthra kumar
cee55a1518 refactor(test): make supplier quotation deterministic 2026-03-18 20:59:35 +05:30
ruthra kumar
1560619fe0 refactor(test): install supplier scorecard presets 2026-03-18 20:59:35 +05:30
ruthra kumar
5b20935235 chore: remove default templated test case 2026-03-18 20:59:35 +05:30
ruthra kumar
4eb23df627 refactor(test): set_user utility method 2026-03-18 20:59:35 +05:30
ruthra kumar
253fbc2a70 refactor: replace all IntegrationTestCase -> ERPNextTestSuite 2026-03-18 20:59:35 +05:30
ruthra kumar
ea2763432d refactor: utility to return default supplier scorecards 2026-03-18 20:59:35 +05:30
ruthra kumar
03a64b67d9 refactor(test): flaky test in lead 2026-03-18 20:59:35 +05:30
ruthra kumar
2309bea1a0 refactor(test): flaky tax rule testsuite
- Make Sales Stage preset
2026-03-18 20:59:35 +05:30
ruthra kumar
3c14621ae0 refactor(test): load shipping rule records 2026-03-18 20:59:35 +05:30
ruthra kumar
27474eceee refactor(test): fix flaky shareholder test 2026-03-18 20:59:35 +05:30
ruthra kumar
36a9893558 refactor(test): fix flaky process deferred accounting tests 2026-03-18 20:59:35 +05:30
ruthra kumar
d37f2ada65 refactor(test): flaky pricing rule tests 2026-03-18 20:59:35 +05:30
ruthra kumar
c0647cf93b refactor(test): flaky stock entry; load records json 2026-03-18 20:59:35 +05:30
ruthra kumar
95d6bbe7ad refactor(test): flaky pos invoice merge log test 2026-03-18 20:59:35 +05:30
ruthra kumar
aeae6d4a10 refactor(test): flaky post invoice test 2026-03-18 20:59:35 +05:30
ruthra kumar
0914fd695d refactor(test): flaky pos invoice test; load stock entry json 2026-03-18 20:59:35 +05:30
ruthra kumar
a5a6a3bc9c refactor(test): flaky PE test; load currency exchange record 2026-03-18 20:59:35 +05:30
ruthra kumar
56542c805a refactor: load journal entry test records and make holiday list 2026-03-18 20:59:35 +05:30
ruthra kumar
6041574209 refactor: utility to load JSON records 2026-03-18 20:59:35 +05:30
ruthra kumar
0b14d1fe34 refactor(test): update system settings in super() 2026-03-18 20:59:35 +05:30
ruthra kumar
6572dc286a refactor(test): flaky test setup in pos closing entry 2026-03-18 20:59:35 +05:30
ruthra kumar
223737cbe2 refactor(test): fix flaky test setup for opening invoice creation 2026-03-18 20:59:35 +05:30
ruthra kumar
b00df01817 refactor(test): flaky test setup in Exchange Rate Revaluation 2026-03-18 20:59:35 +05:30
ruthra kumar
ce8ce10ef1 refactor(test): flaky test data setup for coupon code 2026-03-18 20:59:35 +05:30
ruthra kumar
97b922f9f1 refactor(test): make price list - more test records 2026-03-18 20:59:35 +05:30
ruthra kumar
92f0175e91 refactor(test): flaky test data in bank reconciliation tool 2026-03-18 20:59:35 +05:30
ruthra kumar
66c7815369 refactor(test): call super() method first 2026-03-18 20:59:35 +05:30
ruthra kumar
f6b6c93c10 refactor(test): make customer 2026-03-18 20:59:35 +05:30
ruthra kumar
8393c1b4f6 refactor(test): make price list and update selling settings 2026-03-18 20:59:35 +05:30
ruthra kumar
20b835a53b refactor(test): make item attribute 2026-03-18 20:59:35 +05:30
ruthra kumar
1fb26b5989 refactor(test): make test accounts 2026-03-18 20:59:35 +05:30
ruthra kumar
59144e03bc refactor(test): make item tax template 2026-03-18 20:59:35 +05:30
ruthra kumar
0feedd183b refactor(test): make uom 2026-03-18 20:59:35 +05:30
ruthra kumar
402c7df643 refactor(test): make item group 2026-03-18 20:59:35 +05:30
ruthra kumar
526fc1778f refactor(test): make item 2026-03-18 20:59:35 +05:30
ruthra kumar
aa76fc5d7c refactor(test): make warehouse 2026-03-18 20:59:35 +05:30
ruthra kumar
a769c71642 chore: typo in setup method 2026-03-18 20:59:35 +05:30
ruthra kumar
3ea1283613 refactor(test): make persistent location 2026-03-18 20:59:35 +05:30
ruthra kumar
6fc0a53bae refactor(test): setup fiscal years without any gap 2026-03-18 20:59:35 +05:30
ruthra kumar
c6b661526d refactor(test): make cost center 2026-03-18 20:59:35 +05:30
ruthra kumar
0c8145e924 refactor: suppress welcome mail 2026-03-18 20:59:35 +05:30
ruthra kumar
033e826242 refactor(test): even more master data setup 2026-03-18 20:59:35 +05:30
ruthra kumar
783d51e8cc refactor(test): make all presets in setupclass 2026-03-18 20:59:35 +05:30
ruthra kumar
aff6452075 refactor: temporary standing decorator for change_settings 2026-03-18 20:59:35 +05:30
ruthra kumar
33f4791698 refactor: replace IntegrationTestCase with ERPNextTestCase repo-wide
- import ERPNextTestSuite
 - use it on test class
2026-03-18 20:59:35 +05:30
ruthra kumar
4027b82714 refactor(test): bare bones presets for company 2026-03-18 20:59:34 +05:30
ruthra kumar
5c112daa1e refactor(test): make persistent company records
'test_coa_based_on_country_template' made deterministic
2026-03-18 20:59:34 +05:30
ruthra kumar
a00814d849 refactor(test): IntegraionTestCase -> python's built-in TestCase 2026-03-18 20:59:34 +05:30
ruthra kumar
3cee89d827 chore: drop dead hook 2026-03-18 20:59:34 +05:30
ruthra kumar
2447042060 chore: remove global dependencies 2026-03-18 20:59:34 +05:30
ruthra kumar
319e220efe chore: remove IGNORE_TEST_RECORD_DEPENDENCIES 2026-03-18 20:59:34 +05:30
ruthra kumar
8eef42d075 chore: remove EXTRA_TEST_RECORD_DEPENDENCIES 2026-03-18 20:59:34 +05:30
ruthra kumar
002b4fb048 chore: delete all test_records.json 2026-03-18 20:59:34 +05:30
ruthra kumar
4167609e41 ci: run parallel test in lightmode
- modify individual test CI. let it be dormat for now.

Acked-by: ruthra kumar <ruthra@erpnext.com>
2026-03-18 20:59:34 +05:30
Mihir Kandoi
6cb6a52ded fix: incorrect sle calculation when doc has project (#53599) 2026-03-18 13:19:30 +00:00
rohitwaghchaure
0d8f6b05e3 Merge pull request #53246 from aerele/stock-entry-cost-center
feat: add cost center field to the stock entry accounting dimension tab
2026-03-18 11:49:01 +05:30
Lakshit Jain
072ec9b7ae fix: initialize all tax columns to resolve Key error in item_wise_sales_register and item_wise_purchase_register reports (#53323) 2026-03-17 23:37:06 +05:30
Mihir Kandoi
aba1f34de0 Modify CODEOWNERS to include additional owners (#53575) 2026-03-17 17:07:48 +00:00
Sudharsanan Ashok
31d14df37b fix(stock): add company filter while fetching batches (#53369) 2026-03-17 16:39:21 +00:00
Mihir Kandoi
b433852f8a chore: make supplier data expanded by default in PI (#53565) 2026-03-17 22:08:17 +05:30
Sudharsanan Ashok
fe5f16cb18 fix(stock): fix the property setter (#53422) 2026-03-17 22:02:41 +05:30
mergify[bot]
fe85dc10cc fix(italy): fix e-invoice ScontoMaggiorazione structure and included_in_print_rate support (backport #53334) (#53568)
Co-authored-by: Arturo <tamburro92@users.noreply.github.com>
2026-03-17 22:01:15 +05:30
Khushi Rawat
445aef7d17 Merge pull request #53446 from Kesavan-code/Fix-53445
fix: fetch accounting dimensions from child row in asset creation
2026-03-17 21:37:34 +05:30
Mihir Kandoi
f319857939 chore: add documentation link in valuation method field (#53564) 2026-03-17 15:32:29 +00:00
Sudharsanan Ashok
517310182e fix(manufacturing): update working hours validation (#53559) 2026-03-17 20:47:46 +05:30
diptanilsaha
3ff2871f24 fix(sales_invoice): reset payment methods on pos_profile change (#53514) 2026-03-17 19:29:30 +05:30
Soham Kulkarni
72835f9a58 Merge pull request #53322 from sokumon/add-clear-demo-data 2026-03-17 17:05:51 +05:30
ruthra kumar
dd4b83906d Merge pull request #53535 from aerele/remove-payables-receivables-workspace-v16
fix: remove payables and receivables workspace
2026-03-17 17:03:02 +05:30
ruthra kumar
41fbb916a0 fix: incorrect user perms in queries (#53548)
* chore: remove incorrect import

* fix: use qb to prevent incorrect sql due to user permissions
2026-03-17 16:32:05 +05:30
ruthra kumar
04b967bd6d fix: use qb to prevent incorrect sql due to user permissions 2026-03-17 16:06:54 +05:30
sokumon
ed3444de5a fix: use same label 2026-03-17 15:48:24 +05:30
Mihir Kandoi
ef09cffa58 chore: initiate release twice in a week (#53543) 2026-03-17 10:17:02 +00:00
Nishka Gosalia
49581e7408 fix: Creating new item price incase of changes in expired item price (#53534)
Co-authored-by: Nishka Gosalia <nishkagosalia@Nishkas-MacBook-Air.local>
2026-03-17 15:32:17 +05:30
ruthra kumar
fc2edfbded chore: remove incorrect import 2026-03-17 15:23:05 +05:30
rohitwaghchaure
13765e7557 Merge pull request #53500 from rohitwaghchaure/fixed-valuation-for-non-batchwise-valuation-batches
fix: valuation rate for no Use Batch wise Valuation batches
2026-03-17 14:12:15 +05:30
Rohit Waghchaure
4befa15198 fix: valuation rate for no Use Batch wise Valuation batches 2026-03-17 13:17:00 +05:30
ravibharathi656
26a9646407 fix: remove payables and receivables workspace 2026-03-17 12:36:57 +05:30
Jatin3128
a9e52833fe fix(Payment Entry): split orders as per the schedules in the refrence table 2026-03-17 11:28:48 +05:30
Abdus Samad
65ed936ff3 fix: add item_name to quick entry fields in Item doctype (#53530) 2026-03-17 10:56:30 +05:30
Nikhil Kothari
ef32622166 fix(banking): include paid purchase invoices in reports and bank clearance (#52675)
* fix(banking): include paid purchase invoices in reports and bank clearance

* fix: condition for amounts not reflected in system

* fix: set Sales Invoice to be the payment document in bank rec

* fix: add additional filter for `is_paid`

* fix: added is_paid

* fix: added invoice number in bank clearance tool

* chore: make requested changes

* fix: exclude opening JEs

* fix: bring back banking icon in desktop
2026-03-17 10:17:32 +05:30
Jeraldin P J
e2667ab098 fix: enable logs to track changes in doctype. (#53491)
Co-authored-by: jeraldin2003 <jeraldin2003>
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2026-03-16 18:21:26 +00:00
Sanjesh-Raju
0a38389bc3 fix: correct overlap detection in JobCard.has_overlap (#53473)
Co-authored-by: Sanjesh <rsanjesh64@gmail.com>
Co-authored-by: Tridots Tech <info@tridotstech.com>
2026-03-16 18:18:30 +00:00
Nishka Gosalia
953f089c06 feat: Adding requested qty in packed item (#53486)
* feat: Adding requested qty in packed item

* fix: correct import path

---------

Co-authored-by: Nishka Gosalia <nishkagosalia@Nishkas-MacBook-Air.local>
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2026-03-16 18:09:39 +00:00
rohitwaghchaure
87785a2886 Merge pull request #53513 from rohitwaghchaure/fixed-do-not-set-rate-for-si
fix: do not set valuation rate for invoice without update stock
2026-03-16 23:32:52 +05:30
Abdus Samad
4cd150ba7a fix: change "Date" label to "Posting Date" in Sales Invoice and Purchase Invoice (#53503) 2026-03-16 17:57:44 +00:00
Rohit Waghchaure
bec9e48435 fix: do not set valuation rate for invoice without update stock 2026-03-16 23:08:55 +05:30
Shllokkk
0ef7594536 Merge pull request #53223 from Shllokkk/dashboard-chart-fix
Bank balance chart fix for payments dashboard
2026-03-16 20:01:39 +05:30
diptanilsaha
09dd2f851d fix(support-settings): disable the auto-close tickets feature if close_issue_after_days is set to 0 (#53499) 2026-03-16 11:47:01 +00:00
rohitwaghchaure
b5d24f5971 Merge pull request #53495 from rohitwaghchaure/fixed-support-62674
fix: stock adjustment entry
2026-03-16 15:17:12 +05:30
Rohit Waghchaure
af3067ee23 fix: stock adjustment entry 2026-03-16 14:51:09 +05:30
diptanilsaha
5f2c24a199 fix(p&l_statement): disable accumulated value filter by default (#53488) 2026-03-16 07:18:06 +00:00
Mihir Kandoi
fd7d5bdae1 fix: use bom source warehouse in WO created from PP (#53478) 2026-03-16 10:46:28 +05:30
Mihir Kandoi
ebb4a3d053 fix: use bom source warehouse in WO created from PP 2026-03-16 10:29:31 +05:30
Jeraldin P J
c09ea94133 fix: remove supplier selection dialog when creating Purchase Order from Material Request (#53391)
Co-authored-by: jeraldin2003 <jeraldin2003>
Co-authored-by: Nikhil Kothari <nik.kothari22@live.com>
2026-03-16 09:45:30 +05:30
Raffael Meyer
9e8c70e6b4 chore: add docs to project URLs (#53467) 2026-03-15 13:36:00 +00:00
MochaMind
008b296014 chore: update POT file (#53464) 2026-03-15 14:31:26 +01:00
sokumon
413b119ec6 fix: add icon in clear demo data 2026-03-15 17:49:32 +05:30
diptanilsaha
7a8d1931ed fix(serial_and_batch_bundle_selector): handle CSV attachment properly (#53460) 2026-03-15 12:58:58 +05:30
Mihir Kandoi
5ba6446451 fix: sales order indicator should be based on available qty rather th… (#53456) 2026-03-15 09:43:11 +05:30
Mihir Kandoi
708e4fa2be fix: sales order indicator should be based on available qty rather than delivered qty 2026-03-15 09:41:32 +05:30
[Kesavan-001]
e0fb31f81e Fix:Cost center mapping issue 2026-03-14 13:26:46 +05:30
[Kesavan-001]
a084feba96 Fix:Cost center mapping issue 2026-03-14 12:50:47 +05:30
[Kesavan-001]
10fe8580d5 Fix:Cost center mapping issue 2026-03-14 12:39:48 +05:30
David
b5a21855f6 feat(stock): implement fallback logic for Delivery Trip address mapping (#53260) 2026-03-14 05:41:19 +00:00
diptanilsaha
c99598e22e Merge pull request #53309 from frappe/l10n_develop 2026-03-14 02:39:06 +05:30
Sagar Vora
be85ecba1b Merge pull request #53430 from sagarvora/auto-cancel-exempt
fix: exempt ledger entries and closing balance from auto-cancellation
2026-03-13 18:06:21 +00:00
Sagar Vora
c069a1787d fix: hide cancel button from ledger / closing balance doctypes 2026-03-13 23:20:42 +05:30
MochaMind
67a80127e3 fix: Portuguese, Brazilian translations 2026-03-13 23:07:09 +05:30
Sagar Vora
56efe5e82c fix: exempt ledger entries and account closing balance from auto-cancellation 2026-03-13 23:03:13 +05:30
Shllokkk
8e5692d8a3 feat(report): add service start/end date and amount with roll-ups in deferred revenue/expense report 2026-03-13 21:31:37 +05:30
ruthra kumar
b1c1bca2b8 Merge pull request #53423 from ruthra-kumar/remove_fw_added_total_rows_from_trends_reports
refactor: disable total row in trends report
2026-03-13 18:02:05 +05:30
ruthra kumar
4dbc72b301 refactor: disable total row in trends report 2026-03-13 17:37:04 +05:30
ruthra kumar
b9a47d85db Merge pull request #53415 from ruthra-kumar/broken_cost_center_filter_in_get_outstanding_documents
fix: broke cost center filter in get outstanding reference docs
2026-03-13 15:24:28 +05:30
ruthra kumar
7dfe36fdce fix: broke cost center filter in get outstanding reference docs 2026-03-13 14:55:56 +05:30
Khushi Rawat
e85eb90ec7 Merge pull request #53416 from khushi8112/subsidiary-companies-value-in-purchase-analytics
feat: show subsidiary companies value in purchase analytics
2026-03-13 14:42:06 +05:30
khushi8112
9f755ad65a feat: show subsidiary companies value in purchase analytics 2026-03-13 14:37:11 +05:30
Mihir Kandoi
bd87a7e612 Revert "fix(regional): rename duplicate Customer fields in Italy setup" (#53409) 2026-03-13 07:27:32 +00:00
ljain112
e68f149d3a fix: correct item valuation when "Deduct" is used in Purchase Invoice and Receipt. 2026-03-13 11:53:08 +05:30
Smit Vora
20fc9c7b18 Merge pull request #53396 from vorasmit/same-phantom-different-fg 2026-03-13 09:44:42 +05:30
Khushi Rawat
f08293efec Merge pull request #53390 from khushi8112/asset-purchase-amount-currency
refactor: show company currency in purchase amount label
2026-03-13 00:47:37 +05:30
khushi8112
6219a9e6f0 fix: update label on company change 2026-03-13 00:27:43 +05:30
khushi8112
b4c82c0f1a refactor: show company currency in purchase amount label 2026-03-13 00:27:43 +05:30
MochaMind
7362f2e5fb fix: Portuguese, Brazilian translations 2026-03-12 23:05:16 +05:30
MochaMind
62715787c1 fix: Swedish translations 2026-03-12 23:05:07 +05:30
Smit Vora
b1e1c65774 chore: phantom qty unused in sub_assembly_items 2026-03-12 21:16:03 +05:30
Smit Vora
1975ae4486 test: ensure phantom BOM explosion across all items 2026-03-12 20:31:56 +05:30
Solede
c6efc403cd fix(regional): rename duplicate Customer fields in Italy setup (#50921)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 20:25:35 +05:30
Smit Vora
e57de4311c fix: correctly group RMs of same phantom from different FG 2026-03-12 20:21:18 +05:30
Mihir Kandoi
999a72a16a fix: get_item_tax_info type hints (#53392) 2026-03-12 14:07:49 +00:00
Sagar Vora
d8a56e9943 Merge pull request #53395 from shubhdoshi21/flag-fix
fix: update invalid syntax for flags
2026-03-12 12:39:22 +00:00
Shubh Doshi
c6e6859090 fix: update invalid syntax for flags 2026-03-12 17:52:10 +05:30
Shubh Doshi
ad8c05426e fix: make ledger entries submittable and cleanup invalid test submissions (#52921)
* fix: enable submittability for ledger entries and cleanup invalid test submissions

* fix: reverted child table submittability

* fix: added ignore_links flag for back gl entry

* fix: add ignore_links for reconcile,cancelled PLE,cancelled SLE

* fix: update test_recreate_stock_ledgers to use db.delete instead of doc.delete

* chore: temporary test against frappe PR 37009

* fix: make Advance Payment Ledger Entry submittable

* refactor: add extra line for create_shipping_rule

* chore: revert temporary test against frappe PR 37009

* fix: use parent doc save with ignore_validate_update_after_submit for child table updates

* chore: temporary test against frappe PR 37009

* chore: revert temporary test against frappe PR 37009

* fix: use skip_docstatus_validation
2026-03-12 16:27:51 +05:30
Khushi Rawat
0e888cc86b Merge pull request #53379 from khushi8112/correct-filter-for-asset-in-purchase-receipt
fix: use correct filter to get the composite assets
2026-03-12 15:10:34 +05:30
khushi8112
f5a3227349 fix: use correct filter to get the composite assets 2026-03-12 14:51:25 +05:30
Mihir Kandoi
7f644785ce fix: do not modify rate in the child item merely for comparison (#53301) 2026-03-12 14:30:00 +05:30
Mihir Kandoi
3bb18d0baf fix: precision issue in production plan (#53370) 2026-03-12 14:26:29 +05:30
Krishna Shirsath
831b1d3a79 feat(employee): Refactor milestone indicator functions to accept 'today' parameter 2026-03-12 14:19:15 +05:30
Khushi Rawat
bef4c010c6 Merge pull request #53371 from khushi8112/asset-repair-show-general-ledger
fix: move show_general_ledger to Asset Repair form events
2026-03-12 14:05:20 +05:30
khushi8112
ac124bdc7e fix: move show_general_ledger to Asset Repair form events 2026-03-12 13:18:00 +05:30
Mihir Kandoi
9c0c39381f fix: add validation in bom creator function (#53364) 2026-03-12 06:48:54 +00:00
Mihir Kandoi
b1ff4daaf5 fix: NoneType error when template description is to be copied to variant (#53358) 2026-03-12 06:33:28 +00:00
Mihir Kandoi
cb05f8a67a refactor: supplier quotation comparision report button should start f… (#53361) 2026-03-12 06:15:47 +00:00
Mihir Kandoi
8d5566e783 refactor: add type hints required flag to hooks.py (#53356) 2026-03-12 11:42:46 +05:30
Mihir Kandoi
417066d188 refactor: add type hints required flag to hooks.py 2026-03-12 11:08:24 +05:30
Ejaaz Khan
e4d79c6246 fix: remove redundant pos print format (#53348) 2026-03-12 05:11:53 +00:00
David
a3a57e20f1 Feat/shipment default contact (#53029) 2026-03-12 10:40:39 +05:30
NaviN
a8dcf70459 fix(delivery note): avoid maintaining si_detail on return delivery note (#52456) 2026-03-12 10:36:18 +05:30
Pandiyan P
a30599570c fix: handle NoneType error while creating a item (#53313) 2026-03-12 10:31:41 +05:30
V Shankar
e107d3ca84 fix: re-calculate taxes and totals after resetting bundle item rate (#53342) 2026-03-12 10:29:59 +05:30
Pandiyan P
77cf0afa1a fix: update child item schedule_date and prevent past dates (#53298) 2026-03-12 09:57:38 +05:30
Shllokkk
56f597f5ad fix(email_campaign): prevent unsubscribing entire campaign when email group member unsubscribes 2026-03-12 00:54:40 +05:30
MochaMind
793db90a14 fix: Portuguese, Brazilian translations 2026-03-11 23:09:41 +05:30
Krishna Shirsath
e4a0d2ab0b feat(employee): Enhance milestone indicators for birthdays and work anniversaries 2026-03-11 22:38:42 +05:30
Deepesh Garg
9a4c7766e3 Merge pull request #53327 from Nihantra-Patel/fix-journal-entry-ignore-linked-doctypes
fix: Append existing ignored doctypes in Journal Entry on_cancel instead of overwriting
2026-03-11 16:10:37 +05:30
Mihir Kandoi
f1ac0376fb feat: co product by product support (#52979) 2026-03-11 14:46:36 +05:30
ruthra kumar
65c33e6b39 Merge pull request #53326 from ruthra-kumar/allow_cost_center_on_payment_entry_deductions
refactor: make cost center editable in payment entry deduction
2026-03-11 14:45:41 +05:30
Nihantra Patel
39e10c4ab0 fix: Append existing ignored doctypes in Journal Entry on_cancel instead of overwriting 2026-03-11 14:40:41 +05:30
ruthra kumar
38bdc99172 Merge pull request #53294 from ruthra-kumar/stop_v14_weekly_release
ci: drop v14 from weekly release
2026-03-11 14:38:38 +05:30
ruthra kumar
078b22d985 refactor: make cost center editable in payment entry deduction 2026-03-11 14:26:16 +05:30
Nishka Gosalia
0205341cb5 Merge pull request #53312 from creative-paramu/production_plan_item_description_update 2026-03-11 14:18:36 +05:30
nareshkannasln
fa34ebea94 fix: skip BudgetValidation when cancelling GL entries 2026-03-11 11:59:14 +05:30
Parameshwari Palanisamy
39e68a9ce7 Update production_plan.py 2026-03-11 11:41:24 +05:30
creative-paramu
19533551f4 fix: update item description in Production Plan Assembly Items table 2026-03-11 11:14:33 +05:30
MochaMind
f3b270c927 fix: Serbian (Cyrillic) translations 2026-03-10 23:06:36 +05:30
MochaMind
330216ff0d fix: Serbian (Latin) translations 2026-03-10 23:06:26 +05:30
MochaMind
86bad84504 fix: Swedish translations 2026-03-10 23:06:18 +05:30
MochaMind
24e0c4034d fix: Spanish translations 2026-03-10 23:06:09 +05:30
Shllokkk
17eb983c40 fix: sanitize genericode import inputs and secure XML parser 2026-03-10 21:15:33 +05:30
ruthra kumar
ac8f3d7f96 fix: set default list view columns and filters for sales, purchase and accounts module (#53256) 2026-03-10 17:52:17 +05:30
Abdeali Chharchhodawala
0d42faac2e Merge pull request #52636 from Abdeali099/Abdeali/india-coa
refactor: enhance chart of accounts for India with account categories
2026-03-10 17:21:37 +05:30
ruthra kumar
7cf7a967da Merge pull request #53071 from aerele/fix-gross-profit-qty-precision
fix(gross-profit): apply precision-based rounding to grouped totals
2026-03-10 16:37:41 +05:30
ruthra kumar
ee187065c6 ci: drop v14 from weekly release 2026-03-10 16:29:02 +05:30
rohitwaghchaure
ac8a0b7b3d Merge pull request #53283 from rohitwaghchaure/fixed-patch-not-exists
fix: removed non existent patch
2026-03-10 14:25:50 +05:30
Mihir Kandoi
567d6c5102 Merge pull request #53282 from mihir-kandoi/fix-qi-submission 2026-03-10 14:15:32 +05:30
rohitwaghchaure
20cdf744fd Merge pull request #53281 from rohitwaghchaure/fixed-better-validation-message-pi-with-update-stock
fix: better validation message for Purchase Invoice with Update Stock
2026-03-10 14:03:18 +05:30
Mihir Kandoi
9f62ec5192 fix: allow user to make QI after submission not working 2026-03-10 13:55:49 +05:30
Rohit Waghchaure
c4b3080eae fix: removed non existent patch 2026-03-10 13:55:36 +05:30
Rohit Waghchaure
cfb06cf247 fix: better validation message for Purchase Invoice with Update Stock 2026-03-10 13:36:11 +05:30
Mihir Kandoi
53238ba94f Merge pull request #53203 from aerele/employee-user-status 2026-03-10 13:09:08 +05:30
Mihir Kandoi
1da71fee2b Merge pull request #53235 from aerele/fix/sales-order-delivery-date 2026-03-10 12:52:53 +05:30
Priyal Rawal
a6e78c2eea fix: add permission checks in whitelisted functions (#53103) 2026-03-10 07:04:15 +00:00
ruthra kumar
f2f47d6d88 Merge pull request #53238 from vorasmit/regional-rounding
fix: use return value of `get_round_off_applicable_accounts`
2026-03-10 12:28:16 +05:30
rohitwaghchaure
8d470b92db Merge pull request #53272 from rohitwaghchaure/fixed-patch-falling
fix: patch failing
2026-03-10 12:01:42 +05:30
Rohit Waghchaure
6024c4a077 fix: patch failing 2026-03-10 11:44:20 +05:30
MochaMind
b0ec75d539 fix: sync translations from crowdin (#53262) 2026-03-09 20:49:12 +01:00
ruthra kumar
cd7845124c fix: allow payment_request to be created in draft (#53160) 2026-03-09 20:21:33 +05:30
Shllokkk
2e844a58fb perf: optimize account balance data fetching for Chart Of Accounts 2026-03-09 20:09:03 +05:30
rohitwaghchaure
5ca8641488 Merge pull request #53254 from rohitwaghchaure/fixed-github-53253
fix: bom UX issues
2026-03-09 18:17:33 +05:30
Nabin Hait
9cf529215f fix: set default list view columns and filters for sales, purchase and accounts module 2026-03-09 17:20:52 +05:30
Rohit Waghchaure
32447b8204 fix: bom UX issues 2026-03-09 16:25:08 +05:30
Krishna Shirsath
be819eb876 fix(employee): correct work anniversary message pluralization 2026-03-09 16:06:55 +05:30
Nishka Gosalia
af817b8134 Merge pull request #53249 from nishkagosalia/purchase-order-button-fix 2026-03-09 15:05:42 +05:30
Nishka Gosalia
829dbbe12b fix :buttons not visible on purchase and sales order 2026-03-09 15:02:31 +05:30
Khushi Rawat
9c27d66add Merge pull request #53242 from khushi8112/asset-report-query-builder
refactor: replace raw SQL with query builder in asset depreciation and balances report
2026-03-09 14:57:29 +05:30
sudarshan-g
47772f4e77 feat: add cost center field to the stock entry accounting dimension tab 2026-03-09 13:32:59 +05:30
rohitwaghchaure
563184920a Merge pull request #53239 from rohitwaghchaure/fixed-validation-for-docstatus
fix: validation for cancellation
2026-03-09 13:18:56 +05:30
Pandiyan37
77367b5517 fix(selling): update delivery date in line items 2026-03-09 13:10:01 +05:30
Krishna Pramod Shirsath
2b8a4a9b5f Merge branch 'frappe:develop' into feat/employee-milestone-indicators 2026-03-09 13:06:20 +05:30
Krishna Shirsath
7e8a830f42 feat(employee): Add birthdays and work anniversaries indicator in form 2026-03-09 13:01:52 +05:30
khushi8112
f496995415 refactor: more functions in same file 2026-03-09 12:56:24 +05:30
Krishna Shirsath
1f19175fef refactor(employee): remove anniversary indicator logic from employee form 2026-03-09 12:50:56 +05:30
khushi8112
314c882f3b refactor: replace raw SQL with query builder in asset depreciation and balannces report 2026-03-09 12:39:49 +05:30
Mihir Kandoi
adbe856c4e Merge pull request #53234 from aerele/fix/support-#61532 2026-03-09 12:33:46 +05:30
Rohit Waghchaure
8de272a8a1 fix: validation for cancellation 2026-03-09 12:05:46 +05:30
Krishna Pramod Shirsath
f8f61f0b81 Merge branch 'develop' into feat/employee-creation-and-lifecycle 2026-03-09 11:47:19 +05:30
Krishna Shirsath
053242d5bd fix(employee): add 'set_only_once' property to 'Create User Automatically' field 2026-03-09 11:12:12 +05:30
Smit Vora
56a073955a test: regional account correctly added to round off accounts 2026-03-09 06:19:42 +05:30
Smit Vora
5c6056e76b fix: use return value of get_round_off_applicable_accounts 2026-03-09 05:19:22 +05:30
diptanilsaha
bf38dea95f Merge pull request #53233 from frappe/pot_develop_2026-03-08 2026-03-08 22:56:51 +05:30
Sudharsanan11
ae9ff767fa feat(manufacturing): show disassembled qty in progress bar 2026-03-08 19:14:41 +05:30
Sudharsanan11
8027f5aafd fix(manufacturing): show returned qty in progress bar 2026-03-08 19:14:41 +05:30
frappe-pr-bot
cad6956935 chore: update POT file 2026-03-08 09:42:56 +00:00
ruthra kumar
d038ad2350 Merge pull request #53227 from ruthra-kumar/add_party_filter_on_comparison_report
refactor: party type and party filter for comparison report
2026-03-07 18:18:58 +05:30
ruthra kumar
b6f9c0844e refactor: party type and party filter for comparison report 2026-03-07 18:02:56 +05:30
Poovitha Palanivelu
194d060f13 fix: update user status depends on employee status 2026-03-06 12:27:24 +05:30
ervishnucs
24825a16e0 fix: allow payment_request to be created in draft 2026-03-04 16:25:30 +05:30
Navin-S-R
52dd7665e7 fix(gross-profit): apply precision-based rounding to grouped totals 2026-03-02 11:15:49 +05:30
Krishna Pramod Shirsath
66976c13e4 Merge branch 'develop' into feat/employee-creation-and-lifecycle 2026-02-27 13:10:24 +05:30
Krishna Shirsath
124ec4d3c2 fix: add missing type hints to whitelisted function arguments 2026-02-27 12:53:44 +05:30
Krishna Shirsath
4f43f655cf feat(employee): Add birthdays and work anniversaries indicator in form ,list view enhancements and new empty state. 2026-02-25 13:21:06 +05:30
Krishna Shirsath
870254b710 refactor(employee): reorganize joining and employee exit tabs at the end. 2026-02-19 17:14:50 +05:30
Krishna Shirsath
6513185cb7 refactor(employee): create user function -removed useless function calls 2026-02-19 17:00:35 +05:30
Krishna Shirsath
57f3048d27 feat(employee): Add automatic user creation feature and related validations. Create User on Import. 2026-02-19 15:51:53 +05:30
Krishna Shirsath
3b521b74ea feat(employee): Create User button and form. 2026-02-17 13:32:09 +05:30
887 changed files with 168713 additions and 127327 deletions

View File

@@ -1,4 +1,4 @@
### Introduction (first timers)
### Introduction (for first timers)
Thank you for your interest in raising an Issue with ERPNext. An Issue could mean a bug report or a request for a missing feature. By raising a bug report, you are contributing to the development of ERPNext and this is the first step of participating in the community. Bug reports are very helpful for developers as they quickly fix the issue before other users start facing it.
@@ -6,31 +6,31 @@ Feature requests are also a great way to take the product forward. New ideas can
When you are raising an Issue, you should keep a few things in mind. Remember that the developer does not have access to your machine so you must give all the information you can while raising an Issue. If you are suggesting a feature, you should be very clear about what you want.
The Issue list is not the right place to ask a question or start a general discussion. If you want to do that , then the right place is the forum [https://discuss.frappe.io](https://discuss.frappe.io/c/erpnext/6).
The Issue list is not the right place to ask a question or start a general discussion. If you want to do that, then the right place is the forum [https://discuss.frappe.io](https://discuss.frappe.io/c/erpnext/6).
### Reply and Closing Policy
If your issue is not clear or does not meet the guidelines, then it will be closed. If it is closed, please supply the information asked and re-open it.
If your issue is not clear or does not meet the guidelines, then it will be closed. If it is closed, please supply the requested information and re-open it.
### General Issue Guidelines
1. **Search existing Issues:** Before raising a Issue, search if it has been raised before. Maybe add a 👍 or give additional help by creating a mockup if it is not already created.
1. **Report each issue separately:** Don't club multiple, unreleated issues in one note.
1. **Brief:** Please don't include long explanations. Use screenshots and bullet points instead of descriptive paragraphs.
1. **Search existing Issues:** Before raising an Issue, search if it has been raised before. Maybe add a 👍 or give additional help by creating a mockup if it is not already created.
2. **Report each issue separately:** Don't club multiple, unrelated issues in one note.
3. **Brief:** Please don't include long explanations. Use screenshots and bullet points instead of descriptive paragraphs.
### Bug Report Guidelines
1. **Steps to Reproduce:** The bug report must have a list of steps needed to reproduce a bug. If we cannot reproduce it, then we cannot solve it.
1. **Version Number:** Please add the version number in your report. Often a bug is fixed in the latest version
1. **Clear Title:** Add a clear subject to your bug report like "Unable to submit Purchase Order without Basic Rate" instead of just "Cannot Submit"
1. **Screenshots:** Screenshots are a great way of communicating issues. Try adding annotations or using LiceCAP to take a screencast in `gif`.
2. **Version Number:** Please add the version number in your report. Often a bug is fixed in the latest version.
3. **Clear Title:** Add a clear subject to your bug report like "Unable to submit Purchase Order without Basic Rate" instead of just "Cannot Submit".
4. **Screenshots:** Screenshots are a great way of communicating issues. Try adding annotations or using LICEcap to take a screencast in `.gif` format.
### Feature Request Guidelines
1. **Clarity:** Clearly specify how do you want the feature to behave. Don't just say "I would like multiple PDF formats", say that "Ability to add multiple print formats for customers with different languages".
1. **Solution:** Try and identify how the feature should look like.
1. **Mockups:** Mockups are a great way to explain your requirement.
1. **Clarity:** Clearly specify how you want the feature to behave. Don't just say "I would like multiple PDF formats", instead say "Ability to add multiple print formats for customers with different languages".
2. **Solution:** Try to identify what the feature should look like.
3. **Mockups:** Mockups are a great way to explain your requirement.
### What if my Issue is closed
### What if my issue is closed
Don't worry, take the feedback, supply the correct information and re-open it!

View File

@@ -1,6 +1,6 @@
---
name: Feature request
about: Suggest an idea to improve ERPNext
about: Suggest an idea or enhancement for ERPNext
title: ''
labels: feature-request
assignees: ''
@@ -17,17 +17,21 @@ Welcome to ERPNext issue tracker! Before creating an issue, please heed the foll
3. When making a feature request, make sure to be as verbose as possible. The better you convey your message, the greater the drive to make it happen.
Please keep in mind that we get many many requests and we can't possibly work on all of them, we prioritize development based on the goals of the product and organization. Feature requests are still welcome as it helps us in research when we do decide to work on the requested feature.
Please keep in mind that we get many requests and we can't possibly work on all of them, we prioritize development based on the goals of the product and organization. Feature requests are still welcome as it helps us in research when we do decide to work on the requested feature.
If you're in urgent need to a feature, please try the following channels to get paid developments done quickly:
If you're in urgent need of a feature, please try the following channels to get paid developments done quickly:
1. Certified ERPNext partners: https://erpnext.com/partners
2. Developer community on ERPNext forums: https://discuss.frappe.io/c/framework/5
3. Telegram group for ERPNext/Frappe development work: https://t.me/erpnext_opps
-->
## Before Submitting
- [ ] I searched existing issues and confirmed this is not a duplicate
- [ ] This is a feature request, not a bug or support question
- [ ] For support: https://discuss.frappe.io/c/erpnext/6
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
A clear and concise description of what the problem is. Ex. As a [role], I have to [painful task] because [missing feature].
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
@@ -35,5 +39,17 @@ A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Impact**
<!-- Check one: -->
- [ ] Blocks critical workflow — no viable workaround
- [ ] Significant friction — workaround exists but is painful
- [ ] Nice to have — minor improvement
**Additional context**
Add any other context or screenshots about the feature request here.
**Environment**
- ERPNext Version: <!-- Find this in Help > About, e.g. v15.12.0 -->
- Frappe Version: <!-- Find this in Help > About, e.g. v15.10.0 -->
- Deployment: <!-- Frappe Cloud / Self-hosted / ERPNext Cloud -->

View File

@@ -1,39 +0,0 @@
module.exports = async ({ github, context, localeChanged }) => {
const pr = context.payload.pull_request.number
const { owner, repo } = context.repo
const { data: me } = await github.rest.users.getAuthenticated()
const botUser = me.login
const reviews = await github.rest.pulls.listReviews({
owner,
repo,
pull_number: pr
})
const botReview = reviews.data
.reverse()
.find(r => r.user.login === botUser && r.state === "CHANGES_REQUESTED")
if (localeChanged) {
if (!botReview) {
await github.rest.pulls.createReview({
owner,
repo,
pull_number: pr,
event: "REQUEST_CHANGES",
body: "Translations are managed through [Crowdin](https://crowdin.com/project/frappe/). Consider contributing through Crowdin."
})
}
} else {
if (botReview) {
await github.rest.pulls.dismissReview({
owner,
repo,
pull_number: pr,
review_id: botReview.id,
message: ""
})
}
}
}

View File

@@ -19,7 +19,7 @@ jobs:
strategy:
fail-fast: false
matrix:
version: ["14", "15", "16"]
version: ["15", "16"]
steps:
- uses: octokit/request-action@v2.x

View File

@@ -43,3 +43,6 @@ jobs:
- name: Run Semgrep rules
run: semgrep ci --config ./frappe-semgrep-rules/rules --config r/python.lang.correctness
- name: Semgrep for Test Correctness
run: semgrep ci --include=**/test_*.py --config ./semgrep/test-correctness.yml

View File

@@ -1,44 +0,0 @@
name: Prevent Locale Changes
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
check-locale:
permissions:
contents: read
runs-on: ubuntu-latest
if: github.actor != 'frappe-pr-bot'
# Exemption for the bot used for Crowdin Sync and POT File generation.
concurrency:
group: prevent-locale-changes-${{ github.event.pull_request.number }}
cancel-in-progress: true
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Detect locale changes
id: check
run: |
git fetch origin ${{ github.base_ref }}
if git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -q '^erpnext/locale/'; then
echo "locale_changed=true" >> $GITHUB_OUTPUT
else
echo "locale_changed=false" >> $GITHUB_OUTPUT
fi
- name: Manage locale review
uses: actions/github-script@v7
with:
github-token: ${{ secrets.RELEASE_TOKEN }}
script: |
const localeChanged = "${{ steps.check.outputs.locale_changed }}" === "true"
const handler = require('./.github/helper/locale_review.js')
await handler({ github, context, localeChanged })

View File

@@ -4,8 +4,8 @@ on:
workflow_dispatch:
concurrency:
group: server-individual-tests-develop-${{ github.event_name }}-${{ github.event.number || github.event_name == 'workflow_dispatch' && github.run_id || '' }}
cancel-in-progress: false
group: server-individual-tests-lightmode-develop
cancel-in-progress: true
permissions:
contents: read
@@ -21,7 +21,7 @@ jobs:
- id: set-matrix
run: |
# Use grep and find to get the list of test files
matrix=$(find . -path '*/doctype/*/test_*.py' | xargs grep -l 'def test_' | awk '{
matrix=$(find . -path '*/test_*.py' | xargs grep -l 'def test_' | sort | awk '{
# Remove ./ prefix, file extension, and replace / with .
gsub(/^\.\//, "", $0)
gsub(/\.py$/, "", $0)
@@ -58,6 +58,7 @@ jobs:
strategy:
fail-fast: false
matrix: ${{fromJson(needs.discover.outputs.matrix)}}
max-parallel: 14
name: Test
@@ -130,4 +131,13 @@ jobs:
FRAPPE_BRANCH: ${{ github.event.inputs.branch }}
- name: Run Tests
run: 'cd ~/frappe-bench/ && bench --site test_site run-tests --app erpnext --module ${{ matrix.test }}'
run: |
site_name=$(echo "${{matrix.test}}" | sed -e 's/.*\.\(test_.*$\)/\1/')
echo "$site_name"
mkdir ~/frappe-bench/sites/$site_name
cp -r "${GITHUB_WORKSPACE}/.github/helper/site_config_mariadb.json" ~/frappe-bench/sites/$site_name/site_config.json
cd ~/frappe-bench/
bench --site $site_name reinstall --yes
bench --site $site_name set-config allow_tests true
bench --site $site_name run-tests --module ${{ matrix.test }} --lightmode

View File

@@ -41,6 +41,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 60
env:
TZ: 'Asia/Kolkata'
NODE_ENV: "production"
WITH_COVERAGE: ${{ github.event_name != 'pull_request' }}
@@ -56,6 +57,7 @@ jobs:
mysql:
image: mariadb:10.6
env:
TZ: 'Asia/Kolkata'
MARIADB_ROOT_PASSWORD: 'root'
ports:
- 3306:3306
@@ -129,7 +131,7 @@ jobs:
FRAPPE_BRANCH: ${{ github.event.client_payload.sha || github.event.inputs.branch }}
- name: Run Tests
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --total-builds ${{ strategy.job-total }} --build-number ${{ matrix.container }} --with-coverage'
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --lightmode --app erpnext --total-builds ${{ strategy.job-total }} --build-number ${{ matrix.container }} --with-coverage'
env:
TYPE: server

View File

@@ -7,17 +7,17 @@ erpnext/accounts/ @ruthra-kumar
erpnext/assets/ @khushi8112
erpnext/regional @ruthra-kumar
erpnext/selling @ruthra-kumar
erpnext/support/ @ruthra-kumar
erpnext/buying/ @rohitwaghchaure @mihir-kandoi
erpnext/maintenance/ @rohitwaghchaure
erpnext/maintenance/ @rohitwaghchaure @mihir-kandoi
erpnext/manufacturing/ @rohitwaghchaure @mihir-kandoi
erpnext/quality_management/ @rohitwaghchaure
erpnext/quality_management/ @rohitwaghchaure @mihir-kandoi
erpnext/stock/ @rohitwaghchaure @mihir-kandoi
erpnext/subcontracting @mihir-kandoi
erpnext/subcontracting/ @mihir-kandoi
erpnext/projects/ @nishkagosalia
erpnext/controllers/ @ruthra-kumar @rohitwaghchaure @mihir-kandoi
erpnext/patches/ @ruthra-kumar
erpnext/patches/ @ruthra-kumar @rohitwaghchaure @mihir-kandoi
.github/ @ruthra-kumar
.github/ @ruthra-kumar @mihir-kandoi
pyproject.toml @ruthra-kumar

View File

@@ -1,12 +1,12 @@
<div align="center">
<a href="https://frappe.io/erpnext">
<img src="./erpnext/public/images/v16/erpnext.svg" alt="ERPNext Logo" height="80px" width="80xp"/>
<img src="./erpnext/public/images/v16/erpnext.svg" alt="ERPNext Logo" height="80px" width="80px"/>
</a>
<h2>ERPNext</h2>
<p align="center">
<div align="center">
<p>Powerful, Intuitive and Open-Source ERP</p>
</p>
</div>
[![Learn on Frappe School](https://img.shields.io/badge/Frappe%20School-Learn%20ERPNext-blue?style=flat-square)](https://frappe.school)<br><br>
[![CI](https://github.com/frappe/erpnext/actions/workflows/server-tests-mariadb.yml/badge.svg?event=schedule)](https://github.com/frappe/erpnext/actions/workflows/server-tests-mariadb.yml)
@@ -15,7 +15,7 @@
</div>
<div align="center">
<img src="./erpnext/public/images/v16/hero_image.png"/>
<img src="./erpnext/public/images/v16/hero_image.png" alt="ERPNext Hero Image"/>
</div>
<div align="center">
@@ -28,19 +28,19 @@
## ERPNext
100% Open-Source ERP system to help you run your business.
100% Open-Source ERP System to help you run your business.
### Motivation
Running a business is a complex task - handling invoices, tracking stock, managing personnel and even more ad-hoc activities. In a market where software is sold separately to manage each of these tasks, ERPNext does all of the above and more, for free.
Running a business is a complex task - handling invoices, tracking stock, managing personnel, and other daily operations. In a market where software is sold separately to manage each of these tasks, ERPNext does all of the above and more, for free.
### Key Features
- **Accounting**: All the tools you need to manage cash flow in one place, right from recording transactions to summarizing and analyzing financial reports.
- **Order Management**: Track inventory levels, replenish stock, and manage sales orders, customers, suppliers, shipments, deliverables, and order fulfillment.
- **Manufacturing**: Simplifies the production cycle, helps track material consumption, exhibits capacity planning, handles subcontracting, and more!
- **Asset Management**: From purchase to perishment, IT infrastructure to equipment. Cover every branch of your organization, all in one centralized system.
- **Projects**: Delivery both internal and external Projects on time, budget and Profitability. Track tasks, timesheets, and issues by project.
- **Asset Management**: From purchase to disposal, IT infrastructure to equipment. Covers every branch of your organization, all in one centralized system.
- **Projects**: Deliver both internal and external projects on time, budget and profitability. Track tasks, timesheets, and issues by project.
<details open>
@@ -53,7 +53,7 @@ Running a business is a complex task - handling invoices, tracking stock, managi
### Under the Hood
- [**Frappe Framework**](https://github.com/frappe/frappe): A full-stack web application framework written in Python and Javascript. The framework provides a robust foundation for building web applications, including a database abstraction layer, user authentication, and a REST API.
- [**Frappe Framework**](https://github.com/frappe/frappe): A full-stack web application framework written in Python and JavaScript. The framework provides a robust foundation for building web applications, including a database abstraction layer, user authentication, and a REST API.
- [**Frappe UI**](https://github.com/frappe/frappe-ui): A Vue-based UI library, to provide a modern user interface. The Frappe UI library provides a variety of components that can be used to build single-page applications on top of the Frappe Framework.
@@ -61,12 +61,12 @@ Running a business is a complex task - handling invoices, tracking stock, managi
### Managed Hosting
You can try [Frappe Cloud](https://frappecloud.com), a simple, user-friendly and sophisticated [open-source](https://github.com/frappe/press) platform to host Frappe applications with peace of mind.
You can try [Frappe Cloud](https://frappecloud.com), a simple, user-friendly, and sophisticated [open-source](https://github.com/frappe/press) platform to host Frappe applications reliably and securely.
It takes care of installation, setup, upgrades, monitoring, maintenance and support of your Frappe deployments. It is a fully featured developer platform with an ability to manage and control multiple Frappe deployments.
It handles installation, setup, upgrades, monitoring, maintenance, and support of your Frappe deployments. It is a fully featured developer platform with an ability to manage and control multiple Frappe deployments.
<div>
<a href="https://erpnext-demo.frappe.cloud/app/home" target="_blank">
<a href="https://erpnext-demo.frappe.cloud/app/home" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://frappe.io/files/try-on-fc-white.png">
<img src="https://frappe.io/files/try-on-fc-black.png" alt="Try on Frappe Cloud" height="28" />
@@ -75,25 +75,48 @@ It takes care of installation, setup, upgrades, monitoring, maintenance and supp
</div>
### Self-Hosted
#### Docker
Prerequisites: docker, docker-compose, git. Refer [Docker Documentation](https://docs.docker.com) for more details on Docker setup.
See [Frappe Docker Documentation](https://github.com/frappe/frappe_docker) for full documentation & FAQ on Docker setup
Run following commands:
#### Prerequisites
```
- [Docker](https://docs.docker.com/get-docker/)
- [Docker Compose v2](https://docs.docker.com/compose/)
- [git](https://docs.github.com/en/get-started/getting-started-with-git/set-up-git)
> For Docker basics and best practices refer to Docker's [documentation](https://docs.docker.com)
#### Demo setup
The fastest way to try ERPNext is to play in a pre-configured sandbox, in your browser, click the button below:
<a href="https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/frappe/frappe_docker/main/pwd.yml">
<img src="https://raw.githubusercontent.com/play-with-docker/stacks/master/assets/images/button.png" alt="Try in PWD"/>
</a>
### Try on your environment
> **⚠️ Disposable demo only**
>
> **This setup is intended for quick evaluation. Expect to throw the environment away.** You will not be able to install custom apps to this setup. For production deployments, custom configurations, and detailed explanations, see the full documentation.
First clone the repo:
```sh
git clone https://github.com/frappe/frappe_docker
cd frappe_docker
docker compose -f pwd.yml up -d
```
After a couple of minutes, site should be accessible on your localhost port: 8080. Use below default login credentials to access the site.
- Username: Administrator
- Password: admin
Then run:
See [Frappe Docker](https://github.com/frappe/frappe_docker?tab=readme-ov-file#to-run-on-arm64-architecture-follow-this-instructions) for ARM based docker setup.
```sh
docker compose -f pwd.yml up -d
```
Wait for a couple of minutes for ERPNext site to be created or check the `create-site` container logs before opening browser on port `8080`. (username: `Administrator`, password: `admin`)
See [Frappe Docker](https://github.com/frappe/frappe_docker/blob/main/docs/01-getting-started/03-arm64.md) for ARM based docker setup
## Development Setup
@@ -101,7 +124,7 @@ See [Frappe Docker](https://github.com/frappe/frappe_docker?tab=readme-ov-file#t
The Easy Way: our install script for bench will install all dependencies (e.g. MariaDB). See https://github.com/frappe/bench for more details.
New passwords will be created for the ERPNext "Administrator" user, the MariaDB root user, and the frappe user (the script displays the passwords and saves them to ~/frappe_passwords.txt).
New passwords will be created for the ERPNext "Administrator" user, the MariaDB root user, and the Frappe user (the script displays the passwords and saves them to ~/frappe_passwords.txt).
### Local
@@ -130,20 +153,20 @@ To setup the repository locally follow the steps mentioned below:
4. Open the URL `http://erpnext.localhost:8000/app` in your browser, you should see the app running
## Learning and community
## Learning and Community
1. [Frappe School](https://school.frappe.io) - Learn Frappe Framework and ERPNext from the various courses by the maintainers or from the community.
2. [Official documentation](https://docs.erpnext.com/) - Extensive documentation for ERPNext.
3. [Discussion Forum](https://discuss.frappe.io/c/erpnext/6) - Engage with community of ERPNext users and service providers.
3. [Discussion Forum](https://discuss.frappe.io/c/erpnext/6) - Engage with the community of ERPNext users and service providers.
4. [Telegram Group](https://erpnext_public.t.me) - Get instant help from huge community of users.
## Contributing
1. [Issue Guidelines](https://github.com/frappe/erpnext/wiki/Issue-Guidelines)
1. [Report Security Vulnerabilities](https://erpnext.com/security)
1. [Pull Request Requirements](https://github.com/frappe/erpnext/wiki/Contribution-Guidelines)
2. [Translations](https://crowdin.com/project/frappe)
2. [Report Security Vulnerabilities](https://erpnext.com/security)
3. [Pull Request Requirements](https://github.com/frappe/erpnext/wiki/Contribution-Guidelines)
4. [Translations](https://crowdin.com/project/frappe)
## Logo and Trademark Policy

View File

@@ -18,8 +18,9 @@ We will grant permission to use the ERPNext name and logo for projects that meet
- The primary purpose of your project is to promote the spread and improvement of the ERPNext software.
- Your project is non-commercial in nature (it can make money to cover its costs or contribute to non-profit entities, but it cannot be run as a for-profit project or business).
Your project neither promotes nor is associated with entities that currently fail to comply with the GPL license under which ERPNext is distributed.
- If your project meets these criteria, you will be permitted to use the ERPNext name and logo to promote your project in any way you see fit with one exception: Please do not use ERPNext as part of a domain name.
- Your project neither promotes nor is associated with entities that currently fail to comply with the GPL license under which ERPNext is distributed.
If your project meets these criteria, you will be permitted to use the ERPNext name and logo to promote your project in any way you see fit with one exception: Please do not use ERPNext as part of a domain name.
Use of the ERPNext name and logo is additionally allowed in the following situations:

View File

@@ -17,6 +17,15 @@ frappe.dashboards.chart_sources["Account Balance Timeline"] = {
fieldtype: "Link",
options: "Account",
reqd: 1,
default: locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"],
get_query: () => {
return {
filters: {
account_type: "Bank",
is_group: 0,
},
};
},
},
],
};

View File

@@ -4,7 +4,7 @@
import frappe
from frappe import _
from frappe.utils import add_to_date, formatdate, get_link_to_form, getdate, nowdate
from frappe.utils import add_to_date, formatdate, getdate, nowdate
from frappe.utils.dashboard import cache_source
from frappe.utils.dateutils import get_from_date_from_timespan, get_period_ending
from frappe.utils.nestedset import get_descendants_of
@@ -37,21 +37,14 @@ def get(
filters = frappe.parse_json(filters) or frappe.parse_json(chart.filters_json)
account = filters.get("account")
filters.get("company")
company = filters.get("company")
if not account and chart_name:
frappe.throw(
_("Account is not set for the dashboard chart {0}").format(
get_link_to_form("Dashboard Chart", chart_name)
)
)
if not frappe.db.exists("Account", account) and chart_name:
frappe.throw(
_("Account {0} does not exists in the dashboard chart {1}").format(
account, get_link_to_form("Dashboard Chart", chart_name)
)
)
if not company and not account:
frappe.throw(_("Company and account filters not set!"))
if not company:
frappe.throw(_("Company filter not set!"))
if not account:
frappe.throw(_("Account filter not set!"))
if not to_date:
to_date = nowdate()

View File

@@ -523,7 +523,8 @@ def make_gl_entries(
if gl_entries:
try:
make_gl_entries(gl_entries, cancel=(doc.docstatus == 2), merge_entries=True)
frappe.db.commit()
if not frappe.in_test:
frappe.db.commit()
except Exception as e:
if frappe.in_test:
doc.log_error(f"Error while processing deferred accounting for Invoice {doc.name}")
@@ -605,7 +606,8 @@ def book_revenue_via_journal_entry(
if submit:
journal_entry.submit()
frappe.db.commit()
if not frappe.in_test:
frappe.db.commit()
except Exception:
frappe.db.rollback()
doc.log_error(f"Error while processing deferred accounting for Invoice {doc.name}")

View File

@@ -5,8 +5,7 @@ frappe.ui.form.on("Account", {
setup: function (frm) {
frm.add_fetch("parent_account", "report_type", "report_type");
frm.add_fetch("parent_account", "root_type", "root_type");
},
onload: function (frm) {
frm.set_query("parent_account", function (doc) {
return {
filters: {
@@ -15,7 +14,18 @@ frappe.ui.form.on("Account", {
},
};
});
frm.set_query("account_category", function () {
if (!frm.doc.root_type) return;
return {
filters: {
root_type: ["in", [frm.doc.root_type, ""]],
},
};
});
},
refresh: function (frm) {
frm.toggle_display("account_name", frm.is_new());
@@ -58,12 +68,20 @@ frappe.ui.form.on("Account", {
}
}
},
account_type: function (frm) {
if (frm.doc.is_group == 0) {
frm.toggle_display(["tax_rate"], frm.doc.account_type == "Tax");
frm.toggle_display("warehouse", frm.doc.account_type == "Stock");
}
},
root_type: function (frm) {
if (frm.doc.account_category) {
frm.set_value("account_category", "");
}
},
add_toolbar_buttons: function (frm) {
frm.add_custom_button(
__("Chart of Accounts"),

View File

@@ -203,7 +203,7 @@
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2025-08-02 06:26:44.657146",
"modified": "2026-04-14 18:14:42.202065",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",
@@ -256,6 +256,14 @@
"role": "Accounts Manager",
"share": 1,
"write": 1
},
{
"role": "HR User",
"select": 1
},
{
"role": "HR Manager",
"select": 1
}
],
"row_format": "Dynamic",

View File

@@ -52,60 +52,55 @@ frappe.treeview_settings["Account"] = {
],
root_label: "Accounts",
get_tree_nodes: "erpnext.accounts.utils.get_children",
on_get_node: function (nodes, deep = false) {
if (frappe.boot.user.can_read.indexOf("GL Entry") == -1) return;
on_node_render: function (node, deep) {
const render_balances = () => {
for (let account of cur_tree.account_balance_data) {
const node = cur_tree.nodes && cur_tree.nodes[account.value];
if (!node || node.is_root) continue;
let accounts = [];
if (deep) {
// in case of `get_all_nodes`
accounts = nodes.reduce((acc, node) => [...acc, ...node.data], []);
} else {
accounts = nodes;
}
// show Dr if positive since balance is calculated as debit - credit else show Cr
const balance = account.balance_in_account_currency || account.balance;
const dr_or_cr = balance > 0 ? __("Dr") : __("Cr");
const format = (value, currency) => format_currency(Math.abs(value), currency);
frappe.db.get_single_value("Accounts Settings", "show_balance_in_coa").then((value) => {
if (value) {
const get_balances = frappe.call({
method: "erpnext.accounts.utils.get_account_balances",
args: {
accounts: accounts,
company: cur_tree.args.company,
include_default_fb_balances: true,
},
});
get_balances.then((r) => {
if (!r.message || r.message.length == 0) return;
for (let account of r.message) {
const node = cur_tree.nodes && cur_tree.nodes[account.value];
if (!node || node.is_root) continue;
// show Dr if positive since balance is calculated as debit - credit else show Cr
const balance = account.balance_in_account_currency || account.balance;
const dr_or_cr = balance > 0 ? __("Dr") : __("Cr");
const format = (value, currency) => format_currency(Math.abs(value), currency);
if (account.balance !== undefined) {
node.parent && node.parent.find(".balance-area").remove();
$(
'<span class="balance-area pull-right">' +
(account.balance_in_account_currency
? format(
account.balance_in_account_currency,
account.account_currency
) + " / "
: "") +
format(account.balance, account.company_currency) +
" " +
dr_or_cr +
"</span>"
).insertBefore(node.$ul);
}
}
});
if (account.balance !== undefined) {
node.parent && node.parent.find(".balance-area").remove();
$(
'<span class="balance-area pull-right">' +
(account.account_currency != account.company_currency
? format(account.balance_in_account_currency, account.account_currency) +
" / "
: "") +
format(account.balance, account.company_currency) +
" " +
dr_or_cr +
"</span>"
).insertBefore(node.$ul);
}
}
});
};
if (frappe.boot.user.can_read.indexOf("GL Entry") == -1) return;
if (!cur_tree.account_balance_data) {
frappe.db.get_single_value("Accounts Settings", "show_balance_in_coa").then((value) => {
if (value) {
frappe.call({
method: "erpnext.accounts.utils.get_account_balances_coa",
args: {
company: cur_tree.args.company,
include_default_fb_balances: true,
},
callback: function (r) {
if (!r.message || r.message.length === 0) return;
cur_tree.account_balance_data = r.message || [];
render_balances();
},
});
}
});
} else {
render_balances();
}
},
add_tree_node: "erpnext.accounts.utils.add_ac",
menu_items: [

View File

@@ -6,64 +6,83 @@
"Current Assets": {
"Accounts Receivable": {
"Debtors": {
"account_type": "Receivable"
"account_type": "Receivable",
"account_category": "Trade Receivables"
}
},
"Bank Accounts": {
"account_type": "Bank",
"is_group": 1
"is_group": 1,
"account_category": "Cash and Cash Equivalents"
},
"Cash In Hand": {
"Cash": {
"account_type": "Cash"
"account_type": "Cash",
"account_category": "Cash and Cash Equivalents"
},
"account_type": "Cash"
"account_type": "Cash",
"account_category": "Cash and Cash Equivalents"
},
"Loans and Advances (Assets)": {
"is_group": 1
"is_group": 1,
"account_category": "Other Receivables"
},
"Securities and Deposits": {
"Earnest Money": {}
"Earnest Money": {
"account_category": "Other Current Assets"
}
},
"Stock Assets": {
"Stock In Hand": {
"account_type": "Stock"
"account_type": "Stock",
"account_category": "Stock Assets"
},
"account_type": "Stock"
"account_type": "Stock",
"account_category": "Stock Assets"
},
"Tax Assets": {
"is_group": 1
"is_group": 1,
"account_category": "Other Current Assets"
}
},
"Fixed Assets": {
"Capital Equipment": {
"account_type": "Fixed Asset"
"account_type": "Fixed Asset",
"account_category": "Tangible Assets"
},
"Electronic Equipment": {
"account_type": "Fixed Asset"
"account_type": "Fixed Asset",
"account_category": "Tangible Assets"
},
"Furniture and Fixtures": {
"account_type": "Fixed Asset"
"account_type": "Fixed Asset",
"account_category": "Tangible Assets"
},
"Office Equipment": {
"account_type": "Fixed Asset"
"account_type": "Fixed Asset",
"account_category": "Tangible Assets"
},
"Plants and Machineries": {
"account_type": "Fixed Asset"
"account_type": "Fixed Asset",
"account_category": "Tangible Assets"
},
"Buildings": {
"account_type": "Fixed Asset"
"account_type": "Fixed Asset",
"account_category": "Tangible Assets"
},
"Accumulated Depreciations": {
"account_type": "Accumulated Depreciation"
"account_type": "Accumulated Depreciation",
"account_category": "Tangible Assets"
}
},
"Investments": {
"is_group": 1
"is_group": 1,
"account_category": "Long-term Investments"
},
"Temporary Accounts": {
"Temporary Opening": {
"account_type": "Temporary"
"account_type": "Temporary",
"account_category": "Other Non-current Assets"
}
},
"root_type": "Asset"
@@ -72,55 +91,103 @@
"Direct Expenses": {
"Stock Expenses": {
"Cost of Goods Sold": {
"account_type": "Cost of Goods Sold"
"account_type": "Cost of Goods Sold",
"account_category": "Cost of Goods Sold"
},
"Expenses Included In Valuation": {
"account_type": "Expenses Included In Valuation"
"account_type": "Expenses Included In Valuation",
"account_category": "Other Direct Costs"
},
"Stock Adjustment": {
"account_type": "Stock Adjustment"
"account_type": "Stock Adjustment",
"account_category": "Other Direct Costs"
}
}
},
"Indirect Expenses": {
"Administrative Expenses": {},
"Commission on Sales": {},
"Administrative Expenses": {
"account_category": "Operating Expenses"
},
"Commission on Sales": {
"account_category": "Operating Expenses"
},
"Depreciation": {
"account_type": "Depreciation"
"account_type": "Depreciation",
"account_category": "Operating Expenses"
},
"Entertainment Expenses": {
"account_category": "Operating Expenses"
},
"Entertainment Expenses": {},
"Freight and Forwarding Charges": {
"account_type": "Chargeable"
"account_type": "Chargeable",
"account_category": "Operating Expenses"
},
"Legal Expenses": {
"account_category": "Operating Expenses"
},
"Marketing Expenses": {
"account_type": "Chargeable",
"account_category": "Operating Expenses"
},
"Miscellaneous Expenses": {
"account_type": "Chargeable",
"account_category": "Operating Expenses"
},
"Office Maintenance Expenses": {
"account_category": "Operating Expenses"
},
"Office Rent": {
"account_category": "Operating Expenses"
},
"Postal Expenses": {
"account_category": "Operating Expenses"
},
"Print and Stationery": {
"account_category": "Operating Expenses"
},
"Legal Expenses": {},
"Marketing Expenses": {},
"Miscellaneous Expenses": {},
"Office Maintenance Expenses": {},
"Office Rent": {},
"Postal Expenses": {},
"Print and Stationery": {},
"Rounded Off": {
"account_type": "Round Off"
"account_type": "Round Off",
"account_category": "Operating Expenses"
},
"Salary": {},
"Sales Expenses": {},
"Telephone Expenses": {},
"Travel Expenses": {},
"Utility Expenses": {},
"Write Off": {},
"Exchange Gain/Loss": {},
"Gain/Loss on Asset Disposal": {},
"Impairment": {}
"Salary": {
"account_category": "Operating Expenses"
},
"Sales Expenses": {
"account_category": "Operating Expenses"
},
"Telephone Expenses": {
"account_category": "Operating Expenses"
},
"Travel Expenses": {
"account_category": "Operating Expenses"
},
"Utility Expenses": {
"account_category": "Operating Expenses"
},
"Write Off": {
"account_category": "Operating Expenses"
},
"Exchange Gain/Loss": {
"account_category": "Operating Expenses"
},
"Gain/Loss on Asset Disposal": {
"account_category": "Other Operating Income"
},
"Impairment": {
"account_category": "Operating Expenses"
}
},
"root_type": "Expense"
},
"Income": {
"Direct Income": {
"Sales": {
"account_type": "Income Account"
"account_type": "Income Account",
"account_category": "Revenue from Operations"
},
"Service": {
"account_type": "Income Account"
"account_type": "Income Account",
"account_category": "Revenue from Operations"
},
"account_type": "Income Account"
},
@@ -132,31 +199,51 @@
},
"Source of Funds (Liabilities)": {
"Capital Account": {
"Reserves and Surplus": {},
"Shareholders Funds": {},
"Revaluation Surplus": {}
"Reserves and Surplus": {
"account_category": "Reserves and Surplus"
},
"Shareholders Funds": {
"account_category": "Share Capital"
},
"Revaluation Surplus": {
"account_category": "Reserves and Surplus"
}
},
"Current Liabilities": {
"Accounts Payable": {
"Creditors": {
"account_type": "Payable"
"account_type": "Payable",
"account_category": "Trade Payables"
},
"Payroll Payable": {}
"Payroll Payable": {
"account_category": "Other Payables"
}
},
"Stock Liabilities": {
"Stock Received But Not Billed": {
"account_type": "Stock Received But Not Billed"
"account_type": "Stock Received But Not Billed",
"account_category": "Trade Payables"
}
},
"Duties and Taxes": {
"TDS": {
"account_type": "Tax"
}
"account_type": "Tax",
"account_category": "Current Tax Liabilities"
},
"account_type": "Tax",
"is_group": 1,
"account_category": "Current Tax Liabilities"
},
"Loans (Liabilities)": {
"Secured Loans": {},
"Unsecured Loans": {},
"Bank Overdraft Account": {}
"Secured Loans": {
"account_category": "Long-term Borrowings"
},
"Unsecured Loans": {
"account_category": "Long-term Borrowings"
},
"Bank Overdraft Account": {
"account_category": "Short-term Borrowings"
}
}
},
"root_type": "Liability"

View File

@@ -2,7 +2,6 @@
# License: GNU General Public License v3. See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import nowdate
from erpnext.accounts.doctype.account.account import (
@@ -11,11 +10,10 @@ from erpnext.accounts.doctype.account.account import (
update_account_number,
)
from erpnext.stock import get_company_default_inventory_account, get_warehouse_account
EXTRA_TEST_RECORD_DEPENDENCIES = ["Company"]
from erpnext.tests.utils import ERPNextTestSuite
class TestAccount(IntegrationTestCase):
class TestAccount(ERPNextTestSuite):
def test_rename_account(self):
if not frappe.db.exists("Account", "1210 - Debtors - _TC"):
acc = frappe.new_doc("Account")
@@ -322,72 +320,6 @@ class TestAccount(IntegrationTestCase):
self.assertEqual(balance, 0)
def _make_test_records(verbose=None):
from frappe.tests.utils import make_test_objects
accounts = [
# [account_name, parent_account, is_group]
["_Test Bank", "Bank Accounts", 0, "Bank", None],
["_Test Bank USD", "Bank Accounts", 0, "Bank", "USD"],
["_Test Bank EUR", "Bank Accounts", 0, "Bank", "EUR"],
["_Test Cash", "Cash In Hand", 0, "Cash", None],
["_Test Account Stock Expenses", "Direct Expenses", 1, None, None],
["_Test Account Shipping Charges", "_Test Account Stock Expenses", 0, "Chargeable", None],
["_Test Account Customs Duty", "_Test Account Stock Expenses", 0, "Tax", None],
["_Test Account Insurance Charges", "_Test Account Stock Expenses", 0, "Chargeable", None],
["_Test Account Stock Adjustment", "_Test Account Stock Expenses", 0, "Stock Adjustment", None],
["_Test Employee Advance", "Current Liabilities", 0, None, None],
["_Test Account Tax Assets", "Current Assets", 1, None, None],
["_Test Account VAT", "_Test Account Tax Assets", 0, "Tax", None],
["_Test Account Service Tax", "_Test Account Tax Assets", 0, "Tax", None],
["_Test Account Reserves and Surplus", "Current Liabilities", 0, None, None],
["_Test Account Cost for Goods Sold", "Expenses", 0, None, None],
["_Test Account Excise Duty", "_Test Account Tax Assets", 0, "Tax", None],
["_Test Account Education Cess", "_Test Account Tax Assets", 0, "Tax", None],
["_Test Account S&H Education Cess", "_Test Account Tax Assets", 0, "Tax", None],
["_Test Account CST", "Direct Expenses", 0, "Tax", None],
["_Test Account Discount", "Direct Expenses", 0, None, None],
["_Test Write Off", "Indirect Expenses", 0, None, None],
["_Test Exchange Gain/Loss", "Indirect Expenses", 0, None, None],
["_Test Account Sales", "Direct Income", 0, None, None],
# related to Account Inventory Integration
["_Test Account Stock In Hand", "Current Assets", 0, None, None],
# fixed asset depreciation
["_Test Fixed Asset", "Current Assets", 0, "Fixed Asset", None],
["_Test Accumulated Depreciations", "Current Assets", 0, "Accumulated Depreciation", None],
["_Test Depreciations", "Expenses", 0, "Depreciation", None],
["_Test Gain/Loss on Asset Disposal", "Expenses", 0, None, None],
# Receivable / Payable Account
["_Test Receivable", "Current Assets", 0, "Receivable", None],
["_Test Payable", "Current Liabilities", 0, "Payable", None],
["_Test Receivable USD", "Current Assets", 0, "Receivable", "USD"],
["_Test Payable USD", "Current Liabilities", 0, "Payable", "USD"],
]
for company, abbr in [
["_Test Company", "_TC"],
["_Test Company 1", "_TC1"],
["_Test Company with perpetual inventory", "TCP1"],
]:
test_objects = make_test_objects(
"Account",
[
{
"doctype": "Account",
"account_name": account_name,
"parent_account": parent_account + " - " + abbr,
"company": company,
"is_group": is_group,
"account_type": account_type,
"account_currency": currency,
}
for account_name, parent_account, is_group, account_type, currency in accounts
],
)
return test_objects
def get_inventory_account(company, warehouse=None):
account = None
if warehouse:

View File

@@ -1,6 +0,0 @@
[
{
"doctype": "Account",
"name": "_Test Account 1"
}
]

View File

@@ -7,6 +7,8 @@
"engine": "InnoDB",
"field_order": [
"account_category_name",
"root_type",
"column_break_qluu",
"description"
],
"fields": [
@@ -14,6 +16,7 @@
"fieldname": "account_category_name",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Account Category Name",
"reqd": 1,
"unique": 1
@@ -22,12 +25,29 @@
"fieldname": "description",
"fieldtype": "Small Text",
"label": "Description"
},
{
"fieldname": "column_break_qluu",
"fieldtype": "Column Break"
},
{
"fieldname": "root_type",
"fieldtype": "Select",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Root Type",
"options": "\nAsset\nLiability\nIncome\nExpense\nEquity"
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-10-15 03:19:47.171349",
"links": [
{
"link_doctype": "Account",
"link_fieldname": "account_category"
}
],
"modified": "2026-03-05 06:49:34.430723",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account Category",
@@ -64,7 +84,7 @@
}
],
"row_format": "Dynamic",
"search_fields": "account_category_name, description",
"search_fields": "account_category_name, root_type",
"sort_field": "creation",
"sort_order": "DESC",
"states": []

View File

@@ -21,6 +21,7 @@ class AccountCategory(Document):
account_category_name: DF.Data
description: DF.SmallText | None
root_type: DF.Literal["", "Asset", "Liability", "Income", "Expense", "Equity"]
# end: auto-generated types
def after_rename(self, old_name, new_name, merge):

View File

@@ -2,19 +2,3 @@
# See license.txt
# import frappe
from frappe.tests import IntegrationTestCase
# On IntegrationTestCase, the doctype test records and all
# link-field test record dependencies are recursively loaded
# Use these module variables to add/remove to/from that list
EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
class IntegrationTestAccountCategory(IntegrationTestCase):
"""
Integration tests for AccountCategory.
Use this class for testing interactions between multiple components.
"""
pass

View File

@@ -1,8 +1,8 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Account Closing Balance", {
// refresh(frm) {
// },
// });
frappe.ui.form.on("Account Closing Balance", {
refresh(frm) {
frm.page.btn_secondary.hide();
},
});

View File

@@ -5,6 +5,7 @@
"doctype": "DocType",
"document_type": "Document",
"engine": "InnoDB",
"is_submittable": 1,
"field_order": [
"closing_date",
"account",

View File

@@ -2,8 +2,9 @@
# See license.txt
# import frappe
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestAccountClosingBalance(IntegrationTestCase):
class TestAccountClosingBalance(ERPNextTestSuite):
pass

View File

@@ -82,7 +82,7 @@ class AccountingDimension(Document):
else:
frappe.throw(_("Company {0} is added more than once").format(frappe.bold(default.company)))
def after_insert(self):
def on_update(self):
if frappe.in_test:
make_dimension_in_accounting_doctypes(doc=self)
else:

View File

@@ -2,18 +2,13 @@
# See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
EXTRA_TEST_RECORD_DEPENDENCIES = ["Cost Center", "Location", "Warehouse", "Department"]
from erpnext.tests.utils import ERPNextTestSuite
class TestAccountingDimension(IntegrationTestCase):
def setUp(self):
create_dimension()
class TestAccountingDimension(ERPNextTestSuite):
def test_dimension_against_sales_invoice(self):
si = create_sales_invoice(do_not_save=1)
@@ -78,68 +73,3 @@ class TestAccountingDimension(IntegrationTestCase):
si.save()
self.assertRaises(frappe.ValidationError, si.submit)
def tearDown(self):
disable_dimension()
frappe.flags.accounting_dimensions_details = None
frappe.flags.dimension_filter_map = None
def create_dimension():
frappe.set_user("Administrator")
if not frappe.db.exists("Accounting Dimension", {"document_type": "Department"}):
dimension = frappe.get_doc(
{
"doctype": "Accounting Dimension",
"document_type": "Department",
}
)
dimension.append(
"dimension_defaults",
{
"company": "_Test Company",
"reference_document": "Department",
"default_dimension": "_Test Department - _TC",
},
)
dimension.insert()
dimension.save()
else:
dimension = frappe.get_doc("Accounting Dimension", "Department")
dimension.disabled = 0
dimension.save()
if not frappe.db.exists("Accounting Dimension", {"document_type": "Location"}):
dimension1 = frappe.get_doc(
{
"doctype": "Accounting Dimension",
"document_type": "Location",
}
)
dimension1.append(
"dimension_defaults",
{
"company": "_Test Company",
"reference_document": "Location",
"default_dimension": "Block 1",
},
)
dimension1.insert()
dimension1.save()
else:
dimension1 = frappe.get_doc("Accounting Dimension", "Location")
dimension1.disabled = 0
dimension1.save()
def disable_dimension():
dimension1 = frappe.get_doc("Accounting Dimension", "Department")
dimension1.disabled = 1
dimension1.save()
dimension2 = frappe.get_doc("Accounting Dimension", "Location")
dimension2.disabled = 1
dimension2.save()

View File

@@ -1,23 +1,15 @@
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension import (
create_dimension,
disable_dimension,
)
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.exceptions import InvalidAccountDimensionError, MandatoryAccountDimensionError
EXTRA_TEST_RECORD_DEPENDENCIES = ["Location", "Cost Center", "Department"]
from erpnext.tests.utils import ERPNextTestSuite
class TestAccountingDimensionFilter(unittest.TestCase):
class TestAccountingDimensionFilter(ERPNextTestSuite):
def setUp(self):
create_dimension()
create_accounting_dimension_filter()
self.invoice_list = []
@@ -44,17 +36,6 @@ class TestAccountingDimensionFilter(unittest.TestCase):
self.assertRaises(MandatoryAccountDimensionError, si.submit)
self.invoice_list.append(si)
def tearDown(self):
disable_dimension_filter()
disable_dimension()
frappe.flags.accounting_dimensions_details = None
frappe.flags.dimension_filter_map = None
for si in self.invoice_list:
si.load_from_db()
if si.docstatus == 1:
si.cancel()
def create_accounting_dimension_filter():
if not frappe.db.get_value("Accounting Dimension Filter", {"accounting_dimension": "Cost Center"}):

View File

@@ -20,7 +20,6 @@
{
"fieldname": "period_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Period Name",
"reqd": 1,
"unique": 1
@@ -79,7 +78,7 @@
}
],
"links": [],
"modified": "2025-12-01 16:53:44.631299",
"modified": "2026-03-09 17:15:33.577217",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting Period",

View File

@@ -2,7 +2,6 @@
# See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import add_months, nowdate
from erpnext.accounts.doctype.accounting_period.accounting_period import (
@@ -10,11 +9,10 @@ from erpnext.accounts.doctype.accounting_period.accounting_period import (
OverlapError,
)
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
EXTRA_TEST_RECORD_DEPENDENCIES = ["Item"]
from erpnext.tests.utils import ERPNextTestSuite
class TestAccountingPeriod(IntegrationTestCase):
class TestAccountingPeriod(ERPNextTestSuite):
def test_overlap(self):
ap1 = create_accounting_period(
start_date="2018-04-01", end_date="2018-06-30", company="Wind Power LLC"
@@ -89,10 +87,6 @@ class TestAccountingPeriod(IntegrationTestCase):
doc.submit() # Should not raise
self.assertEqual(doc.docstatus, 1)
def tearDown(self):
for d in frappe.get_all("Accounting Period"):
frappe.delete_doc("Accounting Period", d.name)
def create_accounting_period(**args):
args = frappe._dict(args)

View File

@@ -2,7 +2,15 @@
// For license information, please see license.txt
frappe.ui.form.on("Accounts Settings", {
refresh: function (frm) {},
refresh: function (frm) {
frm.set_query("document_type", "repost_allowed_types", function (doc, cdt, cdn) {
return {
filters: {
name: ["in", frappe.boot.sysdefaults.repost_allowed_doctypes],
},
};
});
},
enable_immutable_ledger: function (frm) {
if (!frm.doc.enable_immutable_ledger) {
return;

View File

@@ -16,6 +16,7 @@
"invoicing_features_section",
"check_supplier_invoice_uniqueness",
"automatically_fetch_payment_terms",
"enable_subscription",
"column_break_17",
"enable_common_party_accounting",
"allow_multi_currency_invoices_against_single_party_account",
@@ -62,9 +63,12 @@
"reconciliation_queue_size",
"column_break_resa",
"exchange_gain_loss_posting_date",
"repost_section",
"repost_allowed_types",
"payment_options_section",
"enable_loyalty_point_program",
"column_break_ctam",
"fetch_payment_schedule_in_payment_request",
"invoicing_settings_tab",
"accounts_transactions_settings_section",
"over_billing_allowance",
@@ -688,16 +692,39 @@
"fieldname": "enable_accounting_dimensions",
"fieldtype": "Check",
"label": "Enable Accounting Dimensions"
},
{
"default": "1",
"description": "Enable Subscription tracking in invoice",
"fieldname": "enable_subscription",
"fieldtype": "Check",
"label": "Enable Subscription"
},
{
"default": "1",
"fieldname": "fetch_payment_schedule_in_payment_request",
"fieldtype": "Check",
"label": "Fetch Payment Schedule In Payment Request"
},
{
"fieldname": "repost_section",
"fieldtype": "Section Break",
"label": "Repost"
},
{
"fieldname": "repost_allowed_types",
"fieldtype": "Table",
"label": "Allowed Doctypes",
"options": "Repost Allowed Types"
}
],
"grid_page_length": 50,
"hide_toolbar": 0,
"icon": "icon-cog",
"idx": 1,
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2026-02-27 01:04:09.415288",
"modified": "2026-04-13 15:30:28.729627",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",

View File

@@ -10,6 +10,9 @@ from frappe.custom.doctype.property_setter.property_setter import make_property_
from frappe.model.document import Document
from frappe.utils import cint
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_accounting_dimensions,
)
from erpnext.accounts.utils import sync_auto_reconcile_config
SELLING_DOCTYPES = [
@@ -44,6 +47,8 @@ class AccountsSettings(Document):
if TYPE_CHECKING:
from frappe.types import DF
from erpnext.accounts.doctype.repost_allowed_types.repost_allowed_types import RepostAllowedTypes
add_taxes_from_item_tax_template: DF.Check
add_taxes_from_taxes_and_charges_template: DF.Check
allow_multi_currency_invoices_against_single_party_account: DF.Check
@@ -72,7 +77,9 @@ class AccountsSettings(Document):
enable_immutable_ledger: DF.Check
enable_loyalty_point_program: DF.Check
enable_party_matching: DF.Check
enable_subscription: DF.Check
exchange_gain_loss_posting_date: DF.Literal["Invoice", "Payment", "Reconciliation Date"]
fetch_payment_schedule_in_payment_request: DF.Check
fetch_valuation_rate_for_internal_transaction: DF.Check
general_ledger_remarks_length: DF.Int
ignore_account_closing_balance: DF.Check
@@ -85,6 +92,7 @@ class AccountsSettings(Document):
receivable_payable_fetch_method: DF.Literal["Buffered Cursor", "UnBuffered Cursor", "Raw SQL"]
receivable_payable_remarks_length: DF.Int
reconciliation_queue_size: DF.Int
repost_allowed_types: DF.Table[RepostAllowedTypes]
role_allowed_to_over_bill: DF.Link | None
role_to_notify_on_depreciation_failure: DF.Link | None
role_to_override_stop_action: DF.Link | None
@@ -135,10 +143,15 @@ class AccountsSettings(Document):
toggle_loyalty_point_program_section(not self.enable_loyalty_point_program)
clear_cache = True
if old_doc.enable_subscription != self.enable_subscription:
toggle_subscription_sections(not self.enable_subscription)
clear_cache = True
if clear_cache:
frappe.clear_cache()
self.validate_and_sync_auto_reconcile_config()
self.update_property_for_accounting_dimension()
def validate_stale_days(self):
if not self.allow_stale and cint(self.stale_days) <= 0:
@@ -185,6 +198,17 @@ class AccountsSettings(Document):
title=_("Auto Tax Settings Error"),
)
def update_property_for_accounting_dimension(self):
doctypes = [entry.document_type for entry in self.repost_allowed_types]
if not doctypes:
return
from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import get_child_docs
doctypes += get_child_docs(doctypes)
set_allow_on_submit_for_dimension_fields(doctypes)
@frappe.whitelist()
def drop_ar_sql_procedures(self):
from erpnext.accounts.report.accounts_receivable.accounts_receivable import InitSQLProceduresForAR
@@ -215,6 +239,12 @@ def toggle_loyalty_point_program_section(hide):
create_property_setter_for_hiding_field(doctype, "loyalty_points_redemption", hide)
def toggle_subscription_sections(hide):
subscription_doctypes = frappe.get_hooks("subscription_doctypes")
for doctype in subscription_doctypes:
create_property_setter_for_hiding_field(doctype, "subscription_section", hide)
def create_property_setter_for_hiding_field(doctype, field_name, hide):
make_property_setter(
doctype,
@@ -224,3 +254,12 @@ def create_property_setter_for_hiding_field(doctype, field_name, hide):
"Check",
validate_fields_for_doctype=False,
)
def set_allow_on_submit_for_dimension_fields(doctypes):
for dt in doctypes:
meta = frappe.get_meta(dt)
for dimension in get_accounting_dimensions():
df = meta.get_field(dimension)
if df and not df.allow_on_submit:
frappe.db.set_value("Custom Field", dt + "-" + dimension, "allow_on_submit", 1)

View File

@@ -1,15 +1,9 @@
import frappe
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestAccountsSettings(IntegrationTestCase):
def tearDown(self):
# Just in case `save` method succeeds, we need to take things back to default so that other tests
# don't break
cur_settings = frappe.get_doc("Accounts Settings", "Accounts Settings")
cur_settings.allow_stale = 1
cur_settings.save()
class TestAccountsSettings(ERPNextTestSuite):
def test_stale_days(self):
cur_settings = frappe.get_doc("Accounts Settings", "Accounts Settings")
cur_settings.allow_stale = 0

View File

@@ -3,6 +3,7 @@
frappe.ui.form.on("Advance Payment Ledger Entry", {
refresh(frm) {
frm.page.btn_secondary.hide();
frm.set_currency_labels(["amount"], frm.doc.currency);
frm.set_currency_labels(["base_amount"], erpnext.get_currency(frm.doc.company));
},

View File

@@ -4,6 +4,7 @@
"creation": "2024-10-16 16:57:12.085072",
"doctype": "DocType",
"engine": "InnoDB",
"is_submittable": 1,
"field_order": [
"company",
"voucher_type",

View File

@@ -2,7 +2,6 @@
# See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import nowdate, today
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
@@ -10,14 +9,13 @@ from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
# On IntegrationTestCase, the doctype test records and all
# On ERPNextTestSuite, the doctype test records and all
# link-field test record depdendencies are recursively loaded
# Use these module variables to add/remove to/from that list
EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
from erpnext.tests.utils import ERPNextTestSuite
class TestAdvancePaymentLedgerEntry(AccountsTestMixin, IntegrationTestCase):
class TestAdvancePaymentLedgerEntry(ERPNextTestSuite, AccountsTestMixin):
"""
Integration tests for AdvancePaymentLedgerEntry.
Use this class for testing interactions between multiple components.
@@ -30,9 +28,6 @@ class TestAdvancePaymentLedgerEntry(AccountsTestMixin, IntegrationTestCase):
self.create_item()
self.clear_old_entries()
def tearDown(self):
frappe.db.rollback()
def create_sales_order(self, qty=1, rate=100, currency="INR", do_not_submit=False):
"""
Helper method

View File

@@ -1,8 +1,8 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestBank(IntegrationTestCase):
class TestBank(ERPNextTestSuite):
pass

View File

@@ -116,6 +116,7 @@ def get_default_company_bank_account(company, party_type, party):
@frappe.whitelist()
def get_bank_account_details(bank_account: str):
frappe.has_permission("Bank Account", doc=bank_account, ptype="read", throw=True)
return frappe.get_cached_value(
"Bank Account", bank_account, ["account", "bank", "bank_account_no"], as_dict=1
)

View File

@@ -1,8 +1,8 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestBankAccount(IntegrationTestCase):
class TestBankAccount(ERPNextTestSuite):
pass

View File

@@ -1,8 +1,8 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestBankAccountSubtype(IntegrationTestCase):
class TestBankAccountSubtype(ERPNextTestSuite):
pass

View File

@@ -2,8 +2,8 @@
# See license.txt
# import frappe
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestBankAccountType(IntegrationTestCase):
class TestBankAccountType(ERPNextTestSuite):
pass

View File

@@ -5,7 +5,9 @@
import frappe
from frappe import _, msgprint
from frappe.model.document import Document
from frappe.query_builder import Case
from frappe.query_builder.custom import ConstantColumn
from frappe.query_builder.functions import Coalesce, Sum
from frappe.utils import cint, flt, fmt_money, getdate
from pypika import Order
@@ -182,65 +184,162 @@ def get_payment_entries_for_bank_clearance(
):
entries = []
condition = ""
pe_condition = ""
journal_entry = frappe.qb.DocType("Journal Entry")
journal_entry_account = frappe.qb.DocType("Journal Entry Account")
journal_entry_query = (
frappe.qb.from_(journal_entry_account)
.inner_join(journal_entry)
.on(journal_entry_account.parent == journal_entry.name)
.select(
ConstantColumn("Journal Entry").as_("payment_document"),
journal_entry.name.as_("payment_entry"),
journal_entry.cheque_no.as_("cheque_number"),
journal_entry.cheque_date,
Sum(journal_entry_account.debit_in_account_currency).as_("debit"),
Sum(journal_entry_account.credit_in_account_currency).as_("credit"),
journal_entry.posting_date,
journal_entry_account.against_account,
journal_entry.clearance_date,
journal_entry_account.account_currency,
)
.where(
(journal_entry_account.account == account)
& (journal_entry.docstatus == 1)
& (journal_entry.posting_date >= from_date)
& (journal_entry.posting_date <= to_date)
& (journal_entry.is_opening == "No")
)
)
if not include_reconciled_entries:
condition = "and (clearance_date IS NULL or clearance_date='0000-00-00')"
pe_condition = "and (pe.clearance_date IS NULL or pe.clearance_date='0000-00-00')"
journal_entry_query = journal_entry_query.where(
(journal_entry.clearance_date.isnull()) | (journal_entry.clearance_date == "0000-00-00")
)
journal_entries = frappe.db.sql(
f"""
select
"Journal Entry" as payment_document, t1.name as payment_entry,
t1.cheque_no as cheque_number, t1.cheque_date,
sum(t2.debit_in_account_currency) as debit, sum(t2.credit_in_account_currency) as credit,
t1.posting_date, t2.against_account, t1.clearance_date, t2.account_currency
from
`tabJournal Entry` t1, `tabJournal Entry Account` t2
where
t2.parent = t1.name and t2.account = %(account)s and t1.docstatus=1
and t1.posting_date >= %(from)s and t1.posting_date <= %(to)s
and ifnull(t1.is_opening, 'No') = 'No' {condition}
group by t2.account, t1.name
order by t1.posting_date ASC, t1.name DESC
""",
{"account": account, "from": from_date, "to": to_date},
as_dict=1,
journal_entries = (
journal_entry_query.groupby(journal_entry_account.account, journal_entry.name)
.orderby(journal_entry.posting_date)
.orderby(journal_entry.name, order=Order.desc)
).run(as_dict=True)
pe = frappe.qb.DocType("Payment Entry")
company = frappe.qb.DocType("Company")
payment_entry_query = (
frappe.qb.from_(pe)
.join(company)
.on(pe.company == company.name)
.select(
ConstantColumn("Payment Entry").as_("payment_document"),
pe.name.as_("payment_entry"),
pe.reference_no.as_("cheque_number"),
pe.reference_date.as_("cheque_date"),
(
Case()
.when(
pe.paid_from == account,
(
pe.paid_amount
+ (
Case()
.when(
(pe.payment_type == "Pay")
& (company.default_currency == pe.paid_from_account_currency),
pe.base_total_taxes_and_charges,
)
.else_(pe.total_taxes_and_charges)
)
),
)
.else_(0)
).as_("credit"),
(
Case()
.when(pe.paid_from == account, 0)
.else_(
pe.received_amount
+ (
Case()
.when(
company.default_currency == pe.paid_to_account_currency,
pe.base_total_taxes_and_charges,
)
.else_(pe.total_taxes_and_charges)
)
)
).as_("debit"),
pe.posting_date,
Coalesce(pe.party, Case().when(pe.paid_from == account, pe.paid_to).else_(pe.paid_from)).as_(
"against_account"
),
pe.clearance_date,
(
Case()
.when(pe.paid_to == account, pe.paid_to_account_currency)
.else_(pe.paid_from_account_currency)
).as_("account_currency"),
)
.where(
((pe.paid_from == account) | (pe.paid_to == account))
& (pe.docstatus == 1)
& (pe.posting_date >= from_date)
& (pe.posting_date <= to_date)
)
)
payment_entries = frappe.db.sql(
f"""
select
"Payment Entry" as payment_document, pe.name as payment_entry,
pe.reference_no as cheque_number, pe.reference_date as cheque_date,
if(pe.paid_from=%(account)s, pe.paid_amount + if(pe.payment_type = 'Pay' and c.default_currency = pe.paid_from_account_currency, pe.base_total_taxes_and_charges, pe.total_taxes_and_charges) , 0) as credit,
if(pe.paid_from=%(account)s, 0, pe.received_amount + pe.total_taxes_and_charges) as debit,
pe.posting_date, ifnull(pe.party,if(pe.paid_from=%(account)s,pe.paid_to,pe.paid_from)) as against_account, pe.clearance_date,
if(pe.paid_to=%(account)s, pe.paid_to_account_currency, pe.paid_from_account_currency) as account_currency
from `tabPayment Entry` as pe
join `tabCompany` c on c.name = pe.company
where
(pe.paid_from=%(account)s or pe.paid_to=%(account)s) and pe.docstatus=1
and pe.posting_date >= %(from)s and pe.posting_date <= %(to)s
{pe_condition}
order by
pe.posting_date ASC, pe.name DESC
""",
{
"account": account,
"from": from_date,
"to": to_date,
},
as_dict=1,
if not include_reconciled_entries:
payment_entry_query = payment_entry_query.where(
(pe.clearance_date.isnull()) | (pe.clearance_date == "0000-00-00")
)
payment_entries = (payment_entry_query.orderby(pe.posting_date).orderby(pe.name, order=Order.desc)).run(
as_dict=True
)
pos_sales_invoices, pos_purchase_invoices = [], []
acc = frappe.qb.DocType("Account")
pi = frappe.qb.DocType("Purchase Invoice")
paid_purchase_invoices_query = (
frappe.qb.from_(pi)
.inner_join(acc)
.on(pi.cash_bank_account == acc.name)
.select(
ConstantColumn("Purchase Invoice").as_("payment_document"),
pi.name.as_("payment_entry"),
pi.paid_amount.as_("credit"),
pi.posting_date,
pi.supplier.as_("against_account"),
pi.bill_no.as_("cheque_number"),
pi.clearance_date,
acc.account_currency,
ConstantColumn(0).as_("debit"),
)
.where(
(pi.docstatus == 1)
& (pi.is_paid == 1)
& (pi.cash_bank_account == account)
& (pi.posting_date >= from_date)
& (pi.posting_date <= to_date)
)
)
if not include_reconciled_entries:
paid_purchase_invoices_query = paid_purchase_invoices_query.where(
(pi.clearance_date.isnull()) | (pi.clearance_date == "0000-00-00")
)
paid_purchase_invoices = (
paid_purchase_invoices_query.orderby(pi.posting_date).orderby(pi.name, order=Order.desc)
).run(as_dict=True)
pos_sales_invoices = []
if include_pos_transactions:
si_payment = frappe.qb.DocType("Sales Invoice Payment")
si = frappe.qb.DocType("Sales Invoice")
acc = frappe.qb.DocType("Account")
pos_sales_invoices = (
pos_sales_invoices_query = (
frappe.qb.from_(si_payment)
.inner_join(si)
.on(si_payment.parent == si.name)
@@ -263,38 +362,22 @@ def get_payment_entries_for_bank_clearance(
& (si.posting_date >= from_date)
& (si.posting_date <= to_date)
)
.orderby(si.posting_date)
.orderby(si.name, order=Order.desc)
).run(as_dict=True)
)
pi = frappe.qb.DocType("Purchase Invoice")
if not include_reconciled_entries:
pos_sales_invoices_query = pos_sales_invoices_query.where(
(si_payment.clearance_date.isnull()) | (si_payment.clearance_date == "0000-00-00")
)
pos_purchase_invoices = (
frappe.qb.from_(pi)
.inner_join(acc)
.on(pi.cash_bank_account == acc.name)
.select(
ConstantColumn("Purchase Invoice").as_("payment_document"),
pi.name.as_("payment_entry"),
pi.paid_amount.as_("credit"),
pi.posting_date,
pi.supplier.as_("against_account"),
pi.clearance_date,
acc.account_currency,
ConstantColumn(0).as_("debit"),
)
.where(
(pi.docstatus == 1)
& (pi.cash_bank_account == account)
& (pi.posting_date >= from_date)
& (pi.posting_date <= to_date)
)
.orderby(pi.posting_date)
.orderby(pi.name, order=Order.desc)
pos_sales_invoices = (
pos_sales_invoices_query.orderby(si.posting_date).orderby(si.name, order=Order.desc)
).run(as_dict=True)
entries = (
list(payment_entries) + list(journal_entries) + list(pos_sales_invoices) + list(pos_purchase_invoices)
list(payment_entries)
+ list(journal_entries)
+ list(pos_sales_invoices)
+ list(paid_purchase_invoices)
)
return entries

View File

@@ -2,7 +2,6 @@
# See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import add_months, getdate
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
@@ -14,13 +13,12 @@ from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.stock.doctype.item.test_item import create_item
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
from erpnext.tests.utils import if_lending_app_installed, if_lending_app_not_installed
from erpnext.tests.utils import ERPNextTestSuite, if_lending_app_installed, if_lending_app_not_installed
class TestBankClearance(IntegrationTestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
class TestBankClearance(ERPNextTestSuite):
def setUp(self):
frappe.clear_cache()
create_warehouse(
warehouse_name="_Test Warehouse",
properties={"parent_warehouse": "All Warehouses - _TC"},

View File

@@ -1,8 +1,8 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestBankGuarantee(IntegrationTestCase):
class TestBankGuarantee(ERPNextTestSuite):
pass

View File

@@ -59,7 +59,7 @@ def get_bank_transactions(
filters.append(["date", "<=", to_date])
if from_date:
filters.append(["date", ">=", from_date])
transactions = frappe.get_all(
transactions = frappe.get_list(
"Bank Transaction",
fields=[
"date",
@@ -84,6 +84,7 @@ def get_bank_transactions(
@frappe.whitelist()
def get_account_balance(bank_account: str, till_date: str | date, company: str):
# returns account balance till the specified date
frappe.has_permission("Bank Account", "read", bank_account, throw=True)
account = frappe.db.get_value("Bank Account", bank_account, "account")
filters = frappe._dict(
{

View File

@@ -4,7 +4,6 @@
import frappe
from frappe import qb
from frappe.tests import IntegrationTestCase
from frappe.utils import add_days, today
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
@@ -13,9 +12,10 @@ from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool
)
from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
from erpnext.tests.utils import ERPNextTestSuite
class TestBankReconciliationTool(AccountsTestMixin, IntegrationTestCase):
class TestBankReconciliationTool(ERPNextTestSuite, AccountsTestMixin):
def setUp(self):
self.create_company()
self.create_customer()
@@ -24,9 +24,6 @@ class TestBankReconciliationTool(AccountsTestMixin, IntegrationTestCase):
qb.from_(bank_dt).delete().where(bank_dt.name == "HDFC").run()
self.create_bank_account()
def tearDown(self):
frappe.db.rollback()
def create_bank_account(self):
bank = frappe.get_doc(
{
@@ -43,6 +40,7 @@ class TestBankReconciliationTool(AccountsTestMixin, IntegrationTestCase):
"bank": bank.name,
"is_company_account": True,
"account": self.bank, # account from Chart of Accounts
"company": self.company,
}
)
.insert()

View File

@@ -1,15 +1,14 @@
# Copyright (c) 2020, Frappe Technologies and Contributors
# See license.txt
import unittest
from erpnext.accounts.doctype.bank_statement_import.bank_statement_import import (
is_mt940_format,
preprocess_mt940_content,
)
from erpnext.tests.utils import ERPNextTestSuite
class TestBankStatementImport(unittest.TestCase):
class TestBankStatementImport(ERPNextTestSuite):
"""Unit tests for Bank Statement Import functions"""
def test_preprocess_mt940_content_with_long_statement_number(self):

View File

@@ -2,27 +2,20 @@
# License: GNU General Public License v3. See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import nowdate
from erpnext.accounts.doctype.bank_transaction.test_bank_transaction import create_bank_account
from erpnext.tests.utils import ERPNextTestSuite
IBAN_1 = "DE02000000003716541159"
IBAN_2 = "DE02500105170137075030"
class TestAutoMatchParty(IntegrationTestCase):
@classmethod
def setUpClass(cls):
class TestAutoMatchParty(ERPNextTestSuite):
def setUp(self):
create_bank_account()
frappe.db.set_single_value("Accounts Settings", "enable_party_matching", 1)
frappe.db.set_single_value("Accounts Settings", "enable_fuzzy_matching", 1)
return super().setUpClass()
@classmethod
def tearDownClass(cls):
frappe.db.set_single_value("Accounts Settings", "enable_party_matching", 0)
frappe.db.set_single_value("Accounts Settings", "enable_fuzzy_matching", 0)
def test_match_by_account_number(self):
create_supplier_for_match(account_no=IBAN_1[11:])

View File

@@ -6,7 +6,6 @@ import json
import frappe
from frappe import utils
from frappe.model.docstatus import DocStatus
from frappe.tests import IntegrationTestCase
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
get_linked_payments,
@@ -19,12 +18,10 @@ from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_paymen
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.tests.utils import if_lending_app_installed
EXTRA_TEST_RECORD_DEPENDENCIES = ["Item", "Cost Center"]
from erpnext.tests.utils import ERPNextTestSuite, if_lending_app_installed
class TestBankTransaction(IntegrationTestCase):
class TestBankTransaction(ERPNextTestSuite):
def setUp(self):
make_pos_profile()
@@ -385,7 +382,7 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
frappe.get_doc(
{
"doctype": "Customer",
"customer_group": "All Customer Groups",
"customer_group": "Individual",
"customer_type": "Company",
"customer_name": "Poore Simon's",
}
@@ -416,7 +413,7 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
frappe.get_doc(
{
"doctype": "Customer",
"customer_group": "All Customer Groups",
"customer_group": "Individual",
"customer_type": "Company",
"customer_name": "Fayva",
}

View File

@@ -2,10 +2,11 @@
# See license.txt
import frappe
from frappe.tests import UnitTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestBankTransactionFees(UnitTestCase):
class TestBankTransactionFees(ERPNextTestSuite):
def test_included_fee_throws(self):
"""A fee that's part of a withdrawal cannot be bigger than the
withdrawal itself."""

View File

@@ -2,8 +2,10 @@
# See license.txt
# import frappe
from frappe.tests import IntegrationTestCase
class TestBisectAccountingStatements(IntegrationTestCase):
from erpnext.tests.utils import ERPNextTestSuite
class TestBisectAccountingStatements(ERPNextTestSuite):
pass

View File

@@ -2,8 +2,10 @@
# See license.txt
# import frappe
from frappe.tests import IntegrationTestCase
class TestBisectNodes(IntegrationTestCase):
from erpnext.tests.utils import ERPNextTestSuite
class TestBisectNodes(ERPNextTestSuite):
pass

View File

@@ -17,12 +17,6 @@ from erpnext.tests.utils import ERPNextTestSuite
class TestBudget(ERPNextTestSuite):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.make_monthly_distribution()
cls.make_projects()
def setUp(self):
frappe.db.set_single_value("Accounts Settings", "use_legacy_budget_controller", False)
self.company = "_Test Company"

View File

@@ -1,8 +1,8 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestCashierClosing(IntegrationTestCase):
class TestCashierClosing(ERPNextTestSuite):
pass

View File

@@ -1,8 +1,8 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestChartofAccountsImporter(IntegrationTestCase):
class TestChartofAccountsImporter(ERPNextTestSuite):
pass

View File

@@ -1,8 +1,8 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestChequePrintTemplate(IntegrationTestCase):
class TestChequePrintTemplate(ERPNextTestSuite):
pass

View File

@@ -126,7 +126,7 @@
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2025-01-22 10:46:42.904001",
"modified": "2026-04-14 18:15:27.367298",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cost Center",
@@ -173,11 +173,20 @@
"role": "Employee",
"select": 1,
"share": 1
},
{
"role": "HR User",
"select": 1
},
{
"role": "HR Manager",
"select": 1
}
],
"row_format": "Dynamic",
"search_fields": "parent_cost_center, is_group",
"show_name_in_global_search": 1,
"sort_field": "creation",
"sort_order": "ASC",
"states": []
}
}

View File

@@ -2,10 +2,11 @@
# License: GNU General Public License v3. See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestCostCenter(IntegrationTestCase):
class TestCostCenter(ERPNextTestSuite):
def test_cost_center_creation_against_child_node(self):
cost_center = frappe.get_doc(
{

View File

@@ -1,23 +0,0 @@
[
{
"company": "_Test Company",
"cost_center_name": "_Test Cost Center",
"doctype": "Cost Center",
"is_group": 0,
"parent_cost_center": "_Test Company - _TC"
},
{
"company": "_Test Company",
"cost_center_name": "_Test Cost Center 2",
"doctype": "Cost Center",
"is_group": 0,
"parent_cost_center": "_Test Company - _TC"
},
{
"company": "_Test Company",
"cost_center_name": "_Test Write Off Cost Center",
"doctype": "Cost Center",
"is_group": 0,
"parent_cost_center": "_Test Company - _TC"
}
]

View File

@@ -3,7 +3,6 @@
import frappe
from frappe.query_builder.functions import Sum
from frappe.tests import IntegrationTestCase
from frappe.utils import add_days, today
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
@@ -15,9 +14,10 @@ from erpnext.accounts.doctype.cost_center_allocation.cost_center_allocation impo
WrongPercentageAllocation,
)
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
from erpnext.tests.utils import ERPNextTestSuite
class TestCostCenterAllocation(IntegrationTestCase):
class TestCostCenterAllocation(ERPNextTestSuite):
def setUp(self):
cost_centers = [
"Main Cost Center 1",
@@ -190,7 +190,7 @@ class TestCostCenterAllocation(IntegrationTestCase):
coa2.cancel()
jv.cancel()
@IntegrationTestCase.change_settings("System Settings", {"rounding_method": "Commercial Rounding"})
@ERPNextTestSuite.change_settings("System Settings", {"rounding_method": "Commercial Rounding"})
def test_debit_credit_on_cost_center_allocation_for_commercial_rounding(self):
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice

View File

@@ -2,11 +2,9 @@
# See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
EXTRA_TEST_RECORD_DEPENDENCIES = ["Item"]
from erpnext.tests.utils import ERPNextTestSuite
def test_create_test_data():
@@ -87,6 +85,7 @@ def test_create_test_data():
"partner_name": "_Test Coupon Partner",
"commission_rate": 2,
"referral_code": "COPART",
"territory": "All Territories",
}
)
sales_partner.insert()
@@ -109,13 +108,10 @@ def test_create_test_data():
coupon_code.insert()
class TestCouponCode(IntegrationTestCase):
class TestCouponCode(ERPNextTestSuite):
def setUp(self):
test_create_test_data()
def tearDown(self):
frappe.set_user("Administrator")
def test_sales_order_with_coupon_code(self):
frappe.db.set_value("Coupon Code", "SAVE30", "used", 0)

View File

@@ -101,11 +101,11 @@
"label": "Use HTTP Protocol"
}
],
"hide_toolbar": 1,
"hide_toolbar": 0,
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2026-01-02 18:19:02.873815",
"modified": "2026-03-16 13:28:21.075743",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Currency Exchange Settings",

View File

@@ -2,8 +2,8 @@
# For license information, please see license.txt
# import frappe
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestCurrencyExchangeSettings(IntegrationTestCase):
class TestCurrencyExchangeSettings(ERPNextTestSuite):
pass

View File

@@ -4,37 +4,20 @@ import json
import frappe
from frappe.model import mapper
from frappe.tests import IntegrationTestCase
from frappe.utils import add_days, nowdate, today
from erpnext import get_default_cost_center
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import (
unlink_payment_on_cancel_of_invoice,
)
from erpnext.accounts.doctype.sales_invoice.sales_invoice import (
create_dunning as create_dunning_from_sales_invoice,
)
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import (
create_sales_invoice_against_cost_center,
)
EXTRA_TEST_RECORD_DEPENDENCIES = ["Company", "Cost Center"]
from erpnext.tests.utils import ERPNextTestSuite
class TestDunning(IntegrationTestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
create_dunning_type("First Notice", fee=0.0, interest=0.0, is_default=1)
create_dunning_type("Second Notice", fee=10.0, interest=10.0, is_default=0)
unlink_payment_on_cancel_of_invoice()
@classmethod
def tearDownClass(cls):
unlink_payment_on_cancel_of_invoice(0)
super().tearDownClass()
class TestDunning(ERPNextTestSuite):
def test_dunning_without_fees(self):
dunning = create_dunning(overdue_days=20)

View File

@@ -2,8 +2,8 @@
# See license.txt
# import frappe
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestDunningType(IntegrationTestCase):
class TestDunningType(ERPNextTestSuite):
pass

View File

@@ -1,36 +0,0 @@
[
{
"doctype": "Dunning Type",
"dunning_type": "_Test First Notice",
"company": "_Test Company",
"is_default": 1,
"dunning_fee": 0.0,
"rate_of_interest": 0.0,
"dunning_letter_text": [
{
"language": "en",
"body_text": "We have still not received payment for our invoice",
"closing_text": "We kindly request that you pay the outstanding amount immediately, including interest and late fees."
}
],
"income_account": "Sales - _TC",
"cost_center": "_Test Cost Center - _TC"
},
{
"doctype": "Dunning Type",
"dunning_type": "_Test Second Notice",
"company": "_Test Company",
"is_default": 0,
"dunning_fee": 10.0,
"rate_of_interest": 10.0,
"dunning_letter_text": [
{
"language": "en",
"body_text": "We have still not received payment for our invoice",
"closing_text": "We kindly request that you pay the outstanding amount immediately, including interest and late fees."
}
],
"income_account": "Sales - _TC",
"cost_center": "_Test Cost Center - _TC"
}
]

View File

@@ -5,15 +5,15 @@
import frappe
from frappe.query_builder import functions
from frappe.query_builder.utils import DocType
from frappe.tests import IntegrationTestCase
from frappe.utils import add_days, flt, today
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
from erpnext.tests.utils import ERPNextTestSuite
class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
class TestExchangeRateRevaluation(ERPNextTestSuite, AccountsTestMixin):
def setUp(self):
self.create_company()
self.create_usd_receivable_account()
@@ -22,14 +22,13 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
self.clear_old_entries()
self.set_system_and_company_settings()
def tearDown(self):
frappe.db.rollback()
def set_system_and_company_settings(self):
# set number and currency precision
system_settings = frappe.get_doc("System Settings")
system_settings.float_precision = 2
system_settings.currency_precision = 2
system_settings.language = "en"
system_settings.time_zone = "Asia/Kolkata"
system_settings.save()
# Using Exchange Gain/Loss account for unrealized as well.
@@ -37,7 +36,7 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
company_doc.unrealized_exchange_gain_loss_account = company_doc.exchange_gain_loss_account
company_doc.save()
@IntegrationTestCase.change_settings(
@ERPNextTestSuite.change_settings(
"Accounts Settings",
{"allow_multi_currency_invoices_against_single_party_account": 1, "allow_stale": 0},
)
@@ -91,7 +90,7 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
)[0]
self.assertEqual(acc_balance.balance, 8500.0)
@IntegrationTestCase.change_settings(
@ERPNextTestSuite.change_settings(
"Accounts Settings",
{"allow_multi_currency_invoices_against_single_party_account": 1, "allow_stale": 0},
)
@@ -164,7 +163,7 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
self.assertEqual(acc_balance.balance, 0.0)
self.assertEqual(acc_balance.balance_in_account_currency, 0.0)
@IntegrationTestCase.change_settings(
@ERPNextTestSuite.change_settings(
"Accounts Settings",
{"allow_multi_currency_invoices_against_single_party_account": 1, "allow_stale": 0},
)
@@ -259,7 +258,7 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
self.assertEqual(flt(acc_balance.balance, precision), 0.0)
self.assertEqual(flt(acc_balance.balance_in_account_currency, precision), 0.0)
@IntegrationTestCase.change_settings(
@ERPNextTestSuite.change_settings(
"Accounts Settings",
{"allow_multi_currency_invoices_against_single_party_account": 1, "allow_stale": 0},
)

View File

@@ -2,12 +2,12 @@
# See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
from erpnext.tests.utils import ERPNextTestSuite
class TestFinanceBook(IntegrationTestCase):
class TestFinanceBook(ERPNextTestSuite):
def test_finance_book(self):
finance_book = create_finance_book()

View File

@@ -6,7 +6,7 @@ import json
import math
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from functools import reduce
from functools import cache, reduce
from typing import Any, Union
import frappe
@@ -15,6 +15,7 @@ from frappe.database.operator_map import OPERATOR_MAP
from frappe.query_builder import Case
from frappe.query_builder.functions import Sum
from frappe.utils import cstr, date_diff, flt, getdate
from frappe.utils.xlsxutils import XLSXMetadata, XLSXStyleBuilder
from pypika.terms import Bracket, LiteralValue
from erpnext import get_company_currency
@@ -38,6 +39,9 @@ from erpnext.accounts.report.financial_statements import (
)
from erpnext.accounts.utils import get_children, get_currency_precision
DEFAULT_BULLET_PREFIX = ""
SEGMENT_PREFIX = "seg_"
# ============================================================================
# DATA MODELS
# ============================================================================
@@ -141,7 +145,7 @@ class SegmentData:
@property
def id(self) -> str:
return f"seg_{self.index}"
return f"{SEGMENT_PREFIX}{self.index}"
@dataclass
@@ -222,14 +226,38 @@ class FinancialReportEngine:
return context.get_result()
def _validate_filters(self, filters: dict[str, Any]) -> None:
required_filters = ["report_template", "period_start_date", "period_end_date"]
filter_labels = {
"report_template": _("Report Template"),
"filter_based_on": _("Filter Based On"),
"period_start_date": _("Start Date"),
"period_end_date": _("End Date"),
"from_fiscal_year": _("Start Year"),
"to_fiscal_year": _("End Year"),
}
required_filters_by_basis = {
"Date Range": ("period_start_date", "period_end_date"),
"Fiscal Year": ("from_fiscal_year", "to_fiscal_year"),
}
required_filters = ["report_template", "filter_based_on"]
required_filters.extend(required_filters_by_basis.get(filters.get("filter_based_on"), ()))
for filter_key in required_filters:
if not filters.get(filter_key):
frappe.throw(_("Missing required filter: {0}").format(filter_key))
frappe.throw(
title=_("Missing Required Filter"),
msg=_("Missing required filter: {0}").format(
frappe.bold(filter_labels.get(filter_key, filter_key))
),
)
if filters.get("presentation_currency"):
frappe.msgprint(_("Currency filters are currently unsupported in Custom Financial Report."))
frappe.msgprint(
title=_("Unsupported Feature"),
msg=_("Currency filters are currently unsupported in Custom Financial Report."),
indicator="orange",
)
# Margin view is dependent on first row being an income account. Hence not supported.
# Way to implement this would be using calculated rows with formulas.
@@ -464,6 +492,7 @@ class FinancialQueryBuilder:
self.periods = periods
self.company = filters.get("company")
self.account_meta = {} # {name: {account_name, account_number}}
self.ignore_opening_entries = False
def fetch_account_balances(self, accounts: list[dict]) -> dict[str, AccountData]:
"""
@@ -501,6 +530,8 @@ class FinancialQueryBuilder:
"""
Return opening balances for *all accounts* defaulting to zero.
"""
self.ignore_opening_entries = False
if frappe.get_single_value("Accounts Settings", "ignore_account_closing_balance"):
return self._get_opening_balances_from_gl(accounts)
@@ -520,9 +551,9 @@ class FinancialQueryBuilder:
if last_closing_voucher:
closing_voucher = last_closing_voucher[0]
closing_data = self._get_closing_balances(accounts, closing_voucher.name)
self.ignore_opening_entries = True # Else it will double count
if sum(closing_data.values()) != 0.0:
return self._rebase_closing_balances(closing_data, closing_voucher.period_end_date)
return self._rebase_closing_balances(closing_data, closing_voucher.period_end_date)
return self._get_opening_balances_from_gl(accounts)
@@ -616,7 +647,12 @@ class FinancialQueryBuilder:
.groupby(gl_table.account)
)
if not frappe.get_single_value("Accounts Settings", "ignore_is_opening_check_for_reporting"):
ignore_is_opening = frappe.get_single_value(
"Accounts Settings", "ignore_is_opening_check_for_reporting"
)
if self.ignore_opening_entries and not ignore_is_opening:
# This filter here applies to all accounts (BS & PL)
# However, in legacy query, this filter only applies to BS accounts
query = query.where(gl_table.is_opening == "No")
# Add period-specific columns
@@ -680,11 +716,18 @@ class FinancialQueryBuilder:
account_data.unaccumulate_values()
def _apply_standard_filters(self, query, table, doctype: str = "GL Entry"):
if self.filters.get("ignore_closing_entries"):
if doctype == "GL Entry":
query = query.where(table.voucher_type != "Period Closing Voucher")
else:
query = query.where(table.is_period_closing_voucher_entry == 0)
# Exclude PCV-generated entries except those posted to a closing-account-head
# so BS retained earnings survive while P&L reversal entries are filtered out
pcv = frappe.qb.DocType("Period Closing Voucher")
closing_heads = frappe.qb.from_(pcv).select(pcv.closing_account_head).where(pcv.docstatus == 1)
if doctype == "GL Entry":
is_pcv = table.voucher_type == "Period Closing Voucher"
else:
# Account Closing Balance
is_pcv = table.is_period_closing_voucher_entry == 1
query = query.where(~is_pcv | table.account.isin(closing_heads))
if self.filters.get("project"):
projects = self.filters.get("project")
@@ -1392,7 +1435,8 @@ class FormattingEngine:
condition=lambda rd: getattr(rd.row, "italic_text", False), format_properties={"italic": True}
),
FormattingRule(
condition=lambda rd: rd.is_detail_row, format_properties={"is_detail": True, "prefix": ""}
condition=lambda rd: rd.is_detail_row,
format_properties={"is_detail": True, "prefix": DEFAULT_BULLET_PREFIX},
),
FormattingRule(
condition=lambda rd: getattr(rd.row, "warn_if_negative", False),
@@ -1838,3 +1882,124 @@ class GrowthViewTransformer:
return 0.0
else:
return flt(((current_value - previous_value) / abs(previous_value)) * 100, 2)
# ============================================================================
# XLSX EXPORT STYLING
# ============================================================================
def get_xlsx_styles(metadata: XLSXMetadata) -> dict | None:
"""
Generate XLSX styles for financial report templates.
NOTE: Currently only custom report generated with "Report Template" filter will have styles applied.
"""
# skip styling
if not metadata.filters.get("report_template"):
return
builder = XLSXStyleBuilder(metadata, default_styling=False)
builder.apply_default_styles(currency_formatting=False)
# currency is fixed for all columns (only if report template filter is applied)
currency = get_company_currency(metadata.filters.get("company"))
styles = {
"bold": builder.register_style({"bold": True}),
"italic": builder.register_style({"italic": True}),
"warning": builder.register_style({"font_color": "#dc3545"}), # text-danger
}
fieldtype_formats = {
"Int": builder.register_style({"num_format": "General"}),
"Float": builder.register_style({"num_format": builder.get_number_format("Float")}),
"Percent": builder.register_style({"num_format": builder.get_number_format("Percent")}),
"Currency": builder.register_style({"num_format": builder.get_number_format("Currency", currency)}),
}
# quick access for hot loop
style_cell = builder.style_cell
@cache
def get_color_style(color: str) -> int:
return builder.register_style({"font_color": color})
@cache
def get_prefix_style(prefix: str) -> int:
prefix = f"{prefix or DEFAULT_BULLET_PREFIX}@"
return builder.register_style({"num_format": prefix})
@cache
def get_indent_style(indent: int) -> int:
return builder.register_style({"align": "left", "indent": indent})
# column level styling of currency columns
for col_idx, col in metadata.column_map.items():
if col.get("fieldtype") != "Currency":
continue
builder.style_column(col_idx, fieldtype_formats["Currency"])
# cell level styling
for row_idx, row in metadata.row_map.items():
# skip total row
if metadata.has_total_row and row_idx == builder.last_row_index:
continue
is_segmented = (row.get("_segment_info", {}).get("total_segments", 1) or 1) > 1
segment_values = row.get("segment_values", {}) or {}
for col_idx, col in metadata.column_map.items():
fieldname = col.get("fieldname")
is_account = fieldname == "account"
# determine formatting bucket
if is_segmented and fieldname.startswith(SEGMENT_PREFIX):
formatting = row.copy()
_, seg_idx, seg_fieldname = fieldname.split("_", 2)
is_account = seg_fieldname == "account"
formatting.update(segment_values.get(f"{SEGMENT_PREFIX}{seg_idx}", {}) or {})
else:
formatting = row # default formatting bucket.
if not is_account and formatting.get("is_blank_line"):
continue
col_fieldtype = col.get("fieldtype")
cell_fieldtype = formatting.get("fieldtype") or col_fieldtype
cell_value = row.get(fieldname)
if cell_value in (None, ""):
continue
# account column and other fieldtype styling
if is_account:
if formatting.get("is_detail") or (prefix := formatting.get("prefix")):
style_cell(row_idx, col_idx, get_prefix_style(prefix))
# custom indentation (different segment might have different indentation levels)
if is_segmented and (indent := formatting.get("indent")) and indent > 0:
style_cell(row_idx, col_idx, get_indent_style(indent))
else:
if col_fieldtype != cell_fieldtype and cell_fieldtype in fieldtype_formats:
style_cell(row_idx, col_idx, fieldtype_formats[cell_fieldtype])
# text styles
for style_key in ("bold", "italic"):
if formatting.get(style_key):
style_cell(row_idx, col_idx, styles[style_key])
# color styles
if (
formatting.get("warn_if_negative")
and cell_fieldtype in frappe.model.numeric_fieldtypes
and flt(cell_value) < 0
):
style_cell(row_idx, col_idx, styles["warning"])
elif color := formatting.get("color"):
style_cell(row_idx, col_idx, get_color_style(color))
return builder.result

View File

@@ -3,6 +3,8 @@
frappe.ui.form.on("Financial Report Template", {
refresh(frm) {
if (frm.is_new() || frm.doc.rows.length === 0) return;
// add custom button to view missed accounts
frm.add_custom_button(__("View Account Coverage"), function () {
let selected_rows = frm.get_field("rows").grid.get_selected_children();
@@ -20,7 +22,7 @@ frappe.ui.form.on("Financial Report Template", {
});
},
validate(frm) {
after_save(frm) {
if (!frm.doc.rows || frm.doc.rows.length === 0) {
frappe.msgprint(__("At least one row is required for a financial report template"));
}
@@ -34,14 +36,6 @@ frappe.ui.form.on("Financial Report Row", {
update_formula_label(frm, row.data_source);
update_formula_description(frm, row.data_source);
if (row.data_source !== "Account Data") {
frappe.model.set_value(cdt, cdn, "balance_type", "");
}
if (["Blank Line", "Column Break", "Section Break"].includes(row.data_source)) {
frappe.model.set_value(cdt, cdn, "calculation_formula", "");
}
set_up_filters_editor(frm, cdt, cdn);
},
@@ -322,6 +316,8 @@ function update_formula_description(frm, data_source) {
const list_style = `style="margin-bottom: var(--margin-sm); color: var(--text-muted); font-size: 0.9em;"`;
const note_style = `style="margin-bottom: 0; color: var(--text-muted); font-size: 0.9em;"`;
const tip_style = `style="margin-bottom: 0; color: var(--text-color); font-size: 0.85em;"`;
const code_style = `style="background: var(--bg-light-gray); padding: var(--padding-xs); border-radius: var(--border-radius); font-size: 0.85em; width: max-content; margin-bottom: var(--margin-sm);"`;
const pre_style = `style="margin: 0; border-radius: var(--border-radius)"`;
let description_html = "";
@@ -382,8 +378,13 @@ function update_formula_description(frm, data_source) {
<li><code>my_app.financial_reports.get_kpi_data</code></li>
</ul>
<h6 ${subtitle_style}>Method Signature:</h6>
<div ${code_style}>
<pre ${pre_style}>def get_custom_data(filters, periods, row): <br>&nbsp; # filters: dict — report filters (company, period, etc.) <br>&nbsp; # periods: list[dict] — period definitions <br>&nbsp; # row: dict — the current report row <br><br>&nbsp; return [1000.0, 1200.0, 1150.0] # one value per period</pre>
</div>
<h6 ${subtitle_style}>Return Format:</h6>
<p ${text_style}>Numbers for each period: <code>[1000.0, 1200.0, 1150.0]</code></p>
<p ${text_style}>A list of numbers, one for each period: <code>[1000.0, 1200.0, 1150.0]</code></p>
</div>`;
} else if (data_source === "Blank Line") {
description_html = `

View File

@@ -1,6 +1,5 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "field:template_name",
"creation": "2025-08-02 04:44:15.184541",
"doctype": "DocType",
@@ -31,7 +30,8 @@
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Report Type",
"options": "\nProfit and Loss Statement\nBalance Sheet\nCash Flow\nCustom Financial Statement"
"options": "\nProfit and Loss Statement\nBalance Sheet\nCash Flow\nCustom Financial Statement",
"reqd": 1
},
{
"depends_on": "eval:frappe.boot.developer_mode",
@@ -66,7 +66,7 @@
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-11-14 00:11:03.508139",
"modified": "2026-02-23 01:04:05.797161",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Financial Report Template",

View File

@@ -31,6 +31,19 @@ class FinancialReportTemplate(Document):
template_name: DF.Data
# end: auto-generated types
def before_validate(self):
self.clear_hidden_fields()
def clear_hidden_fields(self):
style_data_sources = {"Blank Line", "Column Break", "Section Break"}
for row in self.rows:
if row.data_source != "Account Data":
row.balance_type = None
if row.data_source in style_data_sources:
row.calculation_formula = None
def validate(self):
validator = TemplateValidator(self)
result = validator.validate()

View File

@@ -67,8 +67,8 @@ class ValidationResult:
self.warnings.append(issue)
def notify_user(self) -> None:
warnings = "<br><br>".join(str(w) for w in self.warnings)
errors = "<br><br>".join(str(e) for e in self.issues)
warnings = "<br><br>".join(str(w) for w in self.warnings if w)
errors = "<br><br>".join(str(e) for e in self.issues if e)
if warnings:
frappe.msgprint(warnings, title=_("Warnings"), indicator="orange")
@@ -96,9 +96,8 @@ class TemplateValidator:
result.merge(validator.validate(self.template))
# Run row-level validations
account_fields = {field.fieldname for field in frappe.get_meta("Account").fields}
for row in self.template.rows:
result.merge(self.formula_validator.validate(row, account_fields))
result.merge(self.formula_validator.validate(row))
return result
@@ -380,7 +379,8 @@ class AccountFilterValidator(Validator):
"""Validates account filter expressions used in Account Data rows"""
def __init__(self, account_fields: set | None = None):
self.account_fields = account_fields or set(frappe.get_meta("Account")._valid_columns)
self.account_meta = frappe.get_meta("Account")
self.account_fields = account_fields or set(self.account_meta._valid_columns)
def validate(self, row) -> ValidationResult:
result = ValidationResult()
@@ -400,7 +400,11 @@ class AccountFilterValidator(Validator):
try:
filter_config = json.loads(row.calculation_formula)
error = self._validate_filter_structure(filter_config, self.account_fields)
error = self._validate_filter_structure(
filter_config,
self.account_fields,
row.advanced_filtering,
)
if error:
result.add_error(
@@ -422,7 +426,12 @@ class AccountFilterValidator(Validator):
return result
def _validate_filter_structure(self, filter_config, account_fields: set) -> str | None:
def _validate_filter_structure(
self,
filter_config,
account_fields: set,
advanced_filtering: bool = False,
) -> str | None:
# simple condition: [field, operator, value]
if isinstance(filter_config, list):
if len(filter_config) != 3:
@@ -433,8 +442,10 @@ class AccountFilterValidator(Validator):
if not isinstance(field, str) or not isinstance(operator, str):
return "Field and operator must be strings"
display = (field if advanced_filtering else self.account_meta.get_label(field)) or field
if field not in account_fields:
return f"Field '{field}' is not a valid account field"
return f"Field '{display}' is not a valid Account field"
if operator.casefold() not in OPERATOR_MAP:
return f"Invalid operator '{operator}'"
@@ -457,7 +468,7 @@ class AccountFilterValidator(Validator):
# recursive
for condition in conditions:
error = self._validate_filter_structure(condition, account_fields)
error = self._validate_filter_structure(condition, account_fields, advanced_filtering)
if error:
return error
else:
@@ -473,7 +484,7 @@ class FormulaValidator(Validator):
self.calculation_validator = CalculationFormulaValidator(reference_codes)
self.account_filter_validator = AccountFilterValidator()
def validate(self, row, account_fields: set) -> ValidationResult:
def validate(self, row) -> ValidationResult:
result = ValidationResult()
if not row.calculation_formula:
@@ -483,9 +494,6 @@ class FormulaValidator(Validator):
return self.calculation_validator.validate(row)
elif row.data_source == "Account Data":
# Update account fields if provided
if account_fields:
self.account_filter_validator.account_fields = account_fields
return self.account_filter_validator.validate(row)
elif row.data_source == "Custom API":

View File

@@ -8,6 +8,7 @@ from erpnext.accounts.doctype.financial_report_template.financial_report_engine
DependencyResolver,
FilterExpressionParser,
FinancialQueryBuilder,
FinancialReportEngine,
FormulaCalculator,
)
from erpnext.accounts.doctype.financial_report_template.test_financial_report_template import (
@@ -16,12 +17,6 @@ from erpnext.accounts.doctype.financial_report_template.test_financial_report_te
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
from erpnext.accounts.utils import get_currency_precision, get_fiscal_year
# On IntegrationTestCase, the doctype test records and all
# link-field test record dependencies are recursively loaded
# Use these module variables to add/remove to/from that list
EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
class TestDependencyResolver(FinancialReportTemplateTestCase):
"""Test cases for DependencyResolver class"""
@@ -1298,6 +1293,7 @@ class TestFilterExpressionParser(FinancialReportTemplateTestCase):
self.data_source = "Account Data"
self.idx = 1
self.reverse_sign = 0
self.advanced_filtering = True
return MockReportRow(formula, reference_code)
@@ -1954,6 +1950,159 @@ class TestFinancialQueryBuilder(FinancialReportTemplateTestCase):
jv_2023.cancel()
def test_opening_entries_roll_into_opening_after_period_closing(self):
"""
Sequence:
1. is_opening JV of 3000 in current year (FY 2024)
2. is_opening JV of 5000 in next year (FY 2025)
3. Period Closing Voucher for previous year (FY 2023)
Expected (BS report for FY 2024):
opening of FY 2024 = 3000 + 5000 = 8000
(all is_opening entries roll into opening irrespective of fiscal year,
on top of the PCV carry-forward — here PCV closing for cash is 0).
"""
company = "_Test Company"
cash_account = "_Test Cash - _TC"
# Opening JVs cannot post against P&L accounts; use a Balance Sheet offset.
opening_offset_account = "Temporary Opening - _TC"
pcv = None
jv_current_year = None
jv_next_year = None
original_pcv_setting = frappe.db.get_single_value(
"Accounts Settings", "use_legacy_controller_for_pcv"
)
try:
# Step 1: opening JV in current year (FY 2024) — must be posted before PCV
# exists, else `validate_against_pcv` rejects it.
jv_current_year = make_journal_entry(
account1=cash_account,
account2=opening_offset_account,
amount=3000,
posting_date="2024-06-15",
company=company,
save=False,
)
jv_current_year.is_opening = "Yes"
jv_current_year.insert()
jv_current_year.submit()
# Step 2: opening JV in next year (FY 2025)
jv_next_year = make_journal_entry(
account1=cash_account,
account2=opening_offset_account,
amount=5000,
posting_date="2025-06-15",
company=company,
save=False,
)
jv_next_year.is_opening = "Yes"
jv_next_year.insert()
jv_next_year.submit()
# Step 3: book Period Closing Voucher for previous year (FY 2023)
closing_account = frappe.db.get_value(
"Account",
{
"company": company,
"root_type": "Liability",
"is_group": 0,
"account_type": ["not in", ["Payable", "Receivable"]],
},
"name",
)
fy_2023 = get_fiscal_year("2023-06-15", company=company)
frappe.db.set_single_value("Accounts Settings", "use_legacy_controller_for_pcv", 1)
pcv = frappe.get_doc(
{
"doctype": "Period Closing Voucher",
"transaction_date": "2023-12-31",
"period_start_date": fy_2023[1],
"period_end_date": fy_2023[2],
"company": company,
"fiscal_year": fy_2023[0],
"cost_center": "_Test Cost Center - _TC",
"closing_account_head": closing_account,
"remarks": "Test Period Closing",
}
)
pcv.insert()
pcv.submit()
pcv.reload()
# Run BS report for FY 2024
filters = {
"company": company,
"from_fiscal_year": "2024",
"to_fiscal_year": "2024",
"period_start_date": "2024-01-01",
"period_end_date": "2024-12-31",
"filter_based_on": "Date Range",
"periodicity": "Yearly",
"ignore_closing_entries": True,
}
periods = [{"key": "2024", "from_date": "2024-01-01", "to_date": "2024-12-31"}]
query_builder = FinancialQueryBuilder(filters, periods)
accounts = [
frappe._dict({"name": cash_account, "account_name": "Cash", "account_number": "1001"}),
frappe._dict(
{
"name": opening_offset_account,
"account_name": "Temporary Opening",
"account_number": "1900",
}
),
]
balances_data = query_builder.fetch_account_balances(accounts)
cash_data = balances_data.get(cash_account)
offset_data = balances_data.get(opening_offset_account)
self.assertIsNotNone(cash_data, "Cash account should exist in results")
self.assertIsNotNone(offset_data, "Offset account should exist in results")
year_2024_cash = cash_data.get_period("2024")
year_2024_offset = offset_data.get_period("2024")
self.assertIsNotNone(year_2024_cash, "FY 2024 period should exist for cash")
self.assertIsNotNone(year_2024_offset, "FY 2024 period should exist for offset")
# All is_opening JVs (current + next year) roll into FY 2024 opening
self.assertEqual(
year_2024_cash.opening,
8000.0,
"FY 2024 cash opening must combine is_opening JVs from current and next year",
)
self.assertEqual(
year_2024_offset.opening,
-8000.0,
"FY 2024 offset opening must combine is_opening JVs from current and next year",
)
self.assertEqual(
year_2024_cash.movement, 0.0, "Opening JVs must not be counted as period movement"
)
self.assertEqual(year_2024_cash.closing, 8000.0, "Closing = opening when no non-opening movement")
finally:
frappe.db.set_single_value(
"Accounts Settings", "use_legacy_controller_for_pcv", original_pcv_setting or 0
)
if pcv:
pcv.reload()
if pcv.docstatus == 1:
pcv.cancel()
if jv_next_year and jv_next_year.docstatus == 1:
jv_next_year.cancel()
if jv_current_year and jv_current_year.docstatus == 1:
jv_current_year.cancel()
def test_account_with_gl_entries_but_no_prior_closing_balance(self):
company = "_Test Company"
cash_account = "_Test Cash - _TC"
@@ -2027,3 +2176,210 @@ class TestFinancialQueryBuilder(FinancialReportTemplateTestCase):
finally:
jv.cancel()
def test_pl_pcv_exclusion_and_growth_view_year_over_year(self):
"""
Sequence:
1. Expense JV 2000 in FY 2024, PCV for FY 2024
→ assert FY 2024 movement = 2000 via FinancialQueryBuilder
2. Expense JV 3000 in FY 2025, PCV for FY 2025
3. Run FinancialReportEngine with selected_view="Growth"
→ assert col_2024 = 2000 (raw), col_2025 = 50.0 (% growth)
"""
company = "_Test Company"
expense_account = "Administrative Expenses - _TC"
bank_account = "_Test Bank - _TC"
template = None
pcv_2024 = None
pcv_2025 = None
jv_2024 = None
jv_2025 = None
original_pcv_setting = frappe.db.get_single_value(
"Accounts Settings", "use_legacy_controller_for_pcv"
)
try:
closing_account = frappe.db.get_value(
"Account",
{
"company": company,
"root_type": "Liability",
"is_group": 0,
"account_type": ["not in", ["Payable", "Receivable"]],
},
"name",
)
frappe.db.set_single_value("Accounts Settings", "use_legacy_controller_for_pcv", 1)
accounts = [
frappe._dict(
{
"name": expense_account,
"account_name": "Administrative Expenses",
"account_number": "5001",
}
),
]
# --- Step 1: FY 2024 expense + PCV, assert PCV reversal excluded ---
jv_2024 = make_journal_entry(
account1=expense_account,
account2=bank_account,
amount=2000,
posting_date="2024-06-15",
company=company,
submit=True,
)
fy_2024 = get_fiscal_year("2024-06-15", company=company)
pcv_2024 = frappe.get_doc(
{
"doctype": "Period Closing Voucher",
"transaction_date": "2024-12-31",
"period_start_date": fy_2024[1],
"period_end_date": fy_2024[2],
"company": company,
"fiscal_year": fy_2024[0],
"cost_center": "_Test Cost Center - _TC",
"closing_account_head": closing_account,
"remarks": "Test PCV FY 2024",
}
)
pcv_2024.insert()
pcv_2024.submit()
pcv_2024.reload()
builder_2024 = FinancialQueryBuilder(
{
"company": company,
"from_fiscal_year": "2024",
"to_fiscal_year": "2024",
"period_start_date": "2024-01-01",
"period_end_date": "2024-12-31",
"filter_based_on": "Date Range",
"periodicity": "Yearly",
},
[{"key": "2024", "from_date": "2024-01-01", "to_date": "2024-12-31"}],
)
data_2024 = builder_2024.fetch_account_balances(accounts)
expense_2024 = data_2024.get(expense_account)
self.assertIsNotNone(expense_2024, "Expense account must appear in FY 2024 results")
year_2024 = expense_2024.get_period("2024")
self.assertEqual(
year_2024.movement,
2000.0,
"FY 2024 expense movement must equal real expense (PCV reversal excluded)",
)
# --- Step 2: FY 2025 expense + PCV ---
jv_2025 = make_journal_entry(
account1=expense_account,
account2=bank_account,
amount=3000,
posting_date="2025-06-15",
company=company,
submit=True,
)
fy_2025 = get_fiscal_year("2025-06-15", company=company)
pcv_2025 = frappe.get_doc(
{
"doctype": "Period Closing Voucher",
"transaction_date": "2025-12-31",
"period_start_date": fy_2025[1],
"period_end_date": fy_2025[2],
"company": company,
"fiscal_year": fy_2025[0],
"cost_center": "_Test Cost Center - _TC",
"closing_account_head": closing_account,
"remarks": "Test PCV FY 2025",
}
)
pcv_2025.insert()
pcv_2025.submit()
pcv_2025.reload()
# --- Step 3: full pipeline with Growth view across both years ---
template_name = f"Test Growth Template {frappe.generate_hash()[:8]}"
template = frappe.get_doc(
{
"doctype": "Financial Report Template",
"template_name": template_name,
"report_type": "Profit and Loss Statement",
"rows": [
{
"reference_code": "EXP_ADMIN",
"display_name": "Administrative Expenses",
"indentation_level": 0,
"data_source": "Account Data",
"balance_type": "Closing Balance",
"calculation_formula": f'["name", "=", "{expense_account}"]',
},
],
}
)
template.insert()
filters = frappe._dict(
{
"company": company,
"report_template": template_name,
"from_fiscal_year": fy_2024[0],
"to_fiscal_year": fy_2025[0],
"period_start_date": "2024-01-01",
"period_end_date": "2025-12-31",
"filter_based_on": "Date Range",
"periodicity": "Yearly",
"accumulated_values": 0,
"selected_view": "Growth",
}
)
_columns, formatted_data, _msg, _chart = FinancialReportEngine().execute(filters)
expense_row = next(
(row for row in formatted_data if row.get("account_name") == "Administrative Expenses"),
None,
)
self.assertIsNotNone(expense_row, "Administrative Expenses row must appear in growth view")
period_keys = expense_row.get("_segment_info", {}).get("period_keys", [])
self.assertEqual(len(period_keys), 2, "Yearly view must yield exactly two periods")
first_period_key, second_period_key = period_keys
# First column: raw absolute value (FY 2024 expense)
self.assertEqual(
flt(expense_row[first_period_key]),
2000.0,
"First column in growth view must keep raw FY 2024 expense value",
)
# Second column: ((3000 - 2000) / 2000) * 100 = 50.0
self.assertEqual(
flt(expense_row[second_period_key]),
50.0,
"Second column must be % growth FY 2024 → FY 2025",
)
finally:
frappe.db.set_single_value(
"Accounts Settings", "use_legacy_controller_for_pcv", original_pcv_setting or 0
)
if pcv_2025:
pcv_2025.reload()
if pcv_2025.docstatus == 1:
pcv_2025.cancel()
if jv_2025 and jv_2025.docstatus == 1:
jv_2025.cancel()
if pcv_2024:
pcv_2024.reload()
if pcv_2024.docstatus == 1:
pcv_2024.cancel()
if jv_2024 and jv_2024.docstatus == 1:
jv_2024.cancel()
if template and frappe.db.exists("Financial Report Template", template.name):
frappe.delete_doc("Financial Report Template", template.name, force=1)

View File

@@ -2,29 +2,16 @@
# For license information, please see license.txt
import frappe
from frappe.tests import IntegrationTestCase
from frappe.tests.utils import make_test_records
# On IntegrationTestCase, the doctype test records and all
# link-field test record dependencies are recursively loaded
# Use these module variables to add/remove to/from that list
EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
from erpnext.tests.utils import ERPNextTestSuite
class TestFinancialReportTemplate(IntegrationTestCase):
pass
class FinancialReportTemplateTestCase(IntegrationTestCase):
class FinancialReportTemplateTestCase(ERPNextTestSuite):
"""Utility class with common setup and helper methods for all test classes"""
@classmethod
def setUpClass(cls):
def setUp(self):
"""Set up test data"""
make_test_records("Company")
make_test_records("Fiscal Year")
cls.create_test_template()
self.create_test_template()
@classmethod
def create_test_template(cls):

View File

@@ -2,13 +2,12 @@
# License: GNU General Public License v3. See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import now_datetime
IGNORE_TEST_RECORD_DEPENDENCIES = ["Company"]
from erpnext.tests.utils import ERPNextTestSuite
class TestFiscalYear(IntegrationTestCase):
class TestFiscalYear(ERPNextTestSuite):
def test_extra_year(self):
if frappe.db.exists("Fiscal Year", "_Test Fiscal Year 2000"):
frappe.delete_doc("Fiscal Year", "_Test Fiscal Year 2000")

View File

@@ -5,6 +5,7 @@
"doctype": "DocType",
"document_type": "Document",
"engine": "InnoDB",
"is_submittable": 1,
"field_order": [
"dates_section",
"posting_date",

View File

@@ -489,4 +489,5 @@ def rename_temporarily_named_docs(doctype):
for hook in frappe.get_hooks(hook_type):
frappe.call(hook, newname=newname, oldname=oldname)
frappe.db.commit()
if not frappe.in_test:
frappe.db.commit()

View File

@@ -3,13 +3,13 @@
import frappe
from frappe.model.naming import parse_naming_series
from frappe.tests import IntegrationTestCase
from erpnext.accounts.doctype.gl_entry.gl_entry import rename_gle_sle_docs
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
from erpnext.tests.utils import ERPNextTestSuite
class TestGLEntry(IntegrationTestCase):
class TestGLEntry(ERPNextTestSuite):
def test_round_off_entry(self):
frappe.db.set_value("Company", "_Test Company", "round_off_account", "_Test Write Off - _TC")
frappe.db.set_value("Company", "_Test Company", "round_off_cost_center", "_Test Cost Center - _TC")

View File

@@ -2,16 +2,16 @@
# See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import add_days, flt, nowdate
from erpnext.accounts.doctype.account.test_account import create_account
from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry_against_invoice
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries
from erpnext.tests.utils import ERPNextTestSuite
class TestInvoiceDiscounting(IntegrationTestCase):
class TestInvoiceDiscounting(ERPNextTestSuite):
def setUp(self):
self.ar_credit = create_account(
account_name="_Test Accounts Receivable Credit",

View File

@@ -47,3 +47,12 @@ frappe.ui.form.on("Item Tax Template", {
});
},
});
frappe.ui.form.on("Item Tax Template Detail", {
not_applicable: function (frm, cdt, cdn) {
let row = locals[cdt][cdn];
if (row.not_applicable) {
frappe.model.set_value(cdt, cdn, "tax_rate", 0);
}
},
});

View File

@@ -27,8 +27,15 @@ class ItemTaxTemplate(Document):
# end: auto-generated types
def validate(self):
self.set_zero_rate_for_not_applicable_tax()
self.validate_tax_accounts()
def set_zero_rate_for_not_applicable_tax(self):
"""Ensure tax_rate is 0 for any row marked as not applicable."""
for row in self.get("taxes"):
if row.not_applicable:
row.tax_rate = 0
def autoname(self):
if self.company and self.title:
abbr = frappe.get_cached_value("Company", self.company, "abbr")

View File

@@ -1,8 +1,8 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestItemTaxTemplate(IntegrationTestCase):
class TestItemTaxTemplate(ERPNextTestSuite):
pass

View File

@@ -1,79 +0,0 @@
[
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 10",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 10,
"tax_type": "_Test Account Excise Duty - _TC"
}
]
},
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 12",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 12,
"tax_type": "_Test Account Excise Duty - _TC"
}
]
},
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 15",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 15,
"tax_type": "_Test Account Excise Duty - _TC"
}
]
},
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 20",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 20,
"tax_type": "_Test Account Excise Duty - _TC"
}
]
},
{
"doctype": "Item Tax Template",
"title": "_Test Item Tax Template 1",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 5,
"tax_type": "_Test Account Excise Duty - _TC"
},
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 10,
"tax_type": "_Test Account Education Cess - _TC"
},
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 15,
"tax_type": "_Test Account S&H Education Cess - _TC"
}
]
}
]

View File

@@ -6,7 +6,8 @@
"engine": "InnoDB",
"field_order": [
"tax_type",
"tax_rate"
"tax_rate",
"not_applicable"
],
"fields": [
{
@@ -21,20 +22,30 @@
"fieldname": "tax_rate",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Tax Rate"
"label": "Tax Rate",
"read_only_depends_on": "eval:doc.not_applicable"
},
{
"default": "0",
"description": "Check if this tax is not applicable to items (distinct from 0% rate)",
"fieldname": "not_applicable",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Not Applicable"
}
],
"istable": 1,
"links": [],
"modified": "2024-03-27 13:09:55.735360",
"modified": "2025-12-26 17:19:18.791891",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Item Tax Template Detail",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
}

View File

@@ -14,6 +14,7 @@ class ItemTaxTemplateDetail(Document):
if TYPE_CHECKING:
from frappe.types import DF
not_applicable: DF.Check
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data

View File

@@ -648,7 +648,7 @@ $.extend(erpnext.journal_entry, {
reqd: 1,
default: frm.doc.posting_date,
},
{ fieldtype: "Small Text", fieldname: "user_remark", label: __("User Remark") },
{ fieldtype: "Small Text", fieldname: "remark", label: __("Remark") },
{
fieldtype: "Select",
fieldname: "naming_series",
@@ -665,8 +665,14 @@ $.extend(erpnext.journal_entry, {
var values = dialog.get_values();
frm.set_value("posting_date", values.posting_date);
frm.set_value("user_remark", values.user_remark);
frm.set_value("naming_series", values.naming_series);
if (values.remark) {
frm.set_value("custom_remark", 1);
frm.set_value("remark", values.remark);
} else {
frm.set_value("custom_remark", 0);
frm.set_value("remark", "");
}
// clear table is used because there might've been an error while adding child
// and cleanup didn't happen

View File

@@ -39,7 +39,7 @@
"clearance_date",
"column_break_oizh",
"user_remark",
"subscription_section",
"auto_repeat_section",
"auto_repeat",
"tax_withholding_tab",
"section_tax_withholding_entry",
@@ -78,6 +78,7 @@
"from_template",
"title",
"column_break3",
"custom_remark",
"remark",
"mode_of_payment",
"party_not_required"
@@ -140,6 +141,7 @@
{
"fieldname": "company",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"oldfieldname": "company",
@@ -181,7 +183,6 @@
"fieldname": "cheque_no",
"fieldtype": "Data",
"in_global_search": 1,
"in_list_view": 1,
"label": "Reference Number",
"mandatory_depends_on": "eval:doc.voucher_type == \"Bank Entry\"",
"no_copy": 1,
@@ -202,6 +203,7 @@
{
"fieldname": "user_remark",
"fieldtype": "Small Text",
"hidden": 1,
"label": "User Remark",
"no_copy": 1,
"oldfieldname": "user_remark",
@@ -315,7 +317,7 @@
"no_copy": 1,
"oldfieldname": "remark",
"oldfieldtype": "Small Text",
"read_only": 1
"read_only_depends_on": "eval: !doc.custom_remark"
},
{
"depends_on": "eval:doc.voucher_type== \"Inter Company Journal Entry\"",
@@ -475,11 +477,6 @@
"options": "Stock Entry",
"read_only": 1
},
{
"fieldname": "subscription_section",
"fieldtype": "Section Break",
"label": "Subscription"
},
{
"allow_on_submit": 1,
"fieldname": "auto_repeat",
@@ -651,6 +648,17 @@
"fieldname": "tax_withholding_tab",
"fieldtype": "Tab Break",
"label": "Tax Withholding"
},
{
"fieldname": "auto_repeat_section",
"fieldtype": "Section Break",
"label": "Auto Repeat"
},
{
"default": "0",
"fieldname": "custom_remark",
"fieldtype": "Check",
"label": "Custom Remark"
}
],
"icon": "fa fa-file-text",
@@ -665,7 +673,7 @@
"table_fieldname": "payment_entries"
}
],
"modified": "2026-02-16 16:06:10.468482",
"modified": "2026-04-08 14:19:30.870894",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry",

View File

@@ -62,6 +62,7 @@ class JournalEntry(AccountsController):
cheque_no: DF.Data | None
clearance_date: DF.Date | None
company: DF.Link
custom_remark: DF.Check
difference: DF.Currency
due_date: DF.Date | None
finance_book: DF.Link | None
@@ -294,6 +295,8 @@ class JournalEntry(AccountsController):
# References for this Journal are removed on the `on_cancel` event in accounts_controller
super().on_cancel()
from_doc_events = getattr(self, "ignore_linked_doctypes", ())
self.ignore_linked_doctypes = (
"GL Entry",
"Stock Ledger Entry",
@@ -307,6 +310,10 @@ class JournalEntry(AccountsController):
"Advance Payment Ledger Entry",
"Tax Withholding Entry",
)
if from_doc_events and from_doc_events != self.ignore_linked_doctypes:
self.ignore_linked_doctypes = self.ignore_linked_doctypes + from_doc_events
self.make_gl_entries(1)
JournalTaxWithholding(self).on_cancel()
self.unlink_advance_entry_reference()
@@ -348,8 +355,11 @@ class JournalEntry(AccountsController):
frappe.throw(_("Account {0} should be of type Expense").format(d.account))
def validate_stock_accounts(self):
if self.voucher_type == "Periodic Accounting Entry":
# Skip validation for periodic accounting entry
if (
not erpnext.is_perpetual_inventory_enabled(self.company)
or self.voucher_type == "Periodic Accounting Entry"
):
# Skip validation for periodic accounting entry and Perpetual Inventory Disabled Company.
return
stock_accounts = get_stock_accounts(self.company, accounts=self.accounts)
@@ -1018,8 +1028,8 @@ class JournalEntry(AccountsController):
if self.flags.skip_remarks_creation:
return
if self.user_remark:
r.append(_("Note: {0}").format(self.user_remark))
if self.get("custom_remark"):
return
if self.cheque_no:
if self.cheque_date:
@@ -1544,35 +1554,42 @@ def get_payment_entry(ref_doc, args):
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_against_jv(doctype: str, txt: str, searchfield: str, start: int, page_len: int, filters: dict):
def get_against_jv(
doctype: str,
txt: str,
searchfield: str,
start: int,
page_len: int,
filters: dict,
):
if not frappe.db.has_column("Journal Entry", searchfield):
return []
return frappe.db.sql(
f"""
SELECT jv.name, jv.posting_date, jv.user_remark
FROM `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
WHERE jv_detail.parent = jv.name
AND jv_detail.account = %(account)s
AND IFNULL(jv_detail.party, '') = %(party)s
AND (
jv_detail.reference_type IS NULL
OR jv_detail.reference_type = ''
)
AND jv.docstatus = 1
AND jv.`{searchfield}` LIKE %(txt)s
ORDER BY jv.name DESC
LIMIT %(limit)s offset %(offset)s
""",
dict(
account=filters.get("account"),
party=cstr(filters.get("party")),
txt=f"%{txt}%",
offset=start,
limit=page_len,
),
JournalEntry = frappe.qb.DocType("Journal Entry")
JournalEntryAccount = frappe.qb.DocType("Journal Entry Account")
query = (
frappe.qb.from_(JournalEntry)
.join(JournalEntryAccount)
.on(JournalEntryAccount.parent == JournalEntry.name)
.select(JournalEntry.name, JournalEntry.posting_date, JournalEntry.remark)
.where(JournalEntryAccount.account == filters.get("account"))
.where(JournalEntryAccount.reference_type.isnull() | (JournalEntryAccount.reference_type == ""))
.where(JournalEntry.docstatus == 1)
.where(JournalEntry[searchfield].like(f"%{txt}%"))
.orderby(JournalEntry.name, order=frappe.qb.desc)
.limit(page_len)
.offset(start)
)
party = filters.get("party")
if party:
query = query.where(JournalEntryAccount.party == party)
else:
query = query.where(JournalEntryAccount.party.isnull() | (JournalEntryAccount.party == ""))
return query.run()
@frappe.whitelist()
def get_outstanding(args: str | dict):

View File

@@ -1,5 +1,5 @@
frappe.listview_settings["Journal Entry"] = {
add_fields: ["voucher_type", "posting_date", "total_debit", "company", "user_remark"],
add_fields: ["voucher_type", "posting_date", "total_debit", "company", "remark"],
get_indicator: function (doc) {
if (doc.docstatus === 1) {
return [__(doc.voucher_type), "blue", `voucher_type,=,${doc.voucher_type}`];

View File

@@ -2,19 +2,20 @@
# License: GNU General Public License v3. See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import flt, nowdate
from erpnext.accounts.doctype.account.test_account import get_inventory_account
from erpnext.accounts.doctype.journal_entry.journal_entry import StockAccountInvalidTransaction
from erpnext.exceptions import InvalidAccountCurrency
from erpnext.selling.doctype.customer.test_customer import make_customer, set_credit_limit
from erpnext.tests.utils import ERPNextTestSuite
class TestJournalEntry(IntegrationTestCase):
@IntegrationTestCase.change_settings(
"Accounts Settings", {"unlink_payment_on_cancellation_of_invoice": 1}
)
class TestJournalEntry(ERPNextTestSuite):
def setUp(self):
self.load_test_records("Journal Entry")
@ERPNextTestSuite.change_settings("Accounts Settings", {"unlink_payment_on_cancellation_of_invoice": 1})
def test_journal_entry_with_against_jv(self):
jv_invoice = frappe.copy_doc(self.globalTestRecords["Journal Entry"][2])
base_jv = frappe.copy_doc(self.globalTestRecords["Journal Entry"][0])
@@ -149,7 +150,6 @@ class TestJournalEntry(IntegrationTestCase):
if account_bal == stock_bal:
self.assertRaises(StockAccountInvalidTransaction, jv.save)
frappe.db.rollback()
else:
jv.submit()
jv.cancel()
@@ -413,9 +413,9 @@ class TestJournalEntry(IntegrationTestCase):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
# Configure Repost Accounting Ledger for JVs
settings = frappe.get_doc("Repost Accounting Ledger Settings")
if not [x for x in settings.allowed_types if x.document_type == "Journal Entry"]:
settings.append("allowed_types", {"document_type": "Journal Entry", "allowed": True})
settings = frappe.get_doc("Accounts Settings")
if "Journal Entry" not in [x.document_type for x in settings.repost_allowed_types]:
settings.append("repost_allowed_types", {"document_type": "Journal Entry"})
settings.save()
# Create JV with defaut cost center - _Test Cost Center
@@ -523,7 +523,7 @@ class TestJournalEntry(IntegrationTestCase):
jv = frappe.new_doc("Journal Entry")
jv.posting_date = nowdate()
jv.company = "_Test Company"
jv.user_remark = "test"
jv.remark = "test"
jv.extend(
"accounts",
[
@@ -592,6 +592,14 @@ class TestJournalEntry(IntegrationTestCase):
self.assertEqual(jv.pay_to_recd_from, "_Test Receiver 2")
def test_custom_remark(self):
# When custom_remark is enabled, remark should not be auto-overwritten on save
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, save=False)
jv.custom_remark = 1
jv.remark = "My custom remark text"
jv.insert()
self.assertEqual(jv.remark, "My custom remark text")
def test_credit_limit_for_customer(self):
customer = make_customer("_Test New Customer")
set_credit_limit("_Test New Customer", "_Test Company", 50)
@@ -620,7 +628,7 @@ def make_journal_entry(
jv = frappe.new_doc("Journal Entry")
jv.posting_date = posting_date or nowdate()
jv.company = company or "_Test Company"
jv.user_remark = "test"
jv.remark = "test"
jv.multi_currency = 1
jv.set(
"accounts",

View File

@@ -2,8 +2,8 @@
# See license.txt
# import frappe
from frappe.tests import IntegrationTestCase
from erpnext.tests.utils import ERPNextTestSuite
class TestJournalEntryTemplate(IntegrationTestCase):
class TestJournalEntryTemplate(ERPNextTestSuite):
pass

View File

@@ -3,23 +3,20 @@
import frappe
from frappe import qb
from frappe.tests import IntegrationTestCase
from frappe.utils import nowdate
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
from erpnext.accounts.utils import run_ledger_health_checks
from erpnext.tests.utils import ERPNextTestSuite
class TestLedgerHealth(AccountsTestMixin, IntegrationTestCase):
class TestLedgerHealth(ERPNextTestSuite, AccountsTestMixin):
def setUp(self):
self.create_company()
self.create_customer()
self.configure_monitoring_tool()
self.clear_old_entries()
def tearDown(self):
frappe.db.rollback()
def configure_monitoring_tool(self):
monitor_settings = frappe.get_doc("Ledger Health Monitor")
monitor_settings.enable_health_monitor = True

View File

@@ -2,8 +2,10 @@
# See license.txt
# import frappe
from frappe.tests import IntegrationTestCase
class TestLedgerHealthMonitor(IntegrationTestCase):
from erpnext.tests.utils import ERPNextTestSuite
class TestLedgerHealthMonitor(ERPNextTestSuite):
pass

View File

@@ -71,14 +71,16 @@ def start_merge(docname):
ledger_merge.account,
)
row.db_set("merged", 1)
frappe.db.commit()
if not frappe.in_test:
frappe.db.commit()
successful_merges += 1
frappe.publish_realtime(
"ledger_merge_progress",
{"ledger_merge": ledger_merge.name, "current": successful_merges, "total": total},
)
except Exception:
frappe.db.rollback()
if not frappe.in_test:
frappe.db.rollback()
ledger_merge.log_error("Ledger merge failed")
finally:
if successful_merges == total:

View File

@@ -2,12 +2,12 @@
# See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from erpnext.accounts.doctype.ledger_merge.ledger_merge import start_merge
from erpnext.tests.utils import ERPNextTestSuite
class TestLedgerMerge(IntegrationTestCase):
class TestLedgerMerge(ERPNextTestSuite):
def test_merge_success(self):
if not frappe.db.exists("Account", "Indirect Expenses - _TC"):
acc = frappe.new_doc("Account")
@@ -100,16 +100,3 @@ class TestLedgerMerge(IntegrationTestCase):
self.assertFalse(frappe.db.exists("Account", "Indirect Test Income - _TC"))
self.assertTrue(frappe.db.exists("Account", "Administrative Test Income - _TC"))
def tearDown(self):
for entry in frappe.db.get_all("Ledger Merge"):
frappe.delete_doc("Ledger Merge", entry.name)
test_accounts = [
"Indirect Test Expenses - _TC",
"Administrative Test Expenses - _TC",
"Indirect Test Income - _TC",
"Administrative Test Income - _TC",
]
for account in test_accounts:
frappe.delete_doc_if_exists("Account", account)

View File

@@ -2,31 +2,20 @@
# See license.txt
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import today
from erpnext.accounts.doctype.loyalty_program.test_loyalty_program import create_records
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.tests.utils import ERPNextTestSuite
class TestLoyaltyPointEntry(IntegrationTestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
class TestLoyaltyPointEntry(ERPNextTestSuite):
def setUp(self):
# Create test records
create_records()
cls.loyalty_program_name = "Test Single Loyalty"
cls.customer_name = "Test Loyalty Customer"
customer = frappe.get_doc("Customer", cls.customer_name)
customer.db_set("loyalty_program", cls.loyalty_program_name)
@classmethod
def tearDownClass(cls):
# Delete all Loyalty Point Entries
frappe.db.sql("DELETE FROM `tabLoyalty Point Entry` WHERE customer = %s", cls.customer_name)
frappe.db.sql("DELETE FROM `tabSales Invoice` WHERE customer = %s", cls.customer_name)
frappe.db.commit()
# cls.customer.delete()
self.loyalty_program_name = "Test Single Loyalty"
self.customer_name = "Test Loyalty Customer"
customer = frappe.get_doc("Customer", self.customer_name)
customer.loyalty_program = self.loyalty_program_name
customer.save()
def create_test_invoice(self, redeem=None):
if redeem:
@@ -68,9 +57,10 @@ class TestLoyaltyPointEntry(IntegrationTestCase):
self.assertEqual(entry.discretionary_reason, "Customer Appreciation")
def test_redeem_loyalty_points(self):
self.create_test_invoice(redeem=10)
self.create_test_invoice()
self.create_test_invoice(redeem=7)
doc = frappe.get_last_doc("Loyalty Point Entry")
self.assertEqual(doc.loyalty_points, -10)
self.assertEqual(doc.loyalty_points, -7)
# Check balance
balance = frappe.db.sql(
@@ -82,4 +72,4 @@ class TestLoyaltyPointEntry(IntegrationTestCase):
(self.customer_name,),
)[0][0]
self.assertEqual(balance, 75) # 85 added, 10 redeemed
self.assertEqual(balance, 3) # 10 added, 7 redeemed

View File

@@ -3,7 +3,6 @@
import unittest
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import cint, flt, getdate, today
from erpnext.accounts.doctype.loyalty_program.loyalty_program import (
@@ -11,15 +10,10 @@ from erpnext.accounts.doctype.loyalty_program.loyalty_program import (
get_loyalty_program_details_with_points,
)
from erpnext.accounts.party import get_dashboard_info
from erpnext.tests.utils import ERPNextTestSuite
class TestLoyaltyProgram(IntegrationTestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
# create relevant item, customer, loyalty program, etc
create_records()
class TestLoyaltyProgram(ERPNextTestSuite):
def test_loyalty_points_earned_single_tier(self):
frappe.db.set_value("Customer", "Test Loyalty Customer", "loyalty_program", "Test Single Loyalty")
# create a new sales invoice
@@ -323,96 +317,3 @@ def create_sales_invoice_record(qty=1):
],
}
)
def create_records():
# create a new loyalty Account
if not frappe.db.exists("Account", "Loyalty - _TC"):
frappe.get_doc(
{
"doctype": "Account",
"account_name": "Loyalty",
"parent_account": "Direct Expenses - _TC",
"company": "_Test Company",
"is_group": 0,
"account_type": "Expense Account",
}
).insert()
# create a new loyalty program Single tier
if not frappe.db.exists("Loyalty Program", "Test Single Loyalty"):
frappe.get_doc(
{
"doctype": "Loyalty Program",
"loyalty_program_name": "Test Single Loyalty",
"auto_opt_in": 1,
"from_date": today(),
"loyalty_program_type": "Single Tier Program",
"conversion_factor": 1,
"expiry_duration": 10,
"company": "_Test Company",
"cost_center": "Main - _TC",
"expense_account": "Loyalty - _TC",
"collection_rules": [{"tier_name": "Bronce", "collection_factor": 1000, "min_spent": 0}],
}
).insert()
# create a new customer
if not frappe.db.exists("Customer", "Test Loyalty Customer"):
frappe.get_doc(
{
"customer_group": "_Test Customer Group",
"customer_name": "Test Loyalty Customer",
"customer_type": "Individual",
"doctype": "Customer",
"territory": "_Test Territory",
}
).insert()
# create a new loyalty program Multiple tier
if not frappe.db.exists("Loyalty Program", "Test Multiple Loyalty"):
frappe.get_doc(
{
"doctype": "Loyalty Program",
"loyalty_program_name": "Test Multiple Loyalty",
"auto_opt_in": 1,
"from_date": today(),
"loyalty_program_type": "Multiple Tier Program",
"conversion_factor": 1,
"expiry_duration": 10,
"company": "_Test Company",
"cost_center": "Main - _TC",
"expense_account": "Loyalty - _TC",
"collection_rules": [
{"tier_name": "Bronze", "collection_factor": 1000, "min_spent": 0},
{"tier_name": "Silver", "collection_factor": 1000, "min_spent": 10000},
{"tier_name": "Gold", "collection_factor": 1000, "min_spent": 19000},
],
}
).insert()
# create an item
if not frappe.db.exists("Item", "Loyal Item"):
frappe.get_doc(
{
"doctype": "Item",
"item_code": "Loyal Item",
"item_name": "Loyal Item",
"item_group": "All Item Groups",
"company": "_Test Company",
"is_stock_item": 1,
"opening_stock": 100,
"valuation_rate": 10000,
}
).insert()
# create item price
if not frappe.db.exists("Item Price", {"price_list": "Standard Selling", "item_code": "Loyal Item"}):
frappe.get_doc(
{
"doctype": "Item Price",
"price_list": "Standard Selling",
"item_code": "Loyal Item",
"price_list_rate": 10000,
}
).insert()

Some files were not shown because too many files have changed in this diff Show More