Compare commits

..

278 Commits

Author SHA1 Message Date
Frappe PR Bot
47d37aa628 chore(release): Bumped to Version 14.51.0
# [14.51.0](https://github.com/frappe/erpnext/compare/v14.50.0...v14.51.0) (2023-11-28)

### Bug Fixes

* Alert message and make sure invoice due dates are different for effective test ([0813f02](0813f02ca5))
* allow on submit for child table fields ([d72fbe9](d72fbe9125))
* annual income and expenses in digest ([7dce68b](7dce68bdcc))
* check reposting settings before allowing editable si ([f777d24](f777d24679))
* condition in other bundle utils ([e96ef73](e96ef7338e))
* create contact if existing customer doesn't have contact ([bb2aa90](bb2aa904b2))
* do not set repost flag without validating voucher ([3ad6d08](3ad6d0890a))
* filter bundle items based on disabled check ([8a3a068](8a3a0688ba))
* fiscal year using future date ([b0aa4ef](b0aa4efd3d))
* has_product_bundle util to only check for enabled bundles ([fd19ac5](fd19ac55e3))
* job card overlap validation (backport [#38345](https://github.com/frappe/erpnext/issues/38345)) ([#38347](https://github.com/frappe/erpnext/issues/38347)) ([9cf8955](9cf8955d24))
* Merge conflicts ([e7183e3](e7183e3ea9))
* Negative Qty and Rates in SO/PO ([#38253](https://github.com/frappe/erpnext/issues/38253)) ([50f3b01](50f3b01eb7))
* Payment Reco Issue and chart of account importer ([730a3bb](730a3bb7ce))
* Re-add no.of rows split in alert message ([fb19e7f](fb19e7f15e))
* **regional:** item wise tax calc issue ([0448d56](0448d56a4f))
* Server Error while creating Product Bundle (backport [#38377](https://github.com/frappe/erpnext/issues/38377)) ([#38379](https://github.com/frappe/erpnext/issues/38379)) ([ca6a788](ca6a78882c))
* skip disabled bundles for non-report utils ([445e9c9](445e9c9041))
* skip fixed assets in parent ([5dcd806](5dcd806176))
* stock availability not showing ([#38382](https://github.com/frappe/erpnext/issues/38382)) ([3929cc3](3929cc30ca))
* validation for existing bundles ([ae960e7](ae960e735a))

### Features

* add disabled field in product bundle ([8d5efc9](8d5efc901d))
* new Report "Lost Quotations" ([#38309](https://github.com/frappe/erpnext/issues/38309)) ([1773e31](1773e31499))
2023-11-28 16:24:55 +00:00
rohitwaghchaure
6260241c55 Merge pull request #38384 from frappe/version-14-hotfix
chore: release v14
2023-11-28 21:53:33 +05:30
Shariq Ansari
6871331ff3 Merge pull request #38399 from frappe/mergify/bp/version-14-hotfix/pr-38398
fix(CRM): create contact if existing customer doesn't have contact (backport #38398)
2023-11-28 20:45:08 +05:30
Shariq Ansari
bb2aa904b2 fix: create contact if existing customer doesn't have contact
(cherry picked from commit 23b0b8ba36)
2023-11-28 14:19:59 +00:00
mergify[bot]
e490bd7785 refactor(Translations): prisoner exchange with HRMS (backport #37376) (#37403)
* refactor: migrate translations to HRMS

* chore: resolve conflicts

* style: remove whitespace

To make the linter happy

---------

Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
2023-11-28 17:50:28 +05:30
mergify[bot]
ca6a78882c fix: Server Error while creating Product Bundle (backport #38377) (#38379)
* fix: product bundle search input

(cherry picked from commit 729fc738af)

* fix: don't select all fields

(cherry picked from commit 8c3713b649)

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2023-11-28 15:26:36 +05:30
Raffael Meyer
321ac4c5f0 style: remove whitespace (#38388)
To make the linter happy
2023-11-28 15:22:35 +05:30
rohitwaghchaure
3929cc30ca fix: stock availability not showing (#38382)
fix: stock availability now showing
2023-11-28 15:16:35 +05:30
mergify[bot]
25f67923ea chore: fix flaky test case (backport #38369) (#38372)
chore: fix flaky test case (#38369)

(cherry picked from commit ad3634be7c)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2023-11-28 08:36:46 +05:30
ruthra kumar
5dc7faba0c Merge pull request #38358 from frappe/mergify/bp/version-14-hotfix/pr-38354
refactor: handle rounding loss on AR/AP reports (backport #38354)
2023-11-27 12:16:27 +05:30
ruthra kumar
2aa9171027 refactor: handle rounding loss on AR/AP reports
(cherry picked from commit 592ce45da7)
2023-11-27 06:22:44 +00:00
mergify[bot]
730a3bb7ce fix: Payment Reco Issue and chart of account importer
fix: Payment Reco Issue and chart of account importer
2023-11-27 10:30:46 +05:30
ruthra kumar
e9a2b002d8 Merge pull request #38355 from frappe/mergify/bp/version-14-hotfix/pr-38081
fix: check reposting ledger settings before setting repost flag (backport #38081)
2023-11-27 09:28:59 +05:30
ruthra kumar
faf025454f chore: resolve conflict 2023-11-27 09:08:23 +05:30
Marica
50f3b01eb7 fix: Negative Qty and Rates in SO/PO (#38253)
* fix: Don't allow negative qty in SO/PO

* fix: Type casting for safe comparisons

* fix: Grammar in error message

* fix: Negative rates should be allowed via Update Items in SO/PO

* fix: Use `non_negative` property in docfield & emove code validation
2023-11-27 09:06:27 +05:30
Gursheen Anand
f777d24679 fix: check reposting settings before allowing editable si
(cherry picked from commit 894ae1fe0f)
2023-11-27 03:35:38 +00:00
Gursheen Anand
d72fbe9125 fix: allow on submit for child table fields
(cherry picked from commit 5fae2f6d57)

# Conflicts:
#	erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
2023-11-27 03:35:37 +00:00
Gursheen Anand
3ad6d0890a fix: do not set repost flag without validating voucher
(cherry picked from commit ad5edbb1de)
2023-11-27 03:35:37 +00:00
Gursheen Anand
776c884403 refactor: validate reposting settings for editables inv
(cherry picked from commit 780b827adc)
2023-11-27 03:35:37 +00:00
mergify[bot]
a4b5fc8100 refactor: bank transaction (#38182)
refactor: bank transaction (#38182)

(cherry picked from commit 5426b93387)

Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2023-11-26 18:58:04 +05:30
Deepesh Garg
b0547b5619 Merge pull request #38074 from frappe/mergify/bp/version-14-hotfix/pr-37859
fix: `split_invoices_based_on_payment_terms` (#37859)
2023-11-26 18:15:11 +05:30
mergify[bot]
9cf8955d24 fix: job card overlap validation (backport #38345) (#38347)
* fix: job card overlap validation (#38345)

(cherry picked from commit d8245cef72)

# Conflicts:
#	erpnext/manufacturing/doctype/job_card/job_card.py

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2023-11-26 17:44:02 +05:30
Deepesh Garg
f7c820ffad Merge pull request #38331 from frappe/mergify/bp/version-14-hotfix/pr-38309
feat: new Report "Lost Quotations" (#38309)
2023-11-25 17:36:27 +05:30
Raffael Meyer
1773e31499 feat: new Report "Lost Quotations" (#38309)
(cherry picked from commit 477d9fa87e)
2023-11-24 21:27:50 +00:00
Deepesh Garg
466d0849e8 Merge pull request #38313 from frappe/mergify/bp/version-14-hotfix/pr-36797
fix(regional): item wise tax calc issue (#36797)
2023-11-24 16:31:03 +05:30
Deepesh Garg
28b6afcb10 Merge pull request #38315 from frappe/mergify/bp/version-14-hotfix/pr-38269
fix: skip fixed assets in product bundle (#38269)
2023-11-24 16:30:05 +05:30
Deepesh Garg
bdde30a456 Merge pull request #38324 from frappe/mergify/bp/version-14-hotfix/pr-38273
fix: annual income and expenses in email digest (#38273)
2023-11-24 16:29:16 +05:30
Gursheen Kaur Anand
aea169d4d4 chore: resolve conflicts 2023-11-24 15:30:19 +05:30
Gursheen Anand
b0aa4efd3d fix: fiscal year using future date
(cherry picked from commit 728cc9f725)
2023-11-24 09:51:29 +00:00
Gursheen Anand
7dce68bdcc fix: annual income and expenses in digest
(cherry picked from commit 52305e3000)

# Conflicts:
#	erpnext/accounts/utils.py
2023-11-24 09:51:29 +00:00
Frappe PR Bot
436ba6f244 chore(release): Bumped to Version 14.50.0
# [14.50.0](https://github.com/frappe/erpnext/compare/v14.49.0...v14.50.0) (2023-11-24)

### Bug Fixes

* don't depreciate non-depreciable assets on scrapping [v14] ([#38294](https://github.com/frappe/erpnext/issues/38294)) ([5261aba](5261aba81f))
* partial cancel of gle and ple (backport [#35609](https://github.com/frappe/erpnext/issues/35609)) ([80bc235](80bc235d6e))
* patch - Duplicate entry quality inspection parameter (backport [#38262](https://github.com/frappe/erpnext/issues/38262)) ([#38263](https://github.com/frappe/erpnext/issues/38263)) ([756f08b](756f08b9ba))
* Supplier `Primary Contact` (backport [#38268](https://github.com/frappe/erpnext/issues/38268)) ([#38285](https://github.com/frappe/erpnext/issues/38285)) ([f170cb9](f170cb9214))

### Features

* add Bank Transaction to connections in Journal and Payment Entry ([#38297](https://github.com/frappe/erpnext/issues/38297)) ([06c6da5](06c6da5c0d))

### Performance Improvements

* optimize total_purchase_cost update ([a88d322](a88d322e4f))
2023-11-24 08:47:31 +00:00
ruthra kumar
79ded4bf19 Merge pull request #38320 from ruthra-kumar/version-14
chore: release v14
2023-11-24 14:16:16 +05:30
ruthra kumar
5af23e760c Merge branch 'version-14-hotfix' into version-14 2023-11-24 13:26:25 +05:30
ruthra kumar
7601861f21 Merge pull request #38318 from frappe/mergify/bp/version-14-hotfix/pr-38298
perf: optimize update_purchase_cost method  (backport #38298)
2023-11-24 12:20:57 +05:30
ruthra kumar
1d1af26f7a chore: resolve conflict 2023-11-24 11:54:55 +05:30
ruthra kumar
47093bebd3 refactor: update project costing based on frequency
(cherry picked from commit dd016e6ced)
2023-11-24 06:20:04 +00:00
ruthra kumar
205d971253 refactor: make update_project_cost optional through Buying Settings
(cherry picked from commit 0fe6dcd742)
2023-11-24 06:20:04 +00:00
ruthra kumar
49a787b1a8 refactor: provide UI button to recalculate when needed
(cherry picked from commit bcbe6c4a53)

# Conflicts:
#	erpnext/projects/doctype/project/project.py
2023-11-24 06:20:04 +00:00
ruthra kumar
a88d322e4f perf: optimize total_purchase_cost update
(cherry picked from commit aa17110bde)
2023-11-24 06:20:02 +00:00
Deepesh Garg
dfdaad0111 Merge pull request #38300 from frappe/mergify/bp/version-14-hotfix/pr-38297
feat: add Bank Transaction to connections in Journal and Payment Entry (#38297)
2023-11-24 10:06:59 +05:30
ruthra kumar
d80e8c6b15 Merge pull request #38311 from frappe/mergify/bp/version-14-hotfix/pr-38296
chore: index to speed up basic submit/cancel functions on purchase invoice (backport #38296)
2023-11-24 10:04:59 +05:30
Gursheen Anand
d7d5317b0e chore: linting issues
(cherry picked from commit 1657337887)
2023-11-24 04:30:38 +00:00
Gursheen Anand
445e9c9041 fix: skip disabled bundles for non-report utils
(cherry picked from commit 362f377f61)
2023-11-24 04:30:38 +00:00
Gursheen Anand
e96ef7338e fix: condition in other bundle utils
(cherry picked from commit 8bdb61cb87)
2023-11-24 04:30:38 +00:00
Gursheen Anand
ae960e735a fix: validation for existing bundles
(cherry picked from commit 67f43d37df)
2023-11-24 04:30:38 +00:00
Gursheen Anand
fd19ac55e3 fix: has_product_bundle util to only check for enabled bundles
(cherry picked from commit 3543f86c63)
2023-11-24 04:30:38 +00:00
Gursheen Anand
8a3a0688ba fix: filter bundle items based on disabled check
(cherry picked from commit 874774fe6c)
2023-11-24 04:30:37 +00:00
Gursheen Anand
8d5efc901d feat: add disabled field in product bundle
(cherry picked from commit ee76af7681)
2023-11-24 04:30:37 +00:00
Gursheen Anand
5dcd806176 fix: skip fixed assets in parent
(cherry picked from commit f9713eeb56)
2023-11-24 04:30:36 +00:00
Dany Robert
0448d56a4f fix(regional): item wise tax calc issue
(cherry picked from commit 89ddf3272e)
2023-11-24 04:28:23 +00:00
ruthra kumar
f74132b0be chore: speed up Purchase Invoice cancellation
(cherry picked from commit 1efff268b0)
2023-11-24 04:16:22 +00:00
ruthra kumar
6353deacf0 chore: index to speed up queries on JE child table reference
(cherry picked from commit 24fcd67f8b)
2023-11-24 04:16:21 +00:00
mergify[bot]
756f08b9ba fix: patch - Duplicate entry quality inspection parameter (backport #38262) (#38263)
fix: patch - Duplicate entry quality inspection parameter (#38262)

(cherry picked from commit 0ca7527f7a)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2023-11-23 22:39:14 +05:30
Raffael Meyer
2293696ab4 chore: resolve conflicts 2023-11-23 15:10:29 +01:00
Raffael Meyer
06c6da5c0d feat: add Bank Transaction to connections in Journal and Payment Entry (#38297)
* feat(Payment Entry): Bank Transaction connection

* feat(Journal Entry): Bank Transaction connection

(cherry picked from commit 3be345e605)

# Conflicts:
#	erpnext/accounts/doctype/payment_entry/payment_entry.json
2023-11-23 13:03:38 +00:00
Anand Baburajan
5261aba81f fix: don't depreciate non-depreciable assets on scrapping [v14] (#38294)
fix: don't depreciate non-depreciable assets on scrapping
2023-11-23 14:15:40 +05:30
mergify[bot]
f170cb9214 fix: Supplier Primary Contact (backport #38268) (#38285)
fix: Supplier `Primary Contact`

(cherry picked from commit 627165dc7c)

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2023-11-23 11:45:57 +05:30
ruthra kumar
8055773425 Merge pull request #38281 from frappe/mergify/bp/version-14-hotfix/pr-38258
refactor: rename 'Unreconcile Payments' doctype to singular 'Unreconcile Payment' (backport #38258)
2023-11-23 11:09:11 +05:30
ruthra kumar
82fa58d4e3 chore: update new unreconcile doctype name in JS and PY files
(cherry picked from commit 74f9e34182)
2023-11-23 05:09:23 +00:00
ruthra kumar
57c6d616e6 chore: rename 'unreconcile payments' to 'unreconcile payment'
(cherry picked from commit 9006c9b747)
2023-11-23 05:09:23 +00:00
ruthra kumar
639512a7c2 Merge pull request #38279 from frappe/mergify/bp/version-14-hotfix/pr-38257
refactor: optmize outstanding amount query (backport #38257)
2023-11-23 10:16:11 +05:30
ruthra kumar
ac13e7362c refactor: optimize outstanding vouchers query
(cherry picked from commit 8b04c1d4f6)
2023-11-23 04:12:42 +00:00
Marica
1e7dfd3071 Merge branch 'version-14-hotfix' into mergify/bp/version-14-hotfix/pr-37859 2023-11-22 20:51:30 +05:30
marination
e7183e3ea9 fix: Merge conflicts 2023-11-22 16:16:37 +01:00
ruthra kumar
c4e57040b7 Merge pull request #38205 from vorasmit/partial-cancel
fix: partial cancel of gle and ple (backport #35609)
2023-11-22 10:27:05 +05:30
Smit Vora
c1a7d614a2 test: partial cancel for gl entries reversal 2023-11-22 10:07:38 +05:30
Frappe PR Bot
7392f9c662 chore(release): Bumped to Version 14.49.0
# [14.49.0](https://github.com/frappe/erpnext/compare/v14.48.1...v14.49.0) (2023-11-22)

### Bug Fixes

* add revaluation journal filter in Payable report ([d0698b3](d0698b32bb))
* attributes were mandatory for manufacturers ([430980a](430980a836))
* duplicate field in `Closing Stock Balance` ([#38105](https://github.com/frappe/erpnext/issues/38105)) ([1f16c47](1f16c47a2c))
* incorrect incoming rate for serial and batch items in standalone debit note ([#38121](https://github.com/frappe/erpnext/issues/38121)) ([9a34518](9a34518e54))
* pass check permission in render_address ([1ccd5e4](1ccd5e4ff5))
* payment entry rounding error ([49735bc](49735bc120))
* remove ESS role when not mapped to employee (backport [#37867](https://github.com/frappe/erpnext/issues/37867)) ([#38132](https://github.com/frappe/erpnext/issues/38132)) ([bc01007](bc01007c16))
* round `unreconciled_amount` before asserting ([392ee2e](392ee2e0fd))
* set asset's valuation_rate according to asset quantity (backport [#38254](https://github.com/frappe/erpnext/issues/38254)) ([#38255](https://github.com/frappe/erpnext/issues/38255)) ([00def82](00def82843))
* set default asset quantity as 1 [v14] ([#38224](https://github.com/frappe/erpnext/issues/38224)) ([3daf6f8](3daf6f822a))
* show party values when naming by is not naming series ([dd76695](dd76695d3a))
* Supplier Quotation fields ([#37963](https://github.com/frappe/erpnext/issues/37963)) ([883eaee](883eaee014))
* test case for rounded total with cash disc ([9b5185a](9b5185adc9))
* **Timesheet:** reset billing hours equal to hours if they exceed actual hours (backport [#38134](https://github.com/frappe/erpnext/issues/38134)) ([#38152](https://github.com/frappe/erpnext/issues/38152)) ([c7c751e](c7c751ecd0))
* **Timesheet:** warn user if billing hours > actual hours instead of resetting  (backport [#38239](https://github.com/frappe/erpnext/issues/38239)) ([#38240](https://github.com/frappe/erpnext/issues/38240)) ([e08f114](e08f1145c9))
* update modified timestamp ([2849e0d](2849e0daed))
* valuation rate in report Item Prices ([#38161](https://github.com/frappe/erpnext/issues/38161)) ([a70696e](a70696ea77))
* wrong round off and rounded total ([296433a](296433a1dd))

### Features

* add `Supplier Delivery Note` field in SCR (backport [#38127](https://github.com/frappe/erpnext/issues/38127)) ([#38155](https://github.com/frappe/erpnext/issues/38155)) ([8d4a19c](8d4a19cecf))
* Add accounting dimensions to Supplier Quotation ([51e33e1](51e33e1556))
* virtual parent doctype ([8dbf2ce](8dbf2ced79))
2023-11-22 04:16:31 +00:00
Deepesh Garg
aa6ef76043 Merge pull request #38247 from frappe/version-14-hotfix
chore: release v14
2023-11-22 09:43:45 +05:30
Deepesh Garg
f6f5ff0be9 Merge branch 'version-14' into version-14-hotfix 2023-11-22 00:28:38 +05:30
mergify[bot]
00def82843 fix: set asset's valuation_rate according to asset quantity (backport #38254) (#38255)
fix: set asset's valuation_rate according to asset quantity (#38254)

(cherry picked from commit e2bb4e2baa)

Co-authored-by: Anand Baburajan <anandbaburajan@gmail.com>
2023-11-21 22:53:31 +05:30
mergify[bot]
e08f1145c9 fix(Timesheet): warn user if billing hours > actual hours instead of resetting (backport #38239) (#38240)
fix(Timesheet): warn user if billing hours > actual hours instead of resetting  (#38239)

* revert: "fix(Timesheet): reset billing hours equal to hours if they exceed actual hours"

This reverts commit 0ec8034507.

* fix: warn user if billing hours > actual hours

(cherry picked from commit ac91030b31)

Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2023-11-21 13:41:08 +05:30
ruthra kumar
ddf82cf433 Merge pull request #38235 from frappe/mergify/bp/version-14-hotfix/pr-38234
test: prevent rounding loss based validation error (backport #38234)
2023-11-21 12:30:34 +05:30
ruthra kumar
59a5e132fe test: prevent rounding loss based validation error
(cherry picked from commit 56e991b7f4)
2023-11-21 06:41:36 +00:00
ruthra kumar
7fc7105c48 Merge pull request #38217 from rtdany10/payment-reco-rounding-issue
fix: round `unreconciled_amount` before asserting
2023-11-21 11:33:42 +05:30
Anand Baburajan
3daf6f822a fix: set default asset quantity as 1 [v14] (#38224)
fix: set default asset quantity as 1
2023-11-20 22:27:25 +05:30
ruthra kumar
d7278477d6 Merge pull request #38213 from frappe/mergify/bp/version-14-hotfix/pr-38210
refactor: extend billed amount update flag to POS Invoice as well (backport #38210)
2023-11-20 15:02:44 +05:30
ruthra kumar
d0571530eb Merge pull request #38215 from frappe/mergify/bp/version-14-hotfix/pr-38212
refactor: update scheduled job for bulk transaction (backport #38212)
2023-11-20 14:49:10 +05:30
Dany Robert
392ee2e0fd fix: round unreconciled_amount before asserting 2023-11-20 14:36:58 +05:30
ruthra kumar
562a55122b refactor: update scheduled job for bulk transaction
(cherry picked from commit fb06ad7330)
2023-11-20 08:51:08 +00:00
ruthra kumar
b226adeb2f Merge pull request #38150 from frappe/mergify/bp/version-14-hotfix/pr-38038
refactor: supercharge Bulk actions (backport #38038)
2023-11-20 14:16:27 +05:30
ruthra kumar
12f027b3f4 chore: resolve conflict 2023-11-20 14:15:33 +05:30
ruthra kumar
9f8aa7c59d refactor: add flag to POS Invoice
(cherry picked from commit 83a13e22b7)

# Conflicts:
#	erpnext/accounts/doctype/pos_invoice/pos_invoice.json
2023-11-20 08:36:52 +00:00
ruthra kumar
40f904391e refactor: set default for 'update_billed_amount_in_delivery_note'
(cherry picked from commit ee0c64215d)
2023-11-20 08:36:51 +00:00
ruthra kumar
bfb85527dc Merge pull request #38196 from frappe/mergify/bp/version-14-hotfix/pr-38159
refactor: provision to truncate `remarks` in General Ledger and Accounts Receivable/Payable reports (backport #38159)
2023-11-20 13:30:39 +05:30
ruthra kumar
b868e2bd5b chore: resolve conflicts 2023-11-20 12:33:51 +05:30
Sagar Vora
b7e74b479f Merge pull request #38198 from frappe/mergify/bp/version-14-hotfix/pr-37963
fix: Supplier Quotation fields (backport #37963)
2023-11-20 11:46:25 +05:30
Sagar Vora
7c92ecdc9d chore: resolve conflicts 2023-11-20 11:39:15 +05:30
Smit Vora
80bc235d6e fix: partial cancel of gle and ple (backport #35609) 2023-11-20 10:56:56 +05:30
Vishakh Desai
883eaee014 fix: Supplier Quotation fields (#37963)
(cherry picked from commit c2bda2c705)

# Conflicts:
#	erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
2023-11-20 04:42:39 +00:00
ruthra kumar
ae319760a0 refactor: add substring logic in ar/ap report
(cherry picked from commit a9bf906545)
2023-11-20 04:38:04 +00:00
ruthra kumar
4e2d0aa892 refactor: provision to set remarks length in accounts settings
(cherry picked from commit 97090ff367)

# Conflicts:
#	erpnext/accounts/doctype/accounts_settings/accounts_settings.json
2023-11-20 04:38:04 +00:00
Deepesh Garg
5afb8b59c9 Merge pull request #38190 from frappe/mergify/bp/version-14-hotfix/pr-38171
fix: wrong round off and rounded total (#38171)
2023-11-19 19:44:04 +05:30
Deepesh Garg
8136657dfc Merge pull request #38146 from GursheenK/show-party-values-when-naming-series-unset
fix(minor): show party values when naming by is not naming series
2023-11-19 19:23:57 +05:30
Dany Robert
9b5185adc9 fix: test case for rounded total with cash disc
(cherry picked from commit cc60c328fe)
2023-11-19 13:49:06 +00:00
Dany Robert
296433a1dd fix: wrong round off and rounded total
(cherry picked from commit 3a487bd33a)
2023-11-19 13:49:05 +00:00
Deepesh Garg
5033f189f9 Merge pull request #38172 from frappe/mergify/bp/version-14-hotfix/pr-38142
feat: Add accounting dimensions to Supplier Quotation (#38142)
2023-11-19 19:10:39 +05:30
Deepesh Garg
d85185db2e Merge pull request #38175 from frappe/mergify/bp/version-14-hotfix/pr-38163
fix: attributes were mandatory for manufacturers (#38163)
2023-11-19 19:08:46 +05:30
Deepesh Garg
76b6e0407d Merge pull request #38179 from frappe/mergify/bp/version-14-hotfix/pr-38161
fix: valuation rate in report Item Prices (#38161)
2023-11-19 18:47:40 +05:30
Deepesh Garg
2fdc575441 Merge pull request #38181 from pps190/fix-pe-precision-bp
fix: payment entry rounding error (#38177)
2023-11-19 18:47:01 +05:30
Deepesh Garg
7b9afa43ff chore: resolve conflicts 2023-11-19 18:34:47 +05:30
Devin Slauenwhite
49735bc120 fix: payment entry rounding error 2023-11-18 15:09:44 +00:00
Patrick Eissler
a70696ea77 fix: valuation rate in report Item Prices (#38161)
Co-authored-by: PatrickDenis-stack <77415730+PatrickDenis-stack@users.noreply.github.com>
(cherry picked from commit 32f622ef80)
2023-11-18 14:55:12 +00:00
barredterra
2849e0daed fix: update modified timestamp
Was missing in 434c2a1815
2023-11-18 15:44:36 +01:00
Deepesh Garg
da27c0fb2d chore: resolve conflicts 2023-11-18 20:10:28 +05:30
PatrickDenis-stack
430980a836 fix: attributes were mandatory for manufacturers
(cherry picked from commit 434c2a1815)
2023-11-18 14:38:57 +00:00
Deepesh Garg
51e33e1556 feat: Add accounting dimensions to Supplier Quotation
(cherry picked from commit 089da459f7)

# Conflicts:
#	erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
#	erpnext/patches.txt
2023-11-18 14:11:16 +00:00
mergify[bot]
8d4a19cecf feat: add Supplier Delivery Note field in SCR (backport #38127) (#38155)
* feat: add `Supplier Delivery Note` field in SCR

(cherry picked from commit da80e4dbce)

# Conflicts:
#	erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.json

* chore: `conflicts`

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2023-11-18 18:53:55 +05:30
s-aga-r
9a34518e54 fix: incorrect incoming rate for serial and batch items in standalone debit note (#38121) 2023-11-18 18:48:25 +05:30
Sagar Vora
39841f9edd Merge pull request #38168 from frappe/mergify/bp/version-14-hotfix/pr-38167
fix: pass check permission in `render_address` (backport #38167)
2023-11-18 17:39:38 +05:30
Vishakh Desai
1ccd5e4ff5 fix: pass check permission in render_address
(cherry picked from commit 45299fe4b3)
2023-11-18 12:08:24 +00:00
Gursheen Kaur Anand
05d514ca8e Merge branch 'version-14-hotfix' into show-party-values-when-naming-series-unset 2023-11-17 20:36:11 +05:30
mergify[bot]
c7c751ecd0 fix(Timesheet): reset billing hours equal to hours if they exceed actual hours (backport #38134) (#38152)
fix(Timesheet): reset billing hours equal to hours if they exceed actual hours (#38134)

(cherry picked from commit 20c6e9fca2)

Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2023-11-17 18:28:10 +05:30
ruthra kumar
fa1f623801 refactor: raise exception on invalid date
(cherry picked from commit a393a6b76c)
2023-11-17 10:56:24 +00:00
ruthra kumar
8dbe753a25 refactor: update traceback on retry
(cherry picked from commit a52a1b49af)
2023-11-17 10:56:24 +00:00
ruthra kumar
a060000b70 refactor: support list view filters
(cherry picked from commit 93295bf25b)
2023-11-17 10:56:24 +00:00
ruthra kumar
b615cfc540 chore: resolve linting issue
(cherry picked from commit 73639db910)
2023-11-17 10:56:24 +00:00
ruthra kumar
32b6eed691 refactor: rollback for retries and UI alerts
(cherry picked from commit c320288690)
2023-11-17 10:56:23 +00:00
ruthra kumar
ad03008a1a refactor: barebones retry functionality
(cherry picked from commit 0aa1636d04)
2023-11-17 10:56:23 +00:00
ruthra kumar
2ec1a2f862 chore: show retried in list view
(cherry picked from commit 194d70f8a0)
2023-11-17 10:56:23 +00:00
ruthra kumar
f5f48f7480 refactor: add basic functionalities
(cherry picked from commit af35590549)
2023-11-17 10:56:23 +00:00
ruthra kumar
8dbf2ced79 feat: virtual parent doctype
(cherry picked from commit a248b13cc3)
2023-11-17 10:56:22 +00:00
ruthra kumar
b951dbfced chore: make from_doctype readonly
(cherry picked from commit b0dfc936a1)
2023-11-17 10:56:22 +00:00
ruthra kumar
863a200989 chore: add indexes
(cherry picked from commit 73090fa130)
2023-11-17 10:56:22 +00:00
ruthra kumar
8dafe103bd chore: add list view filters
(cherry picked from commit ade09bc709)
2023-11-17 10:56:22 +00:00
ruthra kumar
eda9800c93 refactor: simplify logging logic bulk_transaction
(cherry picked from commit ebd74a4e5b)
2023-11-17 10:56:22 +00:00
ruthra kumar
6d983b5f45 chore: rearrange fields
(cherry picked from commit c4f8f3613f)
2023-11-17 10:56:21 +00:00
ruthra kumar
65614497ed chore: convert child to normal table
(cherry picked from commit e5a8ad54e2)
2023-11-17 10:56:21 +00:00
ruthra kumar
785bec98d3 chore: remove 'Bulk Transaction Log' doctype
(cherry picked from commit 815c616f18)
2023-11-17 10:56:21 +00:00
Gursheen Kaur Anand
6b08aa2198 Merge branch 'version-14-hotfix' into show-party-values-when-naming-series-unset 2023-11-17 14:21:52 +05:30
Gursheen Anand
dd76695d3a fix: show party values when naming by is not naming series 2023-11-17 12:50:08 +05:30
Frappe PR Bot
236a064cd3 chore(release): Bumped to Version 14.48.1
## [14.48.1](https://github.com/frappe/erpnext/compare/v14.48.0...v14.48.1) (2023-11-17)

### Bug Fixes

* add revaluation journal filter in Payable report ([4eb37cc](4eb37cce26))
2023-11-17 04:38:02 +00:00
ruthra kumar
dd685e50df Merge pull request #38140 from frappe/mergify/bp/version-14/pr-38119
fix: add revaluation journal filter in Payable report (backport #38119)
2023-11-17 10:06:30 +05:30
ruthra kumar
85853295c4 Merge pull request #38138 from frappe/mergify/bp/version-14-hotfix/pr-38119
fix: add revaluation journal filter in Payable report (backport #38119)
2023-11-17 10:04:51 +05:30
ruthra kumar
4eb37cce26 fix: add revaluation journal filter in Payable report
(cherry picked from commit 134201794a)
2023-11-17 10:03:24 +05:30
ruthra kumar
d0698b32bb fix: add revaluation journal filter in Payable report
(cherry picked from commit 134201794a)
2023-11-17 10:02:13 +05:30
mergify[bot]
bc01007c16 fix: remove ESS role when not mapped to employee (backport #37867) (#38132)
fix: remove ESS role when not mapped to employee (#37867)

* fix: remove ESS role when not mapped to employee

* fix: emp role removal on unlinking

* fix: test case for user employee role mapping

* fix: mapped employee and user on creation

(cherry picked from commit 56b8d1b927)

Co-authored-by: Dany Robert <danyrt@wahni.com>
2023-11-16 20:27:53 +05:30
Anand Baburajan
fb2ca3e172 Merge pull request #38114 from frappe/mergify/bp/version-14/pr-38112
chore: change read only condition of asset quantity field (backport #38111) (backport #38112)
2023-11-15 18:03:01 +05:30
mergify[bot]
7d66cb2195 chore: change read only condition of asset quantity field (backport #38111) (#38112)
chore: change read only condition of asset quantity field (#38111)

chore: change read only condition of asset quantity
(cherry picked from commit 6e0362dee8)

Co-authored-by: Anand Baburajan <anandbaburajan@gmail.com>
(cherry picked from commit 58cb4303ee)
2023-11-15 12:32:19 +00:00
mergify[bot]
58cb4303ee chore: change read only condition of asset quantity field (backport #38111) (#38112)
chore: change read only condition of asset quantity field (#38111)

chore: change read only condition of asset quantity
(cherry picked from commit 6e0362dee8)

Co-authored-by: Anand Baburajan <anandbaburajan@gmail.com>
2023-11-15 18:01:28 +05:30
Deepesh Garg
56c70d300b Merge pull request #38106 from frappe/mergify/bp/version-14-hotfix/pr-38105
fix: duplicate field (#38105)
2023-11-15 13:29:35 +05:30
Arjun
1f16c47a2c fix: duplicate field in Closing Stock Balance (#38105)
(cherry picked from commit 908b21f7fd)
2023-11-15 07:06:34 +00:00
Anand Baburajan
7b14e9d5f6 Merge pull request #38100 from frappe/mergify/bp/version-14/pr-38098
chore: refetch item images on transaction save (backport #38095) (backport #38098)
2023-11-14 20:15:28 +05:30
mergify[bot]
966adfc081 chore: refetch item images on transaction save (backport #38095) (#38098)
* chore: refetch item images on transaction save (#38095)

chore: re fetch item images on transaction save
(cherry picked from commit e93a19ffb5)

# Conflicts:
#	erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json
#	erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
#	erpnext/selling/doctype/quotation_item/quotation_item.json

* chore: fix conflict in pos_invoice_item.json

* chore: fix conflict in sales_invoice_item.json

* chore: fix conflict in quotation_item.json

---------

Co-authored-by: Anand Baburajan <anandbaburajan@gmail.com>
(cherry picked from commit d1a8202624)
2023-11-14 14:43:12 +00:00
mergify[bot]
d1a8202624 chore: refetch item images on transaction save (backport #38095) (#38098)
* chore: refetch item images on transaction save (#38095)

chore: re fetch item images on transaction save
(cherry picked from commit e93a19ffb5)

# Conflicts:
#	erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json
#	erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
#	erpnext/selling/doctype/quotation_item/quotation_item.json

* chore: fix conflict in pos_invoice_item.json

* chore: fix conflict in sales_invoice_item.json

* chore: fix conflict in quotation_item.json

---------

Co-authored-by: Anand Baburajan <anandbaburajan@gmail.com>
2023-11-14 20:11:23 +05:30
Frappe PR Bot
7a2df24129 chore(release): Bumped to Version 14.48.0
# [14.48.0](https://github.com/frappe/erpnext/compare/v14.47.4...v14.48.0) (2023-11-14)

### Bug Fixes

* asset depreciation ledger (backport [#37991](https://github.com/frappe/erpnext/issues/37991)) ([#37992](https://github.com/frappe/erpnext/issues/37992)) ([043dc1b](043dc1b14b))
* close `Credit Limit Crossed` dialog (backport [#38052](https://github.com/frappe/erpnext/issues/38052)) ([#38058](https://github.com/frappe/erpnext/issues/38058)) ([6979c3e](6979c3e490))
* COA Importer app related issues ([#37238](https://github.com/frappe/erpnext/issues/37238)) ([57ce73d](57ce73d540))
* german translations of Accounts Settings ([b75aae9](b75aae99ca))
* indentation issue in the Production Plan Summary report (backport [#38019](https://github.com/frappe/erpnext/issues/38019)) ([#38068](https://github.com/frappe/erpnext/issues/38068)) ([c552884](c5528844fd))
* make adjustment entry using stock reconciliation (backport [#37995](https://github.com/frappe/erpnext/issues/37995)) ([#38008](https://github.com/frappe/erpnext/issues/38008)) ([984703c](984703c3c9))
* make item field read-only in batch (backport [#38010](https://github.com/frappe/erpnext/issues/38010)) ([#38033](https://github.com/frappe/erpnext/issues/38033)) ([424ebd1](424ebd154a))
* minor change added to test_case ([6b34568](6b34568128))
* minor issue ([0eab723](0eab723243))
* new logic for handling revaluation journals ([9c0d80c](9c0d80cef4))
* pick serial nos from selected batch only ([#37988](https://github.com/frappe/erpnext/issues/37988)) ([db29180](db29180eec))
* sales order not assigned to territory orders ([#37905](https://github.com/frappe/erpnext/issues/37905)) ([#38024](https://github.com/frappe/erpnext/issues/38024)) ([620f4f2](620f4f2c10))
* Set right party name in bank transaction ([21b430a](21b430a575))
* **translations:** suggestions from review ([4d2169e](4d2169e48e))
* Use `process.extract` to get the corresponding party doc name of the result ([b0a184e](b0a184e937))

### Features

* **accounts_receivable:** test_case added for multi-select customer group ([cf0d936](cf0d936195))
* multi-select customer group in AR Report ([935286f](935286ff94))
2023-11-14 12:57:28 +00:00
Deepesh Garg
ecb116aa99 Merge pull request #38086 from frappe/version-14-hotfix
chore: release v14
2023-11-14 18:25:20 +05:30
mergify[bot]
8446e87cc2 chore: delete comments and unlink attachments on company transactions deletion (backport #38077) (#38078)
* chore: delete comments and unlink attachments on company transactions deletion

(cherry picked from commit 2f9e96e324)

* fix: unrelated transation date typo

(cherry picked from commit b097bb20d9)

---------

Co-authored-by: anandbaburajan <anandbaburajan@gmail.com>
2023-11-13 19:20:52 +05:30
marination
fb19e7f15e fix: Re-add no.of rows split in alert message
(cherry picked from commit 1fc5844025)
2023-11-13 10:46:39 +00:00
marination
c840f30a20 style: Remove spaces introduced via merge conflict
(cherry picked from commit 4b4b176fcf)

# Conflicts:
#	erpnext/accounts/doctype/payment_entry/test_payment_entry.py
2023-11-13 10:46:39 +00:00
marination
0813f02ca5 fix: Alert message and make sure invoice due dates are different for effective test
- Make invoice due dates are different so that the invoice with the earliest due date is allocated first in the test
- Translate voucher type, simplify alert message. The invoice could be "split" into 1 row, no. of rows in the message seems unnecessary.

(cherry picked from commit 56ac3424d2)
2023-11-13 10:46:38 +00:00
marination
a7e2867526 test: get_outstanding_reference_documents (triggered via UI)
(cherry picked from commit 162c0497d1)
2023-11-13 10:46:38 +00:00
marination
077f3928cf refactor: split_invoices_based_on_payment_terms
- Invoices were in the wrong order due to the logic. The invoices with payment terms were added first and the rest after.
- Overly long function with unnecessary loops (reduced to one main loop) and complexity
- The split row as per payment terms was not ordered. So the second installment was allocated first

(cherry picked from commit 6bd56d2d5f)

# Conflicts:
#	erpnext/accounts/doctype/payment_entry/payment_entry.py
2023-11-13 10:46:38 +00:00
mergify[bot]
c5528844fd fix: indentation issue in the Production Plan Summary report (backport #38019) (#38068)
fix: indentation issue in the Production Plan Summary report (#38019)

fix: Production Plan Summary report
(cherry picked from commit 4a111f7362)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2023-11-13 14:03:45 +05:30
ruthra kumar
55885e84ab Merge pull request #38066 from frappe/mergify/bp/version-14/pr-38064
refactor: add revaluation journal checkbox in AR/AP summary reports (backport #38064)
2023-11-13 12:15:34 +05:30
ruthra kumar
2faf2ce468 Merge pull request #38065 from frappe/mergify/bp/version-14-hotfix/pr-38064
refactor: add revaluation journal checkbox in AR/AP summary reports (backport #38064)
2023-11-13 12:15:27 +05:30
ruthra kumar
7ab18fc434 refactor: add revaluation journal checkbox in AR/AP summary reports
(cherry picked from commit 95edd82638)
2023-11-13 06:39:03 +00:00
ruthra kumar
a104a4bca6 refactor: add revaluation journal checkbox in AR/AP summary reports
(cherry picked from commit 95edd82638)
2023-11-13 06:38:38 +00:00
mergify[bot]
6979c3e490 fix: close Credit Limit Crossed dialog (backport #38052) (#38058)
fix: close `Credit Limit Crossed` dialog (#38052)

(cherry picked from commit 94faa44697)

Co-authored-by: Arjun <arjun99c@gmail.com>
2023-11-12 18:07:31 +05:30
mergify[bot]
57ce73d540 fix: COA Importer app related issues (#37238)
fix: COA Importer app related issues (#37238)

* fix: COA Importer app related issues

* fix: Clear all account links fields befor import

* fix: Attribute error

(cherry picked from commit 8634abc021)

Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
2023-11-12 17:40:56 +05:30
mergify[bot]
424ebd154a fix: make item field read-only in batch (backport #38010) (#38033)
* fix: make item field read-only in batch

(cherry picked from commit 779260fb49)

# Conflicts:
#	erpnext/stock/doctype/batch/batch.json

* chore: `conflicts`

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2023-11-11 10:51:36 +05:30
Frappe PR Bot
7c7dc5328e chore(release): Bumped to Version 14.47.4
## [14.47.4](https://github.com/frappe/erpnext/compare/v14.47.3...v14.47.4) (2023-11-10)

### Bug Fixes

* new logic for handling revaluation journals ([010ccf8](010ccf80f5))
2023-11-10 07:46:10 +00:00
ruthra kumar
cb655226de Merge pull request #38037 from frappe/mergify/bp/version-14/pr-38004
fix: handling of exchange rate journals in AR/AP (backport #38004)
2023-11-10 13:14:45 +05:30
ruthra kumar
010ccf80f5 fix: new logic for handling revaluation journals
(cherry picked from commit 1d8fcd66e6)
2023-11-10 12:05:46 +05:30
ruthra kumar
13ea910fa6 Merge pull request #38035 from frappe/mergify/bp/version-14-hotfix/pr-38004
fix: handling of exchange rate journals in AR/AP (backport #38004)
2023-11-10 11:59:03 +05:30
ruthra kumar
9c0d80cef4 fix: new logic for handling revaluation journals
(cherry picked from commit 1d8fcd66e6)
2023-11-10 11:17:46 +05:30
mergify[bot]
620f4f2c10 fix: sales order not assigned to territory orders (#37905) (#38024)
fix: sales order not assigned to territory orders (#37905)

filtered sales order are not assigned to 'territory_orders' which results in 0 order amount and 0 billing amount in the output

(cherry picked from commit 45b4bfc947)

Co-authored-by: jabir-elat <44110258+jabir-elat@users.noreply.github.com>
2023-11-09 21:52:43 +05:30
ruthra kumar
89695022c7 Merge pull request #38021 from frappe/mergify/bp/version-14/pr-37860
refactor: ignore disabled account while selecting Income Accounts (backport #37860)
2023-11-09 17:28:14 +05:30
Frappe PR Bot
50627733b4 chore(release): Bumped to Version 14.47.3
## [14.47.3](https://github.com/frappe/erpnext/compare/v14.47.2...v14.47.3) (2023-11-09)

### Bug Fixes

* make adjustment entry using stock reconciliation (backport [#37995](https://github.com/frappe/erpnext/issues/37995)) (backport [#38008](https://github.com/frappe/erpnext/issues/38008)) ([#38018](https://github.com/frappe/erpnext/issues/38018)) ([7942ad4](7942ad488e))
2023-11-09 11:24:29 +00:00
mergify[bot]
7942ad488e fix: make adjustment entry using stock reconciliation (backport #37995) (backport #38008) (#38018)
fix: make adjustment entry using stock reconciliation (backport #37995) (#38008)

* fix: make adjustment entry using stock reconciliation (#37995)

fix: do adjustment entry using stock reconciliation
(cherry picked from commit a8216b9727)

# Conflicts:
#	erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
#	erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py

* chore: fix conflicts

* fix: conflicts

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 984703c3c9)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2023-11-09 16:53:14 +05:30
ruthra kumar
c3d7348c73 refactor: ignore disabled account while selecting Income Accounts
(cherry picked from commit 6e3e094c95)
2023-11-09 11:14:38 +00:00
Deepesh Garg
ad178db28f Merge pull request #38012 from frappe/mergify/bp/version-14-hotfix/pr-37716
feat: multi-select customer group in AR Report (backport #37716)
2023-11-09 14:05:59 +05:30
mergify[bot]
984703c3c9 fix: make adjustment entry using stock reconciliation (backport #37995) (#38008)
* fix: make adjustment entry using stock reconciliation (#37995)

fix: do adjustment entry using stock reconciliation
(cherry picked from commit a8216b9727)

# Conflicts:
#	erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
#	erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py

* chore: fix conflicts

* fix: conflicts

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2023-11-09 13:40:14 +05:30
vishal
6b34568128 fix: minor change added to test_case
(cherry picked from commit 30402033bc)
2023-11-09 07:35:16 +00:00
vishal
cf0d936195 feat(accounts_receivable): test_case added for multi-select customer group
(cherry picked from commit de445b32f5)
2023-11-09 07:35:16 +00:00
vishal
0eab723243 fix: minor issue
(cherry picked from commit b60c57a97d)
2023-11-09 07:35:15 +00:00
vishal
935286ff94 feat: multi-select customer group in AR Report
(cherry picked from commit 8903c1bc6f)
2023-11-09 07:35:15 +00:00
Frappe PR Bot
9a2674ea29 chore(release): Bumped to Version 14.47.2
## [14.47.2](https://github.com/frappe/erpnext/compare/v14.47.1...v14.47.2) (2023-11-09)

### Bug Fixes

* pick serial nos from selected batch only (backport [#37988](https://github.com/frappe/erpnext/issues/37988)) ([#38011](https://github.com/frappe/erpnext/issues/38011)) ([0405aae](0405aae4a0))
2023-11-09 07:28:50 +00:00
mergify[bot]
0405aae4a0 fix: pick serial nos from selected batch only (backport #37988) (#38011)
fix: pick serial nos from selected batch only (#37988)

* fix: pick current serial nos from selected batch only

* test: add test case for current qty and current serial nos

(cherry picked from commit db29180eec)

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2023-11-09 12:57:03 +05:30
s-aga-r
db29180eec fix: pick serial nos from selected batch only (#37988)
* fix: pick current serial nos from selected batch only

* test: add test case for current qty and current serial nos
2023-11-09 12:30:22 +05:30
ruthra kumar
b5bed65d9e Merge pull request #38001 from frappe/mergify/bp/version-14-hotfix/pr-37860
refactor: ignore disabled account while selecting Income Accounts (backport #37860)
2023-11-09 10:41:13 +05:30
ruthra kumar
3f7f5bd8f0 refactor: ignore disabled account while selecting Income Accounts
(cherry picked from commit 6e3e094c95)
2023-11-09 04:45:53 +00:00
Frappe PR Bot
3f433b1b8b chore(release): Bumped to Version 14.47.1
## [14.47.1](https://github.com/frappe/erpnext/compare/v14.47.0...v14.47.1) (2023-11-08)

### Bug Fixes

* asset depreciation ledger (backport [#37991](https://github.com/frappe/erpnext/issues/37991)) ([#37992](https://github.com/frappe/erpnext/issues/37992)) ([0ac78a9](0ac78a96a9))
2023-11-08 18:40:20 +00:00
Anand Baburajan
0532f72cb1 Merge pull request #37996 from frappe/mergify/bp/version-14/pr-37992
fix: asset depreciation ledger (backport #37991) (backport #37992)
2023-11-09 00:09:05 +05:30
mergify[bot]
0ac78a96a9 fix: asset depreciation ledger (backport #37991) (#37992)
* fix: asset depreciation ledger (#37991)

* fix: include opening acc depr while calculating asset depr ledger report

* chore: include opening acc depr properly in acc depr amt

* chore: add cost_center in asset depr ledger report

* fix: handle finance books properly in asset depr ledger report

* chore: rename 'include default book entries' to 'include default FB entries'

(cherry picked from commit 9a171db97f)

# Conflicts:
#	erpnext/accounts/report/balance_sheet/balance_sheet.js
#	erpnext/accounts/report/cash_flow/cash_flow.js
#	erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
#	erpnext/accounts/report/trial_balance/trial_balance.js
#	erpnext/translations/pl.csv
#	erpnext/translations/tr.csv

* chore: fix conflict in balance_sheet.js

* chore: fix conflict in cash_flow.js

* chore: fix conflict in consolidated_financial_statement.js

* chore: fix conflict in trial_balance.js

* chore: fix conflict in tr.csv

* chore: fix conflict in pl.csv

---------

Co-authored-by: Anand Baburajan <anandbaburajan@gmail.com>
(cherry picked from commit 043dc1b14b)
2023-11-08 18:07:42 +00:00
mergify[bot]
043dc1b14b fix: asset depreciation ledger (backport #37991) (#37992)
* fix: asset depreciation ledger (#37991)

* fix: include opening acc depr while calculating asset depr ledger report

* chore: include opening acc depr properly in acc depr amt

* chore: add cost_center in asset depr ledger report

* fix: handle finance books properly in asset depr ledger report

* chore: rename 'include default book entries' to 'include default FB entries'

(cherry picked from commit 9a171db97f)

# Conflicts:
#	erpnext/accounts/report/balance_sheet/balance_sheet.js
#	erpnext/accounts/report/cash_flow/cash_flow.js
#	erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
#	erpnext/accounts/report/trial_balance/trial_balance.js
#	erpnext/translations/pl.csv
#	erpnext/translations/tr.csv

* chore: fix conflict in balance_sheet.js

* chore: fix conflict in cash_flow.js

* chore: fix conflict in consolidated_financial_statement.js

* chore: fix conflict in trial_balance.js

* chore: fix conflict in tr.csv

* chore: fix conflict in pl.csv

---------

Co-authored-by: Anand Baburajan <anandbaburajan@gmail.com>
2023-11-08 23:36:17 +05:30
Deepesh Garg
c5a6b17c15 Merge pull request #37825 from frappe/mergify/bp/version-14-hotfix/pr-37278
fix: german translations of Accounts Settings (backport #37278)
2023-11-08 18:44:11 +05:30
Deepesh Garg
16c3f3bcbd Merge pull request #37913 from frappe/mergify/bp/version-14-hotfix/pr-37299
fix: Set right party name in bank transaction (backport #37299)
2023-11-08 12:28:10 +05:30
Frappe PR Bot
4d804951c6 chore(release): Bumped to Version 14.47.0
# [14.47.0](https://github.com/frappe/erpnext/compare/v14.46.7...v14.47.0) (2023-11-08)

### Bug Fixes

* `TypeError` in PR for non-stock item ([ef4471f](ef4471f8c0))
* add missing disbursement account in update_old_loans patch ([ad64065](ad64065ec6))
* add translation wrapper (backport [#37911](https://github.com/frappe/erpnext/issues/37911)) ([#37946](https://github.com/frappe/erpnext/issues/37946)) ([c53d281](c53d281b9e))
* don't reset rate if greater than zero in standalone debit note (backport [#37935](https://github.com/frappe/erpnext/issues/37935)) ([#37940](https://github.com/frappe/erpnext/issues/37940)) ([64658fc](64658fc790))
* fetch asset received but not billed account only when needed ([7df4009](7df4009dd3))
* gov compliance for tax withholding report ([#37590](https://github.com/frappe/erpnext/issues/37590)) ([273cc35](273cc35b91))
* In-Transit Warehouse company filter (backport [#37796](https://github.com/frappe/erpnext/issues/37796)) ([#37797](https://github.com/frappe/erpnext/issues/37797)) ([0b1da08](0b1da08d78))
* link between parent and child procedure (backport [#37903](https://github.com/frappe/erpnext/issues/37903)) ([#37943](https://github.com/frappe/erpnext/issues/37943)) ([24da29a](24da29a817))
* list index out of range ([#37880](https://github.com/frappe/erpnext/issues/37880)) ([05fed9e](05fed9e352))
* make `Material Request Item` required if `Material Request` is set in PO (backport [#37928](https://github.com/frappe/erpnext/issues/37928)) ([#37936](https://github.com/frappe/erpnext/issues/37936)) ([c870120](c87012046d))
* permission error while creating Supplier Quotation from Portal (backport [#37864](https://github.com/frappe/erpnext/issues/37864)) ([#37870](https://github.com/frappe/erpnext/issues/37870)) ([1a3dae0](1a3dae0f9a))
* **plaid:** Do not sync pending transactions ([ffdc11b](ffdc11bbf6))
* POS change amount gl entry with no amount ([#37799](https://github.com/frappe/erpnext/issues/37799)) ([5e1a89b](5e1a89b3f9))
* Quality Inspection Parameter migration - DuplicateEntryError due to case sensitivity (backport [#37499](https://github.com/frappe/erpnext/issues/37499)) ([#37916](https://github.com/frappe/erpnext/issues/37916)) ([eb3630b](eb3630bcf8))
* remove voucher type and no for Item and Warehouse based reposting (backport [#37849](https://github.com/frappe/erpnext/issues/37849)) ([#37850](https://github.com/frappe/erpnext/issues/37850)) ([e19cade](e19cade12d))
* standard submit perm in repost ledger for editable invoices (backport [#37826](https://github.com/frappe/erpnext/issues/37826)) ([#37854](https://github.com/frappe/erpnext/issues/37854)) ([69b569d](69b569df46))
* status for over delivery or billing ([d8e7430](d8e743013f))
* type error on new payment entry ([38184f7](38184f77c7))
* typo in AR report ([3d72ec7](3d72ec7ca4))
* validate so item with qtn ([4a225b0](4a225b069b))

### Features

* reserved production plan sub assembly items (backport [#37884](https://github.com/frappe/erpnext/issues/37884)) ([#37926](https://github.com/frappe/erpnext/issues/37926)) ([4de97a4](4de97a4fcb))
* settings page for repost ([09cde5d](09cde5da08))
* **Stock Balance:** add filters from route (backport [#37836](https://github.com/frappe/erpnext/issues/37836)) ([#37839](https://github.com/frappe/erpnext/issues/37839)) ([e8a706a](e8a706a5ea))

### Performance Improvements

* Add index to supplier invoice field (backport [#37861](https://github.com/frappe/erpnext/issues/37861)) ([#37862](https://github.com/frappe/erpnext/issues/37862)) ([2c93f81](2c93f81d59))
* index return against for purchase invoice (backport [#37881](https://github.com/frappe/erpnext/issues/37881)) ([#37882](https://github.com/frappe/erpnext/issues/37882)) ([fed25fa](fed25fac76))
2023-11-08 06:19:10 +00:00
Deepesh Garg
c5ddb4153a Merge pull request #37965 from frappe/version-14-hotfix
chore: release v14
2023-11-08 11:47:53 +05:30
ruthra kumar
b0ed3c2f0a Merge pull request #37977 from ruthra-kumar/add_voucher_detail_no_to_payment_ledger
refactor: Add voucher_detail_no to payment ledger
2023-11-08 11:23:15 +05:30
ruthra kumar
3f8d58c9c6 refactor: add voucher_detail_no to PLE doctype 2023-11-08 10:53:16 +05:30
ruthra kumar
8a3139f6f5 Merge pull request #37901 from frappe/mergify/bp/version-14-hotfix/pr-37887
chore: performance optimization on payment ledger entry doctype (backport #37887)
2023-11-08 10:48:30 +05:30
ruthra kumar
0b601d8cae chore: performance optimization on payment ledger entry doctype
(cherry picked from commit f14d1eb871)
2023-11-08 10:23:52 +05:30
ruthra kumar
9be71e45b9 Merge pull request #37975 from frappe/mergify/bp/version-14-hotfix/pr-37971
refactor: optimize bulk transaction for speed (backport #37971)
2023-11-08 07:08:42 +05:30
ruthra kumar
e58604a90f refactor: optimize for speed
(cherry picked from commit 416bd400bb)
2023-11-08 01:03:28 +00:00
mergify[bot]
e895bb3a63 chore: typo in Stock Entry enqueue msg (backport #37970) (#37972)
chore: typo in `Stock Entry` enqueue msg

(cherry picked from commit ee60fa940c)

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2023-11-07 15:57:20 +00:00
ruthra kumar
38a5e6f10b Merge pull request #37967 from frappe/mergify/bp/version-14-hotfix/pr-37954
refactor: expand repost to `Expense Claim` and make it configurable (backport #37954)
2023-11-07 16:24:44 +05:30
ruthra kumar
8f0cf1b7dc chore: resolve conflict 2023-11-07 15:56:35 +05:30
ruthra kumar
3da2597703 refactor: update permissions for repost settings
(cherry picked from commit 10b9570429)
2023-11-07 10:14:36 +00:00
ruthra kumar
82bf726b83 refactor(test): repost test case for purchase invoice
(cherry picked from commit 11c8d9fcf1)
2023-11-07 10:14:35 +00:00
ruthra kumar
7d4dc67b61 refactor: select distinct types
(cherry picked from commit 61705047b0)
2023-11-07 10:14:33 +00:00
ruthra kumar
35f5498913 refactor(test): update repost settings for test cases
(cherry picked from commit ac79b8483f)
2023-11-07 10:14:32 +00:00
ruthra kumar
ed557274d2 refactor: support for expense claim repost
(cherry picked from commit b651b36fff)
2023-11-07 10:14:30 +00:00
ruthra kumar
18e6931d78 refactor: configurable repost settings
(cherry picked from commit 5a068410c6)
2023-11-07 10:14:29 +00:00
ruthra kumar
560a45b343 chore: patch to update default repost settings value
(cherry picked from commit ebb186c8df)

# Conflicts:
#	erpnext/patches.txt
2023-11-07 10:14:28 +00:00
ruthra kumar
09cde5da08 feat: settings page for repost
(cherry picked from commit d582a73795)
2023-11-07 10:14:21 +00:00
ruthra kumar
503c0f33bb Merge pull request #37957 from frappe/mergify/bp/version-14-hotfix/pr-37956
fix: type error on new payment entry (backport #37956)
2023-11-07 12:47:10 +05:30
ruthra kumar
38184f77c7 fix: type error on new payment entry
(cherry picked from commit adff287160)
2023-11-07 12:40:16 +05:30
Frappe PR Bot
449b641560 chore(release): Bumped to Version 14.46.7
## [14.46.7](https://github.com/frappe/erpnext/compare/v14.46.6...v14.46.7) (2023-11-06)

### Bug Fixes

* typo in AR report ([d54e756](d54e756453))
2023-11-06 15:33:32 +00:00
ruthra kumar
3cc5e5591d Merge pull request #37951 from frappe/mergify/bp/version-14/pr-37948
fix: typo in AR report (backport #37948)
2023-11-06 21:00:23 +05:30
ruthra kumar
bc5e01e846 Merge pull request #37949 from frappe/mergify/bp/version-14-hotfix/pr-37948
fix: typo in AR report (backport #37948)
2023-11-06 20:55:22 +05:30
ruthra kumar
d54e756453 fix: typo in AR report
(cherry picked from commit 67e74d03ed)
2023-11-06 15:00:11 +00:00
ruthra kumar
3d72ec7ca4 fix: typo in AR report
(cherry picked from commit 67e74d03ed)
2023-11-06 14:56:44 +00:00
mergify[bot]
c53d281b9e fix: add translation wrapper (backport #37911) (#37946)
fix: add translation wrapper

(cherry picked from commit 8722318081)

Co-authored-by: hyaray <hyaray@vip.qq.com>
2023-11-06 19:52:11 +05:30
Frappe PR Bot
94b38b900c chore(release): Bumped to Version 14.46.6
## [14.46.6](https://github.com/frappe/erpnext/compare/v14.46.5...v14.46.6) (2023-11-06)

### Bug Fixes

* don't reset rate if greater than zero in standalone debit note (backport [#37935](https://github.com/frappe/erpnext/issues/37935)) (backport [#37940](https://github.com/frappe/erpnext/issues/37940)) ([#37945](https://github.com/frappe/erpnext/issues/37945)) ([235f166](235f1664e0))
2023-11-06 14:15:53 +00:00
mergify[bot]
235f1664e0 fix: don't reset rate if greater than zero in standalone debit note (backport #37935) (backport #37940) (#37945)
fix: don't reset rate if greater than zero in standalone debit note (backport #37935) (#37940)

* fix: don't reset rate if greater than zero in standalone debit note

(cherry picked from commit 5cce522ecd)

* fix(test): `test_gl_entries_for_standalone_debit_note`

(cherry picked from commit f9fc6c9c9d)

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
(cherry picked from commit 64658fc790)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2023-11-06 19:37:15 +05:30
mergify[bot]
24da29a817 fix: link between parent and child procedure (backport #37903) (#37943)
* fix: link between parent and child procedure

(cherry picked from commit 05f24ede96)

* chore: add missing filters for `Parent Procedure`

(cherry picked from commit 8fbd4cea5b)

* test: add test case for Quality Procedure`

(cherry picked from commit 30c6b83a10)

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2023-11-06 19:28:19 +05:30
mergify[bot]
64658fc790 fix: don't reset rate if greater than zero in standalone debit note (backport #37935) (#37940)
* fix: don't reset rate if greater than zero in standalone debit note

(cherry picked from commit 5cce522ecd)

* fix(test): `test_gl_entries_for_standalone_debit_note`

(cherry picked from commit f9fc6c9c9d)

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2023-11-06 19:27:28 +05:30
mergify[bot]
c87012046d fix: make Material Request Item required if Material Request is set in PO (backport #37928) (#37936)
fix: make `Material Request Item` required if `Material Request` is set in PO

(cherry picked from commit a9d91189b0)

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2023-11-06 17:26:37 +05:30
Frappe PR Bot
21ad1dba19 chore(release): Bumped to Version 14.46.5
## [14.46.5](https://github.com/frappe/erpnext/compare/v14.46.4...v14.46.5) (2023-11-06)

### Bug Fixes

* additional filter in ar/ap report ([930aee1](930aee1d70))
2023-11-06 06:42:02 +00:00
ruthra kumar
9c356a0ac2 Merge pull request #37929 from frappe/mergify/bp/version-14/pr-37873
refactor: 'group only by voucher' flag in AR/AP report (backport #37869) (backport #37873)
2023-11-06 12:10:29 +05:30
ruthra kumar
930aee1d70 fix: additional filter in ar/ap report
empty commit
2023-11-06 11:51:39 +05:30
mergify[bot]
4de97a4fcb feat: reserved production plan sub assembly items (backport #37884) (#37926)
feat: reserved production plan sub assembly items (#37884)

(cherry picked from commit 34d3eb88b3)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2023-11-06 11:40:21 +05:30
ruthra kumar
932d1e7c62 Merge pull request #37924 from frappe/mergify/bp/version-14-hotfix/pr-37879
refactor: flag to toggle billed amy update in DN for Credit Note (backport #37879)
2023-11-06 11:24:08 +05:30
ruthra kumar
a8b26ebc6b refactor: group only by voucher flag in AR/AP report
(cherry picked from commit 23beb46d15)
(cherry picked from commit ee5898a773)
2023-11-06 05:53:50 +00:00
ruthra kumar
71ad448281 refactor(test): enable billed amt update on Sales Return(Cr Note)
(cherry picked from commit 0c5bdbdcf3)
2023-11-06 09:40:32 +05:30
ruthra kumar
6eb867a1e4 refactor: flag to toggle billed amy update in DN for Credit Note
(cherry picked from commit a3191f1c8c)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.json
2023-11-06 03:11:20 +00:00
mergify[bot]
5e1a89b3f9 fix: POS change amount gl entry with no amount (#37799)
fix: POS change amount gl entry with no amount (#37799)

(cherry picked from commit 2b02ef0066)

Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
2023-11-05 17:56:19 +05:30
Frappe PR Bot
b2b8b72952 chore(release): Bumped to Version 14.46.4
## [14.46.4](https://github.com/frappe/erpnext/compare/v14.46.3...v14.46.4) (2023-11-05)

### Bug Fixes

* Quality Inspection Parameter migration - DuplicateEntryError due to case sensitivity (backport [#37499](https://github.com/frappe/erpnext/issues/37499)) (backport [#37916](https://github.com/frappe/erpnext/issues/37916)) ([#37919](https://github.com/frappe/erpnext/issues/37919)) ([555ebc1](555ebc190c))
2023-11-05 06:41:12 +00:00
mergify[bot]
555ebc190c fix: Quality Inspection Parameter migration - DuplicateEntryError due to case sensitivity (backport #37499) (backport #37916) (#37919)
fix: Quality Inspection Parameter migration - DuplicateEntryError due to case sensitivity (backport #37499) (#37916)

fix: Quality Inspection Parameter migration - DuplicateEntryError due to case sensitivity (#37499)

* fix: account for case-insensitive database primary key for parameter names

* chore: linting

(cherry picked from commit b099590b2c)

Co-authored-by: Richard Case <110036763+casesolved-co-uk@users.noreply.github.com>
(cherry picked from commit eb3630bcf8)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2023-11-05 12:10:04 +05:30
viralkansodiya15
05fed9e352 fix: list index out of range (#37880)
* fix: list index out of range

* fix: changes in error message

* fix: change error message and date comparision

* fix: change a return a value when disposal date is equal to available for use date

* fix: changes to fix linter test failing
2023-11-05 11:54:39 +05:30
mergify[bot]
eb3630bcf8 fix: Quality Inspection Parameter migration - DuplicateEntryError due to case sensitivity (backport #37499) (#37916)
fix: Quality Inspection Parameter migration - DuplicateEntryError due to case sensitivity (#37499)

* fix: account for case-insensitive database primary key for parameter names

* chore: linting

(cherry picked from commit b099590b2c)

Co-authored-by: Richard Case <110036763+casesolved-co-uk@users.noreply.github.com>
2023-11-05 06:16:23 +00:00
ruthra kumar
c2001bec15 Merge pull request #37915 from ruthra-kumar/prevent_precision_based_validation_error_reconciliation
refactor: avoid precision based validation error on reconciliation
2023-11-05 05:58:32 +05:30
ruthra kumar
be925d2d33 refactor: avoid precision based validation error on reconciliation 2023-11-05 05:22:09 +05:30
marination
b0a184e937 fix: Use process.extract to get the corresponding party doc name of the result
- rapidfuzz accepts an iterable or a dict. dict input gives the dict key and value in the result

(cherry picked from commit e0a03789ae)
2023-11-04 15:48:18 +00:00
marination
21b430a575 fix: Set right party name in bank transaction
- If party name and docname are different, set the docname in Bank Transaction

(cherry picked from commit ff1dc72d74)
2023-11-04 15:48:18 +00:00
Anand Baburajan
65dfef021a chore: rename depreciation_amount_based_on_num_days_in_month to daily_prorata_based [v14] (#37898)
chore: rename depreciation_amount_based_on_num_days_in_month to daily_prorata_based
2023-11-03 20:18:20 +00:00
Anand Baburajan
86c6ae6275 chore: rename daily_depreciation in asset to depreciation_amount_based_on_num_days_in_month [v14] (#37895)
chore: rename daily_depreciation to depreciation_amount_based_on_num_days_in_month
2023-11-03 23:26:34 +05:30
mergify[bot]
fed25fac76 perf: index return against for purchase invoice (backport #37881) (#37882)
perf: index return against for purchase invoice (#37881)

(cherry picked from commit 469ae2c7f1)

Co-authored-by: Ankush Menat <ankush@frappe.io>
2023-11-03 21:59:46 +05:30
Anand Baburajan
6b5cffc77a Merge pull request #37889 from anandbaburajan/update_old_loans_disb_account
fix: add missing disbursement account in update_old_loans patch
2023-11-03 21:45:33 +05:30
anandbaburajan
ad64065ec6 fix: add missing disbursement account in update_old_loans patch 2023-11-03 20:57:52 +05:30
mergify[bot]
1a3dae0f9a fix: permission error while creating Supplier Quotation from Portal (backport #37864) (#37870)
* fix: permission error while creating Supplier Quotation from Portal

(cherry picked from commit e019d43d0b)

# Conflicts:
#	erpnext/controllers/buying_controller.py

* chore: `conflicts`

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2023-11-03 16:24:36 +05:30
ruthra kumar
15308c9aac Merge pull request #37875 from frappe/mergify/bp/version-14-hotfix/pr-37852
refactor: better ledger comparision report (backport #37852)
2023-11-03 13:25:22 +05:30
ruthra kumar
09ba6c1266 Merge pull request #37873 from frappe/mergify/bp/version-14-hotfix/pr-37869
refactor: 'group only by voucher' flag in AR/AP report (backport #37869)
2023-11-03 13:25:04 +05:30
ruthra kumar
afa6ed9e22 refactor(test): for ledger comparision report
(cherry picked from commit 639f427d6d)
2023-11-03 07:22:59 +00:00
ruthra kumar
3d2ff7eea3 refactor: better output on gl and pl comparison report
(cherry picked from commit 539f0251d9)
2023-11-03 07:22:58 +00:00
ruthra kumar
ee5898a773 refactor: group only by voucher flag in AR/AP report
(cherry picked from commit 23beb46d15)
2023-11-03 07:00:25 +00:00
mergify[bot]
2c93f81d59 perf: Add index to supplier invoice field (backport #37861) (#37862)
fix: Add index to supplier invoice field (#37861)

* fix: Add index to supplier invoice field

* chore: remove unintetional changes

(cherry picked from commit c37e374fdd)

Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
2023-11-03 11:52:07 +05:30
mergify[bot]
e19cade12d fix: remove voucher type and no for Item and Warehouse based reposting (backport #37849) (#37850)
* fix: remove voucher type and no for Item and Warehouse based reposting

(cherry picked from commit 0104897d69)

* chore: fix test cases

---------

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2023-11-02 15:15:53 +05:30
mergify[bot]
273cc35b91 fix: gov compliance for tax withholding report (#37590)
* refactor: avoid relying only on against in tds docs query

(cherry picked from commit 705dadae8e)

* chore: change column order

(cherry picked from commit 7ecc0d5a04)

* fix: sort by section code

(cherry picked from commit 4471ad581e)

* feat: proprietorship & partnership options in entity type

(cherry picked from commit ed2457bddf)

# Conflicts:
#	erpnext/buying/doctype/supplier/supplier.json
#	erpnext/selling/doctype/customer/customer.json

* chore: linting issues

(cherry picked from commit 75441017c6)

* feat: add cols for supplier inv details

(cherry picked from commit 6d5ccde864)

* chore: resolve conflicts

* chore: resolve conflicts

* chore: linting issues

---------

Co-authored-by: Gursheen Anand <gursheen@frappe.io>
Co-authored-by: Gursheen Kaur Anand <40693548+GursheenK@users.noreply.github.com>
2023-11-02 14:34:23 +05:30
mergify[bot]
69b569df46 fix: standard submit perm in repost ledger for editable invoices (backport #37826) (#37854)
fix: standard submit perm in repost ledger for editable invoices (#37826)

* fix: ignore perm while reposting ledger

* fix: use flag in save

* fix: remove unnecessary save

(cherry picked from commit 1b808e1d7c)

Co-authored-by: Gursheen Kaur Anand <40693548+GursheenK@users.noreply.github.com>
2023-11-02 14:33:33 +05:30
rohitwaghchaure
a07d58bd0e Merge pull request #37841 from frappe/mergify/bp/version-14-hotfix/pr-37819
fix: `TypeError` in PR for non-stock item (backport #37819)
2023-11-02 13:34:23 +05:30
ruthra kumar
50fdc9dda0 Merge pull request #37846 from frappe/mergify/copy/version-14-hotfix/pr-37845
chore: add std permissions for Process Payment Reconciilation log (copy #37845)
2023-11-02 12:10:27 +05:30
ruthra kumar
9b0a46853f chore: std permissions for Process Payment Reconciilation log
(cherry picked from commit a9fceeb00f)
2023-11-02 06:10:54 +00:00
ruthra kumar
64d7590bd0 Merge pull request #37843 from frappe/mergify/bp/version-14-hotfix/pr-37838
refactor: pass limits to JE and PE queries in reconciliation tool (backport #37838)
2023-11-02 11:08:51 +05:30
mergify[bot]
e8a706a5ea feat(Stock Balance): add filters from route (backport #37836) (#37839)
feat(Stock Balance): add filters from route

(cherry picked from commit 38e5e4a893)

Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
2023-11-02 10:46:42 +05:30
ruthra kumar
289236d065 refactor: pass limits to JE and PE queries in reconciliation tool
(cherry picked from commit 54e8ce1ac5)
2023-11-02 05:13:08 +00:00
s-aga-r
ef4471f8c0 fix: TypeError in PR for non-stock item
(cherry picked from commit 028b3e2fbf)
2023-11-02 05:10:19 +00:00
ruthra kumar
e616a0bb63 Merge pull request #37833 from frappe/mergify/bp/version-14-hotfix/pr-37832
refactor: checkbox to toggle remarks in General Ledger (backport #37832)
2023-11-02 08:06:40 +05:30
ruthra kumar
174b76f6ff refactor: checkbox to toggle remarks in General Ledger
(cherry picked from commit 8fa677b8e8)
2023-11-02 07:28:42 +05:30
mergify[bot]
875d7f8b72 refactor: update fields label and remove unused fields from BIN (backport #37827) (#37829)
* refactor: rearrange fields and update label

(cherry picked from commit ec1a7869f8)

* refactor: remove unused fields `fcfs_rate` and `ma_rate` from Bin

(cherry picked from commit f0a1f4ac7c)

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2023-11-01 16:41:33 +05:30
Raffael Meyer
2c1fdecc91 chore: resolve merge conflicts 2023-11-01 11:54:29 +01:00
barredterra
4d2169e48e fix(translations): suggestions from review
(cherry picked from commit 115f024260)
2023-11-01 09:43:41 +00:00
barredterra
b75aae99ca fix: german translations of Accounts Settings
(cherry picked from commit b3486b43c4)

# Conflicts:
#	erpnext/translations/de.csv
2023-11-01 09:43:40 +00:00
Deepesh Garg
f502ec2268 Merge pull request #37821 from frappe/mergify/bp/version-14-hotfix/pr-37635
fix: validate sales order item with quotation (backport #37635)
2023-11-01 15:13:26 +05:30
Deepesh Garg
0196d7ac23 Merge pull request #37717 from frappe/mergify/bp/version-14-hotfix/pr-37690
fix(plaid): Do not sync pending transactions (#37690)
2023-11-01 14:12:33 +05:30
Deepesh Garg
357697702b chore: resolve conflicts 2023-11-01 14:11:36 +05:30
Gursheen Anand
4a225b069b fix: validate so item with qtn
(cherry picked from commit 17ebc1ea80)
2023-11-01 08:34:50 +00:00
Deepesh Garg
28c9458482 Merge pull request #37815 from frappe/mergify/bp/version-14-hotfix/pr-37680
fix: status when over delivery or billing in SO (#37680)
2023-11-01 14:03:59 +05:30
Gursheen Anand
d8e743013f fix: status for over delivery or billing
(cherry picked from commit d69b0d76dd)
2023-11-01 07:00:14 +00:00
Deepesh Garg
555cc62e50 Merge pull request #37812 from frappe/mergify/bp/version-14-hotfix/pr-37737
fix: fetch asset received but not billed account only when needed (backport #37737)
2023-11-01 12:10:04 +05:30
Deepesh Garg
7df4009dd3 fix: fetch asset received but not billed account only when needed
(cherry picked from commit 3a8736374c)
2023-11-01 04:49:59 +00:00
ruthra kumar
08a9a9d188 Merge pull request #37806 from frappe/mergify/bp/version-14-hotfix/pr-37795
chore: update default limit values in reconciliation tool (backport #37795)
2023-10-31 20:37:40 +05:30
ruthra kumar
e98be384f9 Merge pull request #37804 from frappe/mergify/bp/version-14-hotfix/pr-37793
refactor: pull remarks only if needed on AR/AP report (backport #37793)
2023-10-31 20:37:06 +05:30
ruthra kumar
fdf2977ce2 chore: update default limit values in reconciliation tool
(cherry picked from commit 1fd888175f)
2023-10-31 14:22:29 +00:00
ruthra kumar
3276f39740 refactor: pull remarks only if needed on AR/AP report
(cherry picked from commit eb73017798)
2023-10-31 14:21:52 +00:00
mergify[bot]
0b1da08d78 fix: In-Transit Warehouse company filter (backport #37796) (#37797)
fix: In-Transit Warehouse company filter (#37796)

(cherry picked from commit daf2ec063c)

Co-authored-by: hyaray <hyaray@vip.qq.com>
2023-10-31 18:53:37 +05:30
Deepesh Garg
ffdc11bbf6 fix(plaid): Do not sync pending transactions
(cherry picked from commit 46ea868559)

# Conflicts:
#	erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
2023-10-27 06:08:46 +00:00
254 changed files with 3282 additions and 52459 deletions

View File

@@ -3,7 +3,7 @@ import inspect
import frappe
__version__ = "14.46.3"
__version__ = "14.51.0"
def get_default_company(user=None):

View File

@@ -68,7 +68,12 @@
"enable_party_matching",
"enable_fuzzy_matching",
"tab_break_dpet",
"show_balance_in_coa"
"show_balance_in_coa",
"reports_tab",
"remarks_section",
"general_ledger_remarks_length",
"column_break_lvjk",
"receivable_payable_remarks_length"
],
"fields": [
{
@@ -429,6 +434,34 @@
"fieldname": "show_balance_in_coa",
"fieldtype": "Check",
"label": "Show Balances in Chart Of Accounts"
},
{
"fieldname": "reports_tab",
"fieldtype": "Tab Break",
"label": "Reports"
},
{
"default": "0",
"description": "Truncates 'Remarks' column to set character length",
"fieldname": "general_ledger_remarks_length",
"fieldtype": "Int",
"label": "General Ledger"
},
{
"default": "0",
"description": "Truncates 'Remarks' column to set character length",
"fieldname": "receivable_payable_remarks_length",
"fieldtype": "Int",
"label": "Accounts Receivable/Payable"
},
{
"fieldname": "column_break_lvjk",
"fieldtype": "Column Break"
},
{
"fieldname": "remarks_section",
"fieldtype": "Section Break",
"label": "Remarks Column Length"
}
],
"icon": "icon-cog",
@@ -436,7 +469,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2023-07-27 15:05:34.000264",
"modified": "2023-11-20 09:37:47.650347",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",

View File

@@ -423,7 +423,9 @@ def reconcile_vouchers(bank_transaction_name, vouchers):
vouchers = json.loads(vouchers)
transaction = frappe.get_doc("Bank Transaction", bank_transaction_name)
transaction.add_payment_entries(vouchers)
return frappe.get_doc("Bank Transaction", bank_transaction_name)
transaction.save()
return transaction
@frappe.whitelist()

View File

@@ -112,7 +112,8 @@ class AutoMatchbyPartyNameDescription:
for party in parties:
filters = {"status": "Active"} if party == "Employee" else {"disabled": 0}
names = frappe.get_all(party, filters=filters, pluck=party.lower() + "_name")
field = party.lower() + "_name"
names = frappe.get_all(party, filters=filters, fields=[f"{field} as party_name", "name"])
for field in ["bank_party_name", "description"]:
if not self.get(field):
@@ -131,7 +132,11 @@ class AutoMatchbyPartyNameDescription:
def fuzzy_search_and_return_result(self, party, names, field) -> Union[Tuple, None]:
skip = False
result = process.extract(query=self.get(field), choices=names, scorer=fuzz.token_set_ratio)
result = process.extract(
query=self.get(field),
choices={row.get("name"): row.get("party_name") for row in names},
scorer=fuzz.token_set_ratio,
)
party_name, skip = self.process_fuzzy_result(result)
if not party_name:
@@ -149,14 +154,14 @@ class AutoMatchbyPartyNameDescription:
Returns: Result, Skip (whether or not to discontinue matching)
"""
PARTY, SCORE, CUTOFF = 0, 1, 80
SCORE, PARTY_ID, CUTOFF = 1, 2, 80
if not result or not len(result):
return None, False
first_result = result[0]
if len(result) == 1:
return (first_result[PARTY] if first_result[SCORE] > CUTOFF else None), True
return (first_result[PARTY_ID] if first_result[SCORE] > CUTOFF else None), True
second_result = result[1]
if first_result[SCORE] > CUTOFF:
@@ -165,7 +170,7 @@ class AutoMatchbyPartyNameDescription:
if first_result[SCORE] == second_result[SCORE]:
return None, True
return first_result[PARTY], True
return first_result[PARTY_ID], True
else:
return None, False

View File

@@ -13,6 +13,7 @@
"status",
"bank_account",
"company",
"amended_from",
"section_break_4",
"deposit",
"withdrawal",
@@ -25,10 +26,10 @@
"transaction_id",
"transaction_type",
"section_break_14",
"column_break_oufv",
"payment_entries",
"section_break_18",
"allocated_amount",
"amended_from",
"column_break_17",
"unallocated_amount",
"party_section",
@@ -138,10 +139,12 @@
"fieldtype": "Section Break"
},
{
"allow_on_submit": 1,
"fieldname": "allocated_amount",
"fieldtype": "Currency",
"label": "Allocated Amount",
"options": "currency"
"options": "currency",
"read_only": 1
},
{
"fieldname": "amended_from",
@@ -157,10 +160,12 @@
"fieldtype": "Column Break"
},
{
"allow_on_submit": 1,
"fieldname": "unallocated_amount",
"fieldtype": "Currency",
"label": "Unallocated Amount",
"options": "currency"
"options": "currency",
"read_only": 1
},
{
"fieldname": "party_section",
@@ -225,11 +230,15 @@
"fieldname": "bank_party_account_number",
"fieldtype": "Data",
"label": "Party Account No. (Bank Statement)"
},
{
"fieldname": "column_break_oufv",
"fieldtype": "Column Break"
}
],
"is_submittable": 1,
"links": [],
"modified": "2023-06-06 13:58:12.821411",
"modified": "2023-11-18 18:32:47.203694",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Transaction",

View File

@@ -2,78 +2,73 @@
# For license information, please see license.txt
import frappe
from frappe import _
from frappe.utils import flt
from erpnext.controllers.status_updater import StatusUpdater
class BankTransaction(StatusUpdater):
def after_insert(self):
self.unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit))
def before_validate(self):
self.update_allocated_amount()
def on_submit(self):
self.clear_linked_payment_entries()
def validate(self):
self.validate_duplicate_references()
def validate_duplicate_references(self):
"""Make sure the same voucher is not allocated twice within the same Bank Transaction"""
if not self.payment_entries:
return
pe = []
for row in self.payment_entries:
reference = (row.payment_document, row.payment_entry)
if reference in pe:
frappe.throw(
_("{0} {1} is allocated twice in this Bank Transaction").format(
row.payment_document, row.payment_entry
)
)
pe.append(reference)
def update_allocated_amount(self):
self.allocated_amount = (
sum(p.allocated_amount for p in self.payment_entries) if self.payment_entries else 0.0
)
self.unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) - self.allocated_amount
def before_submit(self):
self.allocate_payment_entries()
self.set_status()
if frappe.db.get_single_value("Accounts Settings", "enable_party_matching"):
self.auto_set_party()
_saving_flag = False
# nosemgrep: frappe-semgrep-rules.rules.frappe-modifying-but-not-comitting
def on_update_after_submit(self):
"Run on save(). Avoid recursion caused by multiple saves"
if not self._saving_flag:
self._saving_flag = True
self.clear_linked_payment_entries()
self.update_allocations()
self._saving_flag = False
def before_update_after_submit(self):
self.validate_duplicate_references()
self.allocate_payment_entries()
self.update_allocated_amount()
def on_cancel(self):
self.clear_linked_payment_entries(for_cancel=True)
self.set_status(update=True)
for payment_entry in self.payment_entries:
self.clear_linked_payment_entry(payment_entry, for_cancel=True)
def update_allocations(self):
"The doctype does not allow modifications after submission, so write to the db direct"
if self.payment_entries:
allocated_amount = sum(p.allocated_amount for p in self.payment_entries)
else:
allocated_amount = 0.0
amount = abs(flt(self.withdrawal) - flt(self.deposit))
self.db_set("allocated_amount", flt(allocated_amount))
self.db_set("unallocated_amount", amount - flt(allocated_amount))
self.reload()
self.set_status(update=True)
def add_payment_entries(self, vouchers):
"Add the vouchers with zero allocation. Save() will perform the allocations and clearance"
if 0.0 >= self.unallocated_amount:
frappe.throw(frappe._("Bank Transaction {0} is already fully reconciled").format(self.name))
frappe.throw(_("Bank Transaction {0} is already fully reconciled").format(self.name))
added = False
for voucher in vouchers:
# Can't add same voucher twice
found = False
for pe in self.payment_entries:
if (
pe.payment_document == voucher["payment_doctype"]
and pe.payment_entry == voucher["payment_name"]
):
found = True
if not found:
pe = {
self.append(
"payment_entries",
{
"payment_document": voucher["payment_doctype"],
"payment_entry": voucher["payment_name"],
"allocated_amount": 0.0, # Temporary
}
child = self.append("payment_entries", pe)
added = True
# runs on_update_after_submit
if added:
self.save()
},
)
def allocate_payment_entries(self):
"""Refactored from bank reconciliation tool.
@@ -89,8 +84,8 @@ class BankTransaction(StatusUpdater):
- 0 > a: Error: already over-allocated
- clear means: set the latest transaction date as clearance date
"""
gl_bank_account = frappe.db.get_value("Bank Account", self.bank_account, "account")
remaining_amount = self.unallocated_amount
to_remove = []
for payment_entry in self.payment_entries:
if payment_entry.allocated_amount == 0.0:
unallocated_amount, should_clear, latest_transaction = get_clearance_details(
@@ -100,49 +95,39 @@ class BankTransaction(StatusUpdater):
if 0.0 == unallocated_amount:
if should_clear:
latest_transaction.clear_linked_payment_entry(payment_entry)
self.db_delete_payment_entry(payment_entry)
to_remove.append(payment_entry)
elif remaining_amount <= 0.0:
self.db_delete_payment_entry(payment_entry)
to_remove.append(payment_entry)
elif 0.0 < unallocated_amount and unallocated_amount <= remaining_amount:
payment_entry.db_set("allocated_amount", unallocated_amount)
elif 0.0 < unallocated_amount <= remaining_amount:
payment_entry.allocated_amount = unallocated_amount
remaining_amount -= unallocated_amount
if should_clear:
latest_transaction.clear_linked_payment_entry(payment_entry)
elif 0.0 < unallocated_amount and unallocated_amount > remaining_amount:
payment_entry.db_set("allocated_amount", remaining_amount)
elif 0.0 < unallocated_amount:
payment_entry.allocated_amount = remaining_amount
remaining_amount = 0.0
elif 0.0 > unallocated_amount:
self.db_delete_payment_entry(payment_entry)
frappe.throw(frappe._("Voucher {0} is over-allocated by {1}").format(unallocated_amount))
frappe.throw(_("Voucher {0} is over-allocated by {1}").format(unallocated_amount))
self.reload()
def db_delete_payment_entry(self, payment_entry):
frappe.db.delete("Bank Transaction Payments", {"name": payment_entry.name})
for payment_entry in to_remove:
self.remove(to_remove)
@frappe.whitelist()
def remove_payment_entries(self):
for payment_entry in self.payment_entries:
self.remove_payment_entry(payment_entry)
# runs on_update_after_submit
self.save()
self.save() # runs before_update_after_submit
def remove_payment_entry(self, payment_entry):
"Clear payment entry and clearance"
self.clear_linked_payment_entry(payment_entry, for_cancel=True)
self.remove(payment_entry)
def clear_linked_payment_entries(self, for_cancel=False):
if for_cancel:
for payment_entry in self.payment_entries:
self.clear_linked_payment_entry(payment_entry, for_cancel)
else:
self.allocate_payment_entries()
def clear_linked_payment_entry(self, payment_entry, for_cancel=False):
clearance_date = None if for_cancel else self.date
set_voucher_clearance(
@@ -163,11 +148,10 @@ class BankTransaction(StatusUpdater):
deposit=self.deposit,
).match()
if result:
party_type, party = result
frappe.db.set_value(
"Bank Transaction", self.name, field={"party_type": party_type, "party": party}
)
if not result:
return
self.party_type, self.party = result
@frappe.whitelist()
@@ -199,9 +183,7 @@ def get_clearance_details(transaction, payment_entry):
if gle["gl_account"] == gl_bank_account:
if gle["amount"] <= 0.0:
frappe.throw(
frappe._("Voucher {0} value is broken: {1}").format(
payment_entry.payment_entry, gle["amount"]
)
_("Voucher {0} value is broken: {1}").format(payment_entry.payment_entry, gle["amount"])
)
unmatched_gles -= 1
@@ -222,7 +204,7 @@ def get_clearance_details(transaction, payment_entry):
def get_related_bank_gl_entries(doctype, docname):
# nosemgrep: frappe-semgrep-rules.rules.frappe-using-db-sql
result = frappe.db.sql(
return frappe.db.sql(
"""
SELECT
ABS(gle.credit_in_account_currency - gle.debit_in_account_currency) AS amount,
@@ -240,7 +222,6 @@ def get_related_bank_gl_entries(doctype, docname):
dict(doctype=doctype, docname=docname),
as_dict=True,
)
return result
def get_total_allocated_amount(doctype, docname):
@@ -373,6 +354,7 @@ def set_voucher_clearance(doctype, docname, clearance_date, self):
if clearance_date:
vouchers = [{"payment_doctype": "Bank Transaction", "payment_name": self.name}]
bt.add_payment_entries(vouchers)
bt.save()
else:
for pe in bt.payment_entries:
if pe.payment_document == self.doctype and pe.payment_entry == self.name:

View File

@@ -53,10 +53,18 @@ frappe.ui.form.on('Chart of Accounts Importer', {
of Accounts. Please enter the account names and add more rows as per your requirement.`);
}
}
}
},
{
label : "Company",
fieldname: "company",
fieldtype: "Link",
reqd: 1,
hidden: 1,
default: frm.doc.company,
},
],
primary_action: function() {
var data = d.get_values();
let data = d.get_values();
if (!data.template_type) {
frappe.throw(__('Please select <b>Template Type</b> to download template'));
@@ -66,7 +74,8 @@ frappe.ui.form.on('Chart of Accounts Importer', {
'/api/method/erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template',
{
file_type: data.file_type,
template_type: data.template_type
template_type: data.template_type,
company: data.company
}
);

View File

@@ -8,6 +8,7 @@ from functools import reduce
import frappe
from frappe import _
from frappe.desk.form.linked_with import get_linked_fields
from frappe.model.document import Document
from frappe.utils import cint, cstr
from frappe.utils.csvutils import UnicodeWriter
@@ -112,7 +113,7 @@ def generate_data_from_csv(file_doc, as_dict=False):
if as_dict:
data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)})
else:
if not row[1]:
if not row[1] and len(row) > 1:
row[1] = row[0]
row[3] = row[2]
data.append(row)
@@ -294,10 +295,8 @@ def build_response_as_excel(writer):
@frappe.whitelist()
def download_template(file_type, template_type):
data = frappe._dict(frappe.local.form_dict)
writer = get_template(template_type)
def download_template(file_type, template_type, company):
writer = get_template(template_type, company)
if file_type == "CSV":
# download csv file
@@ -308,8 +307,7 @@ def download_template(file_type, template_type):
build_response_as_excel(writer)
def get_template(template_type):
def get_template(template_type, company):
fields = [
"Account Name",
"Parent Account",
@@ -335,34 +333,17 @@ def get_template(template_type):
["", "", "", "", 0, account_type.get("account_type"), account_type.get("root_type")]
)
else:
writer = get_sample_template(writer)
writer = get_sample_template(writer, company)
return writer
def get_sample_template(writer):
template = [
["Application Of Funds(Assets)", "", "", "", 1, "", "Asset"],
["Sources Of Funds(Liabilities)", "", "", "", 1, "", "Liability"],
["Equity", "", "", "", 1, "", "Equity"],
["Expenses", "", "", "", 1, "", "Expense"],
["Income", "", "", "", 1, "", "Income"],
["Bank Accounts", "Application Of Funds(Assets)", "", "", 1, "Bank", "Asset"],
["Cash In Hand", "Application Of Funds(Assets)", "", "", 1, "Cash", "Asset"],
["Stock Assets", "Application Of Funds(Assets)", "", "", 1, "Stock", "Asset"],
["Cost Of Goods Sold", "Expenses", "", "", 0, "Cost of Goods Sold", "Expense"],
["Asset Depreciation", "Expenses", "", "", 0, "Depreciation", "Expense"],
["Fixed Assets", "Application Of Funds(Assets)", "", "", 0, "Fixed Asset", "Asset"],
["Accounts Payable", "Sources Of Funds(Liabilities)", "", "", 0, "Payable", "Liability"],
["Accounts Receivable", "Application Of Funds(Assets)", "", "", 1, "Receivable", "Asset"],
["Stock Expenses", "Expenses", "", "", 0, "Stock Adjustment", "Expense"],
["Sample Bank", "Bank Accounts", "", "", 0, "Bank", "Asset"],
["Cash", "Cash In Hand", "", "", 0, "Cash", "Asset"],
["Stores", "Stock Assets", "", "", 0, "Stock", "Asset"],
]
for row in template:
writer.writerow(row)
def get_sample_template(writer, company):
currency = frappe.db.get_value("Company", company, "default_currency")
with open(os.path.join(os.path.dirname(__file__), "coa_sample_template.csv"), "r") as f:
for row in f:
row = row.strip().split(",") + [currency]
writer.writerow(row)
return writer
@@ -453,14 +434,11 @@ def get_mandatory_account_types():
def unset_existing_data(company):
linked = frappe.db.sql(
'''select fieldname from tabDocField
where fieldtype="Link" and options="Account" and parent="Company"''',
as_dict=True,
)
# remove accounts data from company
update_values = {d.fieldname: "" for d in linked}
fieldnames = get_linked_fields("Account").get("Company", {}).get("fieldname", [])
linked = [{"fieldname": name} for name in fieldnames]
update_values = {d.get("fieldname"): "" for d in linked}
frappe.db.set_value("Company", company, update_values, update_values)
# remove accounts data from various doctypes

View File

@@ -0,0 +1,17 @@
Application Of Funds(Assets),,,,1,,Asset
Sources Of Funds(Liabilities),,,,1,,Liability
Equity,,,,1,,Equity
Expenses,,,,1,Expense Account,Expense
Income,,,,1,Income Account,Income
Bank Accounts,Application Of Funds(Assets),,,1,Bank,Asset
Cash In Hand,Application Of Funds(Assets),,,1,Cash,Asset
Stock Assets,Application Of Funds(Assets),,,1,Stock,Asset
Cost Of Goods Sold,Expenses,,,0,Cost of Goods Sold,Expense
Asset Depreciation,Expenses,,,0,Depreciation,Expense
Fixed Assets,Application Of Funds(Assets),,,0,Fixed Asset,Asset
Accounts Payable,Sources Of Funds(Liabilities),,,0,Payable,Liability
Accounts Receivable,Application Of Funds(Assets),,,1,Receivable,Asset
Stock Expenses,Expenses,,,0,Stock Adjustment,Expense
Sample Bank,Bank Accounts,,,0,Bank,Asset
Cash,Cash In Hand,,,0,Cash,Asset
Stores,Stock Assets,,,0,Stock,Asset
1 Application Of Funds(Assets) 1 Asset
2 Sources Of Funds(Liabilities) 1 Liability
3 Equity 1 Equity
4 Expenses 1 Expense Account Expense
5 Income 1 Income Account Income
6 Bank Accounts Application Of Funds(Assets) 1 Bank Asset
7 Cash In Hand Application Of Funds(Assets) 1 Cash Asset
8 Stock Assets Application Of Funds(Assets) 1 Stock Asset
9 Cost Of Goods Sold Expenses 0 Cost of Goods Sold Expense
10 Asset Depreciation Expenses 0 Depreciation Expense
11 Fixed Assets Application Of Funds(Assets) 0 Fixed Asset Asset
12 Accounts Payable Sources Of Funds(Liabilities) 0 Payable Liability
13 Accounts Receivable Application Of Funds(Assets) 1 Receivable Asset
14 Stock Expenses Expenses 0 Stock Adjustment Expense
15 Sample Bank Bank Accounts 0 Bank Asset
16 Cash Cash In Hand 0 Cash Asset
17 Stores Stock Assets 0 Stock Asset

View File

@@ -51,7 +51,7 @@ frappe.ui.form.on("Journal Entry", {
}, __('Make'));
}
erpnext.accounts.unreconcile_payments.add_unreconcile_btn(frm);
erpnext.accounts.unreconcile_payment.add_unreconcile_btn(frm);
},
before_save: function(frm) {
if ((frm.doc.docstatus == 0) && (!frm.doc.is_system_generated)) {

View File

@@ -548,8 +548,16 @@
"icon": "fa fa-file-text",
"idx": 176,
"is_submittable": 1,
"links": [],
"modified": "2023-08-10 14:32:22.366895",
"links": [
{
"is_child_table": 1,
"link_doctype": "Bank Transaction Payments",
"link_fieldname": "payment_entry",
"parent_doctype": "Bank Transaction",
"table_fieldname": "payment_entries"
}
],
"modified": "2023-11-23 12:11:04.128015",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry",

View File

@@ -496,7 +496,7 @@ class JournalEntry(AccountsController):
).format(d.reference_name, d.account)
)
else:
dr_or_cr = "debit" if d.credit > 0 else "credit"
dr_or_cr = "debit" if flt(d.credit) > 0 else "credit"
valid = False
for jvd in against_entries:
if flt(jvd[dr_or_cr]) > 0:

View File

@@ -203,7 +203,8 @@
"fieldtype": "Select",
"label": "Reference Type",
"no_copy": 1,
"options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset\nLoan\nPayroll Entry\nEmployee Advance\nExchange Rate Revaluation\nInvoice Discounting\nFees\nFull and Final Statement\nPayment Entry"
"options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset\nLoan\nPayroll Entry\nEmployee Advance\nExchange Rate Revaluation\nInvoice Discounting\nFees\nFull and Final Statement\nPayment Entry",
"search_index": 1
},
{
"fieldname": "reference_name",
@@ -211,7 +212,8 @@
"in_list_view": 1,
"label": "Reference Name",
"no_copy": 1,
"options": "reference_type"
"options": "reference_type",
"search_index": 1
},
{
"depends_on": "eval:doc.reference_type&&!in_list(doc.reference_type, ['Expense Claim', 'Asset', 'Employee Loan', 'Employee Advance'])",
@@ -278,13 +280,14 @@
"fieldtype": "Data",
"hidden": 1,
"label": "Reference Detail No",
"no_copy": 1
"no_copy": 1,
"search_index": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2023-06-16 14:11:13.507807",
"modified": "2023-11-23 11:44:25.841187",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry Account",

View File

@@ -7,7 +7,7 @@ cur_frm.cscript.tax_table = "Advance Taxes and Charges";
frappe.ui.form.on('Payment Entry', {
onload: function(frm) {
frm.ignore_doctypes_on_cancel_all = ['Sales Invoice', 'Purchase Invoice', 'Journal Entry', 'Repost Payment Ledger','Repost Accounting Ledger', 'Unreconcile Payments', 'Unreconcile Payment Entries'];
frm.ignore_doctypes_on_cancel_all = ['Sales Invoice', 'Purchase Invoice', 'Journal Entry', 'Repost Payment Ledger','Repost Accounting Ledger', 'Unreconcile Payment', 'Unreconcile Payment Entries'];
if(frm.doc.__islocal) {
if (!frm.doc.paid_from) frm.set_value("paid_from_account_currency", null);
@@ -152,13 +152,13 @@ frappe.ui.form.on('Payment Entry', {
frm.events.hide_unhide_fields(frm);
frm.events.set_dynamic_labels(frm);
frm.events.show_general_ledger(frm);
if(frm.doc.references.find((elem) => {return elem.exchange_gain_loss != 0})) {
if((frm.doc.references) && (frm.doc.references.find((elem) => {return elem.exchange_gain_loss != 0}))) {
frm.add_custom_button(__("View Exchange Gain/Loss Journals"), function() {
frappe.set_route("List", "Journal Entry", {"voucher_type": "Exchange Gain Or Loss", "reference_name": frm.doc.name});
}, __('Actions'));
}
erpnext.accounts.unreconcile_payments.add_unreconcile_btn(frm);
erpnext.accounts.unreconcile_payment.add_unreconcile_btn(frm);
},
validate_company: (frm) => {
@@ -829,7 +829,6 @@ frappe.ui.form.on('Payment Entry', {
else
total_negative_outstanding += Math.abs(flt(row.outstanding_amount));
})
var allocated_negative_outstanding = 0;
if (
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
@@ -844,6 +843,7 @@ frappe.ui.form.on('Payment Entry', {
var allocated_positive_outstanding = paid_amount + allocated_negative_outstanding;
} else if (in_list(["Customer", "Supplier"], frm.doc.party_type)) {
total_negative_outstanding = flt(total_negative_outstanding, precision("outstanding_amount"))
if(paid_amount > total_negative_outstanding) {
if(total_negative_outstanding == 0) {
frappe.msgprint(

View File

@@ -739,8 +739,16 @@
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2023-06-19 11:38:04.387219",
"links": [
{
"is_child_table": 1,
"link_doctype": "Bank Transaction Payments",
"link_fieldname": "payment_entry",
"parent_doctype": "Bank Transaction",
"table_fieldname": "payment_entries"
}
],
"modified": "2023-11-23 12:07:20.887885",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
@@ -786,4 +794,4 @@
"states": [],
"title_field": "title",
"track_changes": 1
}
}

View File

@@ -107,7 +107,7 @@ class PaymentEntry(AccountsController):
"Repost Payment Ledger Items",
"Repost Accounting Ledger",
"Repost Accounting Ledger Items",
"Unreconcile Payments",
"Unreconcile Payment",
"Unreconcile Payment Entries",
)
super(PaymentEntry, self).on_cancel()
@@ -913,8 +913,11 @@ class PaymentEntry(AccountsController):
):
return
total_negative_outstanding = sum(
abs(flt(d.outstanding_amount)) for d in self.get("references") if flt(d.outstanding_amount) < 0
total_negative_outstanding = flt(
sum(
abs(flt(d.outstanding_amount)) for d in self.get("references") if flt(d.outstanding_amount) < 0
),
self.references[0].precision("outstanding_amount") if self.references else None,
)
paid_amount = self.paid_amount if self.payment_type == "Receive" else self.received_amount
@@ -1549,13 +1552,42 @@ def get_outstanding_reference_documents(args):
return data
def split_invoices_based_on_payment_terms(outstanding_invoices, company):
invoice_ref_based_on_payment_terms = {}
def split_invoices_based_on_payment_terms(outstanding_invoices, company) -> list:
"""Split a list of invoices based on their payment terms."""
exc_rates = get_currency_data(outstanding_invoices, company)
outstanding_invoices_after_split = []
for entry in outstanding_invoices:
if entry.voucher_type in ["Sales Invoice", "Purchase Invoice"]:
if payment_term_template := frappe.db.get_value(
entry.voucher_type, entry.voucher_no, "payment_terms_template"
):
split_rows = get_split_invoice_rows(entry, payment_term_template, exc_rates)
if not split_rows:
continue
frappe.msgprint(
_("Splitting {0} {1} into {2} rows as per Payment Terms").format(
_(entry.voucher_type), frappe.bold(entry.voucher_no), len(split_rows)
),
alert=True,
)
outstanding_invoices_after_split += split_rows
continue
# If not an invoice or no payment terms template, add as it is
outstanding_invoices_after_split.append(entry)
return outstanding_invoices_after_split
def get_currency_data(outstanding_invoices: list, company: str = None) -> dict:
"""Get currency and conversion data for a list of invoices."""
exc_rates = frappe._dict()
company_currency = (
frappe.db.get_value("Company", company, "default_currency") if company else None
)
exc_rates = frappe._dict()
for doctype in ["Sales Invoice", "Purchase Invoice"]:
invoices = [x.voucher_no for x in outstanding_invoices if x.voucher_type == doctype]
for x in frappe.db.get_all(
@@ -1570,71 +1602,54 @@ def split_invoices_based_on_payment_terms(outstanding_invoices, company):
company_currency=company_currency,
)
for idx, d in enumerate(outstanding_invoices):
if d.voucher_type in ["Sales Invoice", "Purchase Invoice"]:
payment_term_template = frappe.db.get_value(
d.voucher_type, d.voucher_no, "payment_terms_template"
return exc_rates
def get_split_invoice_rows(invoice: dict, payment_term_template: str, exc_rates: dict) -> list:
"""Split invoice based on its payment schedule table."""
split_rows = []
allocate_payment_based_on_payment_terms = frappe.db.get_value(
"Payment Terms Template", payment_term_template, "allocate_payment_based_on_payment_terms"
)
if not allocate_payment_based_on_payment_terms:
return [invoice]
payment_schedule = frappe.get_all(
"Payment Schedule", filters={"parent": invoice.voucher_no}, fields=["*"], order_by="due_date"
)
for payment_term in payment_schedule:
if not payment_term.outstanding > 0.1:
continue
doc_details = exc_rates.get(payment_term.parent, None)
is_multi_currency_acc = (doc_details.currency != doc_details.company_currency) and (
doc_details.party_account_currency != doc_details.company_currency
)
payment_term_outstanding = flt(payment_term.outstanding)
if not is_multi_currency_acc:
payment_term_outstanding = doc_details.conversion_rate * flt(payment_term.outstanding)
split_rows.append(
frappe._dict(
{
"due_date": invoice.due_date,
"currency": invoice.currency,
"voucher_no": invoice.voucher_no,
"voucher_type": invoice.voucher_type,
"posting_date": invoice.posting_date,
"invoice_amount": flt(invoice.invoice_amount),
"outstanding_amount": payment_term_outstanding
if payment_term_outstanding
else invoice.outstanding_amount,
"payment_term_outstanding": payment_term_outstanding,
"payment_amount": payment_term.payment_amount,
"payment_term": payment_term.payment_term,
}
)
if payment_term_template:
allocate_payment_based_on_payment_terms = frappe.db.get_value(
"Payment Terms Template", payment_term_template, "allocate_payment_based_on_payment_terms"
)
if allocate_payment_based_on_payment_terms:
payment_schedule = frappe.get_all(
"Payment Schedule", filters={"parent": d.voucher_no}, fields=["*"]
)
)
for payment_term in payment_schedule:
if payment_term.outstanding > 0.1:
doc_details = exc_rates.get(payment_term.parent, None)
is_multi_currency_acc = (doc_details.currency != doc_details.company_currency) and (
doc_details.party_account_currency != doc_details.company_currency
)
payment_term_outstanding = flt(payment_term.outstanding)
if not is_multi_currency_acc:
payment_term_outstanding = doc_details.conversion_rate * flt(payment_term.outstanding)
invoice_ref_based_on_payment_terms.setdefault(idx, [])
invoice_ref_based_on_payment_terms[idx].append(
frappe._dict(
{
"due_date": d.due_date,
"currency": d.currency,
"voucher_no": d.voucher_no,
"voucher_type": d.voucher_type,
"posting_date": d.posting_date,
"invoice_amount": flt(d.invoice_amount),
"outstanding_amount": payment_term_outstanding
if payment_term_outstanding
else d.outstanding_amount,
"payment_term_outstanding": payment_term_outstanding,
"payment_amount": payment_term.payment_amount,
"payment_term": payment_term.payment_term,
}
)
)
outstanding_invoices_after_split = []
if invoice_ref_based_on_payment_terms:
for idx, ref in invoice_ref_based_on_payment_terms.items():
voucher_no = ref[0]["voucher_no"]
voucher_type = ref[0]["voucher_type"]
frappe.msgprint(
_("Spliting {} {} into {} row(s) as per Payment Terms").format(
voucher_type, voucher_no, len(ref)
),
alert=True,
)
outstanding_invoices_after_split += invoice_ref_based_on_payment_terms[idx]
existing_row = list(filter(lambda x: x.get("voucher_no") == voucher_no, outstanding_invoices))
index = outstanding_invoices.index(existing_row[0])
outstanding_invoices.pop(index)
outstanding_invoices_after_split += outstanding_invoices
return outstanding_invoices_after_split
return split_rows
def get_orders_to_be_billed(

View File

@@ -1,15 +1,17 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import json
import unittest
import frappe
from frappe import qb
from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import flt, nowdate
from frappe.utils import add_days, flt, nowdate
from erpnext.accounts.doctype.payment_entry.payment_entry import (
InvalidPaymentEntry,
get_outstanding_reference_documents,
get_payment_entry,
get_reference_details,
)
@@ -21,6 +23,7 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import (
create_sales_invoice,
create_sales_invoice_against_cost_center,
)
from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
from erpnext.setup.doctype.employee.test_employee import make_employee
@@ -1219,6 +1222,115 @@ class TestPaymentEntry(FrappeTestCase):
so.reload()
self.assertEqual(so.advance_paid, so.rounded_total)
def test_outstanding_invoices_api(self):
"""
Test if `get_outstanding_reference_documents` fetches invoices in the right order.
"""
customer = create_customer("Max Mustermann", "INR")
create_payment_terms_template()
# SI has an earlier due date and SI2 has a later due date
si = create_sales_invoice(
qty=1, rate=100, customer=customer, posting_date=add_days(nowdate(), -4)
)
si2 = create_sales_invoice(do_not_save=1, qty=1, rate=100, customer=customer)
si2.payment_terms_template = "Test Receivable Template"
si2.submit()
args = {
"posting_date": nowdate(),
"company": "_Test Company",
"party_type": "Customer",
"payment_type": "Pay",
"party": customer,
"party_account": "Debtors - _TC",
}
args.update(
{
"get_outstanding_invoices": True,
"from_posting_date": add_days(nowdate(), -4),
"to_posting_date": add_days(nowdate(), 2),
}
)
references = get_outstanding_reference_documents(args)
self.assertEqual(len(references), 3)
self.assertEqual(references[0].voucher_no, si.name)
self.assertEqual(references[1].voucher_no, si2.name)
self.assertEqual(references[2].voucher_no, si2.name)
self.assertEqual(references[1].payment_term, "Basic Amount Receivable")
self.assertEqual(references[2].payment_term, "Tax Receivable")
def test_partial_cancel_for_payment_entry(self):
si = create_sales_invoice()
pe = get_payment_entry(si.doctype, si.name)
pe.save()
pe.submit()
# Additional GL Entry
tax_amount = 10
reference_row = pe.references[0]
gl_args = {
"party_type": pe.party_type,
"party": pe.party,
"against_voucher_type": reference_row.reference_doctype,
"against_voucher": reference_row.reference_name,
"voucher_detail_no": reference_row.name,
}
gl_dicts = []
gl_dicts.extend(
[
pe.get_gl_dict(
{
"account": pe.paid_to,
"credit": tax_amount,
"credit_in_account_currency": tax_amount,
**gl_args,
}
),
pe.get_gl_dict(
{
"account": pe.paid_from,
"debit": tax_amount,
"debit_in_account_currency": tax_amount,
**gl_args,
}
),
]
)
make_gl_entries(gl_dicts)
# Assert PLEs Before
self.assertPLEntries(
pe,
[
{"amount": -100.0, "against_voucher_no": si.name},
{"amount": 10.0, "against_voucher_no": si.name},
],
)
# Partially cancel Payment Entry
make_reverse_gl_entries(gl_dicts, partial_cancel=True)
self.assertPLEntries(pe, [{"amount": -100.0, "against_voucher_no": si.name}])
def assertPLEntries(self, payment_doc, expected_pl_entries):
pl_entries = frappe.get_all(
"Payment Ledger Entry",
filters={
"voucher_type": payment_doc.doctype,
"voucher_no": payment_doc.name,
"delinked": 0,
},
fields=["amount", "against_voucher_no"],
)
out_str = json.dumps(sorted(pl_entries, key=json.dumps))
expected_out_str = json.dumps(sorted(expected_pl_entries, key=json.dumps))
self.assertEqual(out_str, expected_out_str)
def create_payment_entry(**args):
payment_entry = frappe.new_doc("Payment Entry")
@@ -1279,6 +1391,9 @@ def create_payment_terms_template():
def create_payment_terms_template_with_discount(
name=None, discount_type=None, discount=None, template_name=None
):
"""
Create a Payment Terms Template with % or amount discount.
"""
create_payment_term(name or "30 Credit Days with 10% Discount")
template_name = template_name or "Test Discount Template"

View File

@@ -13,6 +13,7 @@
"party_type",
"party",
"due_date",
"voucher_detail_no",
"cost_center",
"finance_book",
"voucher_type",
@@ -64,7 +65,8 @@
"fieldtype": "Link",
"in_standard_filter": 1,
"label": "Voucher Type",
"options": "DocType"
"options": "DocType",
"search_index": 1
},
{
"fieldname": "voucher_no",
@@ -72,14 +74,16 @@
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Voucher No",
"options": "voucher_type"
"options": "voucher_type",
"search_index": 1
},
{
"fieldname": "against_voucher_type",
"fieldtype": "Link",
"in_standard_filter": 1,
"label": "Against Voucher Type",
"options": "DocType"
"options": "DocType",
"search_index": 1
},
{
"fieldname": "against_voucher_no",
@@ -87,7 +91,8 @@
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Against Voucher No",
"options": "against_voucher_type"
"options": "against_voucher_type",
"search_index": 1
},
{
"fieldname": "amount",
@@ -143,12 +148,18 @@
"fieldname": "remarks",
"fieldtype": "Text",
"label": "Remarks"
},
{
"fieldname": "voucher_detail_no",
"fieldtype": "Data",
"label": "Voucher Detail No",
"search_index": 1
}
],
"in_create": 1,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-10-30 16:15:00.470283",
"modified": "2023-11-08 10:53:10.664896",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Ledger Entry",

View File

@@ -93,6 +93,8 @@ class PaymentReconciliation(Document):
"t2.against_account like %(bank_cash_account)s" if self.bank_cash_account else "1=1"
)
limit = f"limit {self.payment_limit}" if self.payment_limit else " "
# nosemgrep
journal_entries = frappe.db.sql(
"""
@@ -116,11 +118,13 @@ class PaymentReconciliation(Document):
ELSE {bank_account_condition}
END)
order by t1.posting_date
{limit}
""".format(
**{
"dr_or_cr": dr_or_cr,
"bank_account_condition": bank_account_condition,
"condition": condition,
"limit": limit,
}
),
{
@@ -146,7 +150,7 @@ class PaymentReconciliation(Document):
if self.payment_name:
conditions.append(doc.name.like(f"%{self.payment_name}%"))
self.return_invoices = (
self.return_invoices_query = (
qb.from_(doc)
.select(
ConstantColumn(voucher_type).as_("voucher_type"),
@@ -154,8 +158,11 @@ class PaymentReconciliation(Document):
doc.return_against,
)
.where(Criterion.all(conditions))
.run(as_dict=True)
)
if self.payment_limit:
self.return_invoices_query = self.return_invoices_query.limit(self.payment_limit)
self.return_invoices = self.return_invoices_query.run(as_dict=True)
def get_dr_or_cr_notes(self):

View File

@@ -1137,6 +1137,40 @@ class TestPaymentReconciliation(FrappeTestCase):
self.assertEqual(pay.unallocated_amount, 1000)
self.assertEqual(pay.difference_amount, 0)
def test_rounding_of_unallocated_amount(self):
self.supplier = "_Test Supplier USD"
pi = self.create_purchase_invoice(qty=1, rate=10, do_not_submit=True)
pi.supplier = self.supplier
pi.currency = "USD"
pi.conversion_rate = 80
pi.credit_to = self.creditors_usd
pi.save().submit()
pe = get_payment_entry(pi.doctype, pi.name)
pe.target_exchange_rate = 78.726500000
pe.received_amount = 26.75
pe.paid_amount = 2105.93
pe.references = []
pe.save().submit()
# unallocated_amount will have some rounding loss - 26.749950
self.assertNotEqual(pe.unallocated_amount, 26.75)
pr = frappe.get_doc("Payment Reconciliation")
pr.company = self.company
pr.party_type = "Supplier"
pr.party = self.supplier
pr.receivable_payable_account = self.creditors_usd
pr.from_invoice_date = pr.to_invoice_date = pr.from_payment_date = pr.to_payment_date = nowdate()
pr.get_unreconciled_entries()
invoices = [invoice.as_dict() for invoice in pr.invoices]
payments = [payment.as_dict() for payment in pr.payments]
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
# Should not raise frappe.exceptions.ValidationError: Payment Entry has been modified after you pulled it. Please pull it again.
pr.reconcile()
def make_customer(customer_name, currency=None):
if not frappe.db.exists("Customer", customer_name):

View File

@@ -18,6 +18,7 @@
"is_pos",
"is_return",
"update_billed_amount_in_sales_order",
"update_billed_amount_in_delivery_note",
"column_break1",
"company",
"posting_date",
@@ -1549,12 +1550,19 @@
"fieldtype": "Currency",
"label": "Amount Eligible for Commission",
"read_only": 1
},
{
"default": "1",
"depends_on": "eval: doc.is_return && doc.return_against",
"fieldname": "update_billed_amount_in_delivery_note",
"fieldtype": "Check",
"label": "Update Billed Amount in Delivery Note"
}
],
"icon": "fa fa-file-text",
"is_submittable": 1,
"links": [],
"modified": "2022-09-30 03:49:50.455199",
"modified": "2023-11-20 12:27:12.848149",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Invoice",

View File

@@ -659,7 +659,7 @@ def get_stock_availability(item_code, warehouse):
return bin_qty - pos_sales_qty, is_stock_item
else:
is_stock_item = True
if frappe.db.exists("Product Bundle", item_code):
if frappe.db.exists("Product Bundle", {"name": item_code, "disabled": 0}):
return get_bundle_availability(item_code, warehouse), is_stock_item
else:
is_stock_item = False

View File

@@ -185,6 +185,7 @@
"label": "Image"
},
{
"fetch_from": "item_code.image",
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
@@ -821,7 +822,7 @@
],
"istable": 1,
"links": [],
"modified": "2022-11-02 12:52:39.125295",
"modified": "2023-11-14 18:33:22.585715",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Invoice Item",
@@ -831,4 +832,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -110,7 +110,7 @@
"in_create": 1,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-04-21 17:36:26.642617",
"modified": "2023-11-02 11:32:12.254018",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Process Payment Reconciliation Log",
@@ -125,7 +125,19 @@
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"role": "Accounts Manager",
"share": 1,
"write": 1
},
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"share": 1,
"write": 1
}

View File

@@ -181,7 +181,7 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
}
this.frm.set_df_property("tax_withholding_category", "hidden", doc.apply_tds ? 0 : 1);
erpnext.accounts.unreconcile_payments.add_unreconcile_btn(me.frm);
erpnext.accounts.unreconcile_payment.add_unreconcile_btn(me.frm);
}
unblock_invoice() {

View File

@@ -383,7 +383,8 @@
"label": "Supplier Invoice No",
"oldfieldname": "bill_no",
"oldfieldtype": "Data",
"print_hide": 1
"print_hide": 1,
"search_index": 1
},
{
"fieldname": "column_break_15",
@@ -406,7 +407,8 @@
"no_copy": 1,
"options": "Purchase Invoice",
"print_hide": 1,
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "section_addresses",
@@ -1592,7 +1594,7 @@
"idx": 204,
"is_submittable": 1,
"links": [],
"modified": "2023-10-16 16:24:51.886231",
"modified": "2023-11-03 15:47:30.319200",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",

View File

@@ -13,6 +13,7 @@ from erpnext.accounts.deferred_revenue import validate_service_stop_date
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import (
validate_docs_for_deferred_accounting,
validate_docs_for_voucher_types,
)
from erpnext.accounts.doctype.sales_invoice.sales_invoice import (
check_if_return_invoice_linked_with_payment_entry,
@@ -494,6 +495,7 @@ class PurchaseInvoice(BuyingController):
def validate_for_repost(self):
self.validate_write_off_account()
self.validate_expense_account()
validate_docs_for_voucher_types(["Purchase Invoice"])
validate_docs_for_deferred_accounting([], [self.name])
def on_submit(self):
@@ -532,7 +534,11 @@ class PurchaseInvoice(BuyingController):
if self.update_stock == 1:
self.repost_future_sle_and_gle()
self.update_project()
if (
frappe.db.get_single_value("Buying Settings", "project_update_frequency") == "Each Transaction"
):
self.update_project()
update_linked_doc(self.doctype, self.name, self.inter_company_invoice_reference)
self.update_advance_tax_references()
@@ -1269,7 +1275,10 @@ class PurchaseInvoice(BuyingController):
if self.update_stock == 1:
self.repost_future_sle_and_gle()
self.update_project()
if (
frappe.db.get_single_value("Buying Settings", "project_update_frequency") == "Each Transaction"
):
self.update_project()
self.db_set("status", "Cancelled")
unlink_inter_company_doc(self.doctype, self.name, self.inter_company_invoice_reference)
@@ -1287,13 +1296,21 @@ class PurchaseInvoice(BuyingController):
self.update_advance_tax_references(cancel=1)
def update_project(self):
project_list = []
projects = frappe._dict()
for d in self.items:
if d.project and d.project not in project_list:
project = frappe.get_doc("Project", d.project)
project.update_purchase_costing()
project.db_update()
project_list.append(d.project)
if d.project:
if self.docstatus == 1:
projects[d.project] = projects.get(d.project, 0) + d.base_net_amount
elif self.docstatus == 2:
projects[d.project] = projects.get(d.project, 0) - d.base_net_amount
pj = frappe.qb.DocType("Project")
for proj, value in projects.items():
res = (
frappe.qb.from_(pj).select(pj.total_purchase_cost).where(pj.name == proj).for_update().run()
)
current_purchase_cost = res and res[0][0] or 0
frappe.db.set_value("Project", proj, "total_purchase_cost", current_purchase_cost + value)
def validate_supplier_invoice(self):
if self.bill_date:

View File

@@ -1718,9 +1718,14 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
self.assertTrue(return_pi.docstatus == 1)
def test_gl_entries_for_standalone_debit_note(self):
make_purchase_invoice(qty=5, rate=500, update_stock=True)
from erpnext.stock.doctype.item.test_item import make_item
returned_inv = make_purchase_invoice(qty=-5, rate=5, update_stock=True, is_return=True)
item_code = make_item(properties={"is_stock_item": 1})
make_purchase_invoice(item_code=item_code, qty=5, rate=500, update_stock=True)
returned_inv = make_purchase_invoice(
item_code=item_code, qty=-5, rate=5, update_stock=True, is_return=True
)
# override the rate with valuation rate
sle = frappe.get_all(
@@ -1730,7 +1735,7 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
)[0]
rate = flt(sle.stock_value_difference) / flt(sle.actual_qty)
self.assertAlmostEqual(returned_inv.items[0].rate, rate)
self.assertAlmostEqual(rate, 500)
def test_payment_allocation_for_payment_terms(self):
from erpnext.buying.doctype.purchase_order.test_purchase_order import (
@@ -1833,6 +1838,12 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
disable_dimension()
def test_repost_accounting_entries(self):
# update repost settings
settings = frappe.get_doc("Repost Accounting Ledger Settings")
if not [x for x in settings.allowed_types if x.document_type == "Purchase Invoice"]:
settings.append("allowed_types", {"document_type": "Purchase Invoice", "allowed": True})
settings.save()
pi = make_purchase_invoice(
rate=1000,
price_list_rate=1000,

View File

@@ -156,6 +156,7 @@
"width": "300px"
},
{
"fetch_from": "item_code.image",
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
@@ -491,6 +492,7 @@
"fieldtype": "Column Break"
},
{
"allow_on_submit": 1,
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
@@ -498,6 +500,7 @@
"print_hide": 1
},
{
"allow_on_submit": 1,
"default": ":Company",
"depends_on": "eval:!doc.is_fixed_asset",
"fieldname": "cost_center",
@@ -890,7 +893,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2023-10-03 21:01:01.824892",
"modified": "2023-11-14 18:33:48.547297",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@@ -5,9 +5,7 @@ frappe.ui.form.on("Repost Accounting Ledger", {
setup: function(frm) {
frm.fields_dict['vouchers'].grid.get_field('voucher_type').get_query = function(doc) {
return {
filters: {
name: ['in', ['Purchase Invoice', 'Sales Invoice', 'Payment Entry', 'Journal Entry']],
}
query: "erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger.get_repost_allowed_types"
}
}

View File

@@ -10,9 +10,7 @@ from frappe.utils.data import comma_and
class RepostAccountingLedger(Document):
def __init__(self, *args, **kwargs):
super(RepostAccountingLedger, self).__init__(*args, **kwargs)
self._allowed_types = set(
["Purchase Invoice", "Sales Invoice", "Payment Entry", "Journal Entry"]
)
self._allowed_types = get_allowed_types_from_settings()
def validate(self):
self.validate_vouchers()
@@ -53,15 +51,7 @@ class RepostAccountingLedger(Document):
def validate_vouchers(self):
if self.vouchers:
# Validate voucher types
voucher_types = set([x.voucher_type for x in self.vouchers])
if disallowed_types := voucher_types.difference(self._allowed_types):
frappe.throw(
_("{0} types are not allowed. Only {1} are.").format(
frappe.bold(comma_and(list(disallowed_types))),
frappe.bold(comma_and(list(self._allowed_types))),
)
)
validate_docs_for_voucher_types([x.voucher_type for x in self.vouchers])
def get_existing_ledger_entries(self):
vouchers = [x.voucher_no for x in self.vouchers]
@@ -157,7 +147,7 @@ def start_repost(account_repost_doc=str) -> None:
doc.docstatus = 1
doc.make_gl_entries()
elif doc.doctype in ["Payment Entry", "Journal Entry"]:
elif doc.doctype in ["Payment Entry", "Journal Entry", "Expense Claim"]:
if not repost_doc.delete_cancelled_entries:
doc.make_gl_entries(1)
doc.make_gl_entries()
@@ -165,6 +155,15 @@ def start_repost(account_repost_doc=str) -> None:
frappe.db.commit()
def get_allowed_types_from_settings():
return [
x.document_type
for x in frappe.db.get_all(
"Repost Allowed Types", filters={"allowed": True}, fields=["distinct(document_type)"]
)
]
def validate_docs_for_deferred_accounting(sales_docs, purchase_docs):
docs_with_deferred_revenue = frappe.db.get_all(
"Sales Invoice Item",
@@ -186,3 +185,37 @@ def validate_docs_for_deferred_accounting(sales_docs, purchase_docs):
frappe.bold(comma_and([x[0] for x in docs_with_deferred_expense + docs_with_deferred_revenue]))
)
)
def validate_docs_for_voucher_types(doc_voucher_types):
allowed_types = get_allowed_types_from_settings()
# Validate voucher types
voucher_types = set(doc_voucher_types)
if disallowed_types := voucher_types.difference(allowed_types):
message = "are" if len(disallowed_types) > 1 else "is"
frappe.throw(
_("{0} {1} not allowed to be reposted. Modify {2} to enable reposting.").format(
frappe.bold(comma_and(list(disallowed_types))),
message,
frappe.bold(
frappe.utils.get_link_to_form(
"Repost Accounting Ledger Settings", "Repost Accounting Ledger Settings"
)
),
)
)
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_repost_allowed_types(doctype, txt, searchfield, start, page_len, filters):
filters = {"allowed": True}
if txt:
filters.update({"document_type": ("like", f"%{txt}%")})
if allowed_types := frappe.db.get_all(
"Repost Allowed Types", filters=filters, fields=["distinct(document_type)"], as_list=1
):
return allowed_types
return []

View File

@@ -20,10 +20,18 @@ class TestRepostAccountingLedger(AccountsTestMixin, FrappeTestCase):
self.create_company()
self.create_customer()
self.create_item()
self.update_repost_settings()
def teadDown(self):
frappe.db.rollback()
def update_repost_settings(self):
allowed_types = ["Sales Invoice", "Purchase Invoice", "Payment Entry", "Journal Entry"]
repost_settings = frappe.get_doc("Repost Accounting Ledger Settings")
for x in allowed_types:
repost_settings.append("allowed_types", {"document_type": x, "allowed": True})
repost_settings.save()
def test_01_basic_functions(self):
si = create_sales_invoice(
item=self.item,

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Repost Accounting Ledger Settings", {
// refresh(frm) {
// },
// });

View File

@@ -0,0 +1,46 @@
{
"actions": [],
"creation": "2023-11-07 09:57:20.619939",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"allowed_types"
],
"fields": [
{
"fieldname": "allowed_types",
"fieldtype": "Table",
"label": "Allowed Doctypes",
"options": "Repost Allowed Types"
}
],
"in_create": 1,
"issingle": 1,
"links": [],
"modified": "2023-11-07 14:24:13.321522",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Repost Accounting Ledger Settings",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "Administrator",
"share": 1,
"write": 1
},
{
"read": 1,
"role": "System Manager",
"select": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}

View File

@@ -0,0 +1,9 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class RepostAccountingLedgerSettings(Document):
pass

View File

@@ -0,0 +1,9 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestRepostAccountingLedgerSettings(FrappeTestCase):
pass

View File

@@ -0,0 +1,45 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2023-11-07 09:58:03.595382",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"document_type",
"column_break_sfzb",
"allowed"
],
"fields": [
{
"fieldname": "document_type",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Doctype",
"options": "DocType"
},
{
"default": "0",
"fieldname": "allowed",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Allowed"
},
{
"fieldname": "column_break_sfzb",
"fieldtype": "Column Break"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-11-07 10:01:39.217861",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Repost Allowed Types",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@@ -0,0 +1,9 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class RepostAllowedTypes(Document):
pass

View File

@@ -34,7 +34,7 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
super.onload();
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice', 'Timesheet', 'POS Invoice Merge Log',
'POS Closing Entry', 'Journal Entry', 'Payment Entry', "Repost Payment Ledger", "Repost Accounting Ledger", "Unreconcile Payments", "Unreconcile Payment Entries"];
'POS Closing Entry', 'Journal Entry', 'Payment Entry', "Repost Payment Ledger", "Repost Accounting Ledger", "Unreconcile Payment", "Unreconcile Payment Entries"];
if(!this.frm.doc.__islocal && !this.frm.doc.customer && this.frm.doc.debit_to) {
// show debit_to in print format
@@ -178,10 +178,9 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
}
}
erpnext.accounts.unreconcile_payments.add_unreconcile_btn(me.frm);
erpnext.accounts.unreconcile_payment.add_unreconcile_btn(me.frm);
}
make_maintenance_schedule() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_maintenance_schedule",
@@ -557,15 +556,6 @@ cur_frm.fields_dict.write_off_cost_center.get_query = function(doc) {
}
}
// Income Account in Details Table
// --------------------------------
cur_frm.set_query("income_account", "items", function(doc) {
return{
query: "erpnext.controllers.queries.get_income_account",
filters: {'company': doc.company}
}
});
// Cost Center in Details Table
// -----------------------------
cur_frm.fields_dict["items"].grid.get_field("cost_center").get_query = function(doc) {
@@ -660,6 +650,16 @@ frappe.ui.form.on('Sales Invoice', {
};
});
frm.set_query("income_account", "items", function() {
return{
query: "erpnext.controllers.queries.get_income_account",
filters: {
'company': frm.doc.company,
"disabled": 0
}
}
});
frm.custom_make_buttons = {
'Delivery Note': 'Delivery',
'Sales Invoice': 'Return / Credit Note',

View File

@@ -26,6 +26,7 @@
"is_return",
"return_against",
"update_billed_amount_in_sales_order",
"update_billed_amount_in_delivery_note",
"is_debit_note",
"amended_from",
"accounting_dimensions_section",
@@ -1612,7 +1613,8 @@
"hide_seconds": 1,
"label": "Inter Company Invoice Reference",
"options": "Purchase Invoice",
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "customer_group",
@@ -2144,6 +2146,13 @@
"fieldname": "use_company_roundoff_cost_center",
"fieldtype": "Check",
"label": "Use Company default Cost Center for Round off"
},
{
"default": "1",
"depends_on": "eval: doc.is_return",
"fieldname": "update_billed_amount_in_delivery_note",
"fieldtype": "Check",
"label": "Update Billed Amount in Delivery Note"
}
],
"icon": "fa fa-file-text",
@@ -2156,7 +2165,7 @@
"link_fieldname": "consolidated_invoice"
}
],
"modified": "2023-06-19 16:02:05.309332",
"modified": "2023-11-23 16:56:29.679499",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -17,6 +17,7 @@ from erpnext.accounts.doctype.loyalty_program.loyalty_program import (
)
from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import (
validate_docs_for_deferred_accounting,
validate_docs_for_voucher_types,
)
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import (
get_party_tax_withholding_details,
@@ -180,6 +181,7 @@ class SalesInvoice(SellingController):
self.validate_write_off_account()
self.validate_account_for_change_amount()
self.validate_income_account()
validate_docs_for_voucher_types(["Sales Invoice"])
validate_docs_for_deferred_accounting([self.name], [])
def validate_fixed_asset(self):
@@ -261,6 +263,7 @@ class SalesInvoice(SellingController):
self.update_status_updater_args()
self.update_prevdoc_status()
self.update_billing_status_in_dn()
self.clear_unallocated_mode_of_payments()
@@ -407,7 +410,7 @@ class SalesInvoice(SellingController):
"Repost Payment Ledger Items",
"Repost Accounting Ledger",
"Repost Accounting Ledger Items",
"Unreconcile Payments",
"Unreconcile Payment",
"Unreconcile Payment Entries",
"Payment Ledger Entry",
)
@@ -1036,7 +1039,7 @@ class SalesInvoice(SellingController):
def make_customer_gl_entry(self, gl_entries):
# Checked both rounding_adjustment and rounded_total
# because rounded_total had value even before introcution of posting GLE based on rounded total
# because rounded_total had value even before introduction of posting GLE based on rounded total
grand_total = (
self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
)
@@ -1271,7 +1274,7 @@ class SalesInvoice(SellingController):
if skip_change_gl_entries and payment_mode.account == self.account_for_change_amount:
payment_mode.base_amount -= flt(self.change_amount)
if payment_mode.amount:
if payment_mode.base_amount:
# POS, make payment entries
gl_entries.append(
self.get_gl_dict(
@@ -1433,6 +1436,8 @@ class SalesInvoice(SellingController):
)
def update_billing_status_in_dn(self, update_modified=True):
if self.is_return and not self.update_billed_amount_in_delivery_note:
return
updated_delivery_notes = []
for d in self.get("items"):
if d.dn_detail:

View File

@@ -782,6 +782,28 @@ class TestSalesInvoice(FrappeTestCase):
w = self.make()
self.assertEqual(w.outstanding_amount, w.base_rounded_total)
def test_rounded_total_with_cash_discount(self):
si = frappe.copy_doc(test_records[2])
item = copy.deepcopy(si.get("items")[0])
item.update(
{
"qty": 1,
"rate": 14960.66,
}
)
si.set("items", [item])
si.set("taxes", [])
si.apply_discount_on = "Grand Total"
si.is_cash_or_non_trade_discount = 1
si.discount_amount = 1
si.insert()
self.assertEqual(si.grand_total, 14959.66)
self.assertEqual(si.rounded_total, 14960)
self.assertEqual(si.rounding_adjustment, 0.34)
def test_payment(self):
w = self.make()

View File

@@ -167,6 +167,7 @@
"print_hide": 1
},
{
"fetch_from": "item_code.image",
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
@@ -891,7 +892,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2023-07-25 11:58:10.723833",
"modified": "2023-11-14 18:34:10.479329",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",
@@ -901,4 +902,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -10,7 +10,7 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
class TestUnreconcilePayments(AccountsTestMixin, FrappeTestCase):
class TestUnreconcilePayment(AccountsTestMixin, FrappeTestCase):
def setUp(self):
self.create_company()
self.create_customer()
@@ -73,7 +73,7 @@ class TestUnreconcilePayments(AccountsTestMixin, FrappeTestCase):
unreconcile = frappe.get_doc(
{
"doctype": "Unreconcile Payments",
"doctype": "Unreconcile Payment",
"company": self.company,
"voucher_type": pe.doctype,
"voucher_no": pe.name,
@@ -138,7 +138,7 @@ class TestUnreconcilePayments(AccountsTestMixin, FrappeTestCase):
unreconcile = frappe.get_doc(
{
"doctype": "Unreconcile Payments",
"doctype": "Unreconcile Payment",
"company": self.company,
"voucher_type": pe2.doctype,
"voucher_no": pe2.name,
@@ -196,7 +196,7 @@ class TestUnreconcilePayments(AccountsTestMixin, FrappeTestCase):
unreconcile = frappe.get_doc(
{
"doctype": "Unreconcile Payments",
"doctype": "Unreconcile Payment",
"company": self.company,
"voucher_type": pe.doctype,
"voucher_no": pe.name,
@@ -281,7 +281,7 @@ class TestUnreconcilePayments(AccountsTestMixin, FrappeTestCase):
unreconcile = frappe.get_doc(
{
"doctype": "Unreconcile Payments",
"doctype": "Unreconcile Payment",
"company": self.company,
"voucher_type": pe2.doctype,
"voucher_no": pe2.name,

View File

@@ -1,7 +1,7 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Unreconcile Payments", {
frappe.ui.form.on("Unreconcile Payment", {
refresh(frm) {
frm.set_query("voucher_type", function() {
return {

View File

@@ -21,7 +21,7 @@
"fieldtype": "Link",
"label": "Amended From",
"no_copy": 1,
"options": "Unreconcile Payments",
"options": "Unreconcile Payment",
"print_hide": 1,
"read_only": 1
},
@@ -61,7 +61,7 @@
"modified": "2023-08-28 17:42:50.261377",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Unreconcile Payments",
"name": "Unreconcile Payment",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
@@ -90,4 +90,4 @@
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
}

View File

@@ -15,7 +15,7 @@ from erpnext.accounts.utils import (
)
class UnreconcilePayments(Document):
class UnreconcilePayment(Document):
def validate(self):
self.supported_types = ["Payment Entry", "Journal Entry"]
if not self.voucher_type in self.supported_types:
@@ -142,7 +142,7 @@ def create_unreconcile_doc_for_selection(selections=None):
selections = frappe.json.loads(selections)
# assuming each row is a unique voucher
for row in selections:
unrecon = frappe.new_doc("Unreconcile Payments")
unrecon = frappe.new_doc("Unreconcile Payment")
unrecon.company = row.get("company")
unrecon.voucher_type = row.get("voucher_type")
unrecon.voucher_no = row.get("voucher_no")

View File

@@ -556,7 +556,12 @@ def get_round_off_account_and_cost_center(
def make_reverse_gl_entries(
gl_entries=None, voucher_type=None, voucher_no=None, adv_adj=False, update_outstanding="Yes"
gl_entries=None,
voucher_type=None,
voucher_no=None,
adv_adj=False,
update_outstanding="Yes",
partial_cancel=False,
):
"""
Get original gl entries of the voucher
@@ -576,14 +581,19 @@ def make_reverse_gl_entries(
if gl_entries:
create_payment_ledger_entry(
gl_entries, cancel=1, adv_adj=adv_adj, update_outstanding=update_outstanding
gl_entries,
cancel=1,
adv_adj=adv_adj,
update_outstanding=update_outstanding,
partial_cancel=partial_cancel,
)
validate_accounting_period(gl_entries)
check_freezing_date(gl_entries[0]["posting_date"], adv_adj)
is_opening = any(d.get("is_opening") == "Yes" for d in gl_entries)
validate_against_pcv(is_opening, gl_entries[0]["posting_date"], gl_entries[0]["company"])
set_as_cancel(gl_entries[0]["voucher_type"], gl_entries[0]["voucher_no"])
if not partial_cancel:
set_as_cancel(gl_entries[0]["voucher_type"], gl_entries[0]["voucher_no"])
for entry in gl_entries:
new_gle = copy.deepcopy(entry)

View File

@@ -31,7 +31,12 @@ from erpnext.accounts.utils import get_fiscal_year
from erpnext.exceptions import InvalidAccountCurrency, PartyDisabled, PartyFrozen
from erpnext.utilities.regional import temporary_flag
PURCHASE_TRANSACTION_TYPES = {"Purchase Order", "Purchase Receipt", "Purchase Invoice"}
PURCHASE_TRANSACTION_TYPES = {
"Supplier Quotation",
"Purchase Order",
"Purchase Receipt",
"Purchase Invoice",
}
SALES_TRANSACTION_TYPES = {
"Quotation",
"Sales Order",
@@ -231,7 +236,9 @@ def set_address_details(
if shipping_address:
party_details.update(
shipping_address=shipping_address,
shipping_address_display=render_address(shipping_address),
shipping_address_display=render_address(
shipping_address, check_permissions=not ignore_permissions
),
**get_fetch_values(doctype, "shipping_address", shipping_address)
)

View File

@@ -143,7 +143,18 @@ frappe.query_reports["Accounts Payable"] = {
"fieldname": "show_future_payments",
"label": __("Show Future Payments"),
"fieldtype": "Check",
},
{
"fieldname": "for_revaluation_journals",
"label": __("Revaluation Journals"),
"fieldtype": "Check",
},
{
"fieldname": "ignore_accounts",
"label": __("Group by Voucher"),
"fieldtype": "Check",
}
],
"formatter": function(value, row, column, data, default_formatter) {
@@ -175,4 +186,4 @@ function get_party_type_options() {
});
});
return options;
}
}

View File

@@ -110,6 +110,11 @@ frappe.query_reports["Accounts Payable Summary"] = {
"fieldname":"based_on_payment_terms",
"label": __("Based On Payment Terms"),
"fieldtype": "Check",
},
{
"fieldname": "for_revaluation_journals",
"label": __("Revaluation Journals"),
"fieldtype": "Check",
}
],

View File

@@ -114,10 +114,13 @@ frappe.query_reports["Accounts Receivable"] = {
"reqd": 1
},
{
"fieldname": "customer_group",
"fieldname":"customer_group",
"label": __("Customer Group"),
"fieldtype": "Link",
"options": "Customer Group"
"fieldtype": "MultiSelectList",
"options": "Customer Group",
get_data: function(txt) {
return frappe.db.get_link_options('Customer Group', txt);
}
},
{
"fieldname": "payment_terms_template",
@@ -172,7 +175,19 @@ frappe.query_reports["Accounts Receivable"] = {
"fieldname": "show_remarks",
"label": __("Show Remarks"),
"fieldtype": "Check",
},
{
"fieldname": "for_revaluation_journals",
"label": __("Revaluation Journals"),
"fieldtype": "Check",
},
{
"fieldname": "ignore_accounts",
"label": __("Group by Voucher"),
"fieldtype": "Check",
}
],
"formatter": function(value, row, column, data, default_formatter) {
@@ -205,4 +220,4 @@ function get_party_type_options() {
});
});
return options;
}
}

View File

@@ -7,7 +7,7 @@ from collections import OrderedDict
import frappe
from frappe import _, qb, scrub
from frappe.query_builder import Criterion
from frappe.query_builder.functions import Date, Sum
from frappe.query_builder.functions import Date, Substring, Sum
from frappe.utils import cint, cstr, flt, getdate, nowdate
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
@@ -116,7 +116,12 @@ class ReceivablePayableReport(object):
# build all keys, since we want to exclude vouchers beyond the report date
for ple in self.ple_entries:
# get the balance object for voucher_type
key = (ple.account, ple.voucher_type, ple.voucher_no, ple.party)
if self.filters.get("ignore_accounts"):
key = (ple.voucher_type, ple.voucher_no, ple.party)
else:
key = (ple.account, ple.voucher_type, ple.voucher_no, ple.party)
if not key in self.voucher_balance:
self.voucher_balance[key] = frappe._dict(
voucher_type=ple.voucher_type,
@@ -183,7 +188,10 @@ class ReceivablePayableReport(object):
):
return
key = (ple.account, ple.against_voucher_type, ple.against_voucher_no, ple.party)
if self.filters.get("ignore_accounts"):
key = (ple.against_voucher_type, ple.against_voucher_no, ple.party)
else:
key = (ple.account, ple.against_voucher_type, ple.against_voucher_no, ple.party)
# If payment is made against credit note
# and credit note is made against a Sales Invoice
@@ -192,13 +200,19 @@ class ReceivablePayableReport(object):
if ple.against_voucher_no in self.return_entries:
return_against = self.return_entries.get(ple.against_voucher_no)
if return_against:
key = (ple.account, ple.against_voucher_type, return_against, ple.party)
if self.filters.get("ignore_accounts"):
key = (ple.against_voucher_type, return_against, ple.party)
else:
key = (ple.account, ple.against_voucher_type, return_against, ple.party)
row = self.voucher_balance.get(key)
if not row:
# no invoice, this is an invoice / stand-alone payment / credit note
row = self.voucher_balance.get((ple.account, ple.voucher_type, ple.voucher_no, ple.party))
if self.filters.get("ignore_accounts"):
row = self.voucher_balance.get((ple.voucher_type, ple.voucher_no, ple.party))
else:
row = self.voucher_balance.get((ple.account, ple.voucher_type, ple.voucher_no, ple.party))
row.party_type = ple.party_type
return row
@@ -267,11 +281,20 @@ class ReceivablePayableReport(object):
row.invoice_grand_total = row.invoiced
if (abs(row.outstanding) > 1.0 / 10**self.currency_precision) and (
(abs(row.outstanding_in_account_currency) > 1.0 / 10**self.currency_precision)
or (row.voucher_no in self.err_journals)
):
must_consider = False
if self.filters.get("for_revaluation_journals"):
if (abs(row.outstanding) > 0.0 / 10**self.currency_precision) or (
(abs(row.outstanding_in_account_currency) > 0.0 / 10**self.currency_precision)
):
must_consider = True
else:
if (abs(row.outstanding) > 1.0 / 10**self.currency_precision) and (
(abs(row.outstanding_in_account_currency) > 1.0 / 10**self.currency_precision)
or (row.voucher_no in self.err_journals)
):
must_consider = True
if must_consider:
# non-zero oustanding, we must consider this row
if self.is_invoice(row) and self.filters.based_on_payment_terms:
@@ -718,6 +741,7 @@ class ReceivablePayableReport(object):
query = (
qb.from_(ple)
.select(
ple.name,
ple.account,
ple.voucher_type,
ple.voucher_no,
@@ -731,13 +755,20 @@ class ReceivablePayableReport(object):
ple.account_currency,
ple.amount,
ple.amount_in_account_currency,
ple.remarks,
)
.where(ple.delinked == 0)
.where(Criterion.all(self.qb_selection_filter))
.where(Criterion.any(self.or_filters))
)
if self.filters.get("show_remarks"):
if remarks_length := frappe.db.get_single_value(
"Accounts Settings", "receivable_payable_remarks_length"
):
query = query.select(Substring(ple.remarks, 1, remarks_length).as_("remarks"))
else:
query = query.select(ple.remarks)
if self.filters.get("group_by_party"):
query = query.orderby(self.ple.party, self.ple.posting_date)
else:
@@ -823,7 +854,13 @@ class ReceivablePayableReport(object):
self.customer = qb.DocType("Customer")
if self.filters.get("customer_group"):
self.get_hierarchical_filters("Customer Group", "customer_group")
groups = get_customer_group_with_children(self.filters.customer_group)
customers = (
qb.from_(self.customer)
.select(self.customer.name)
.where(self.customer["customer_group"].isin(groups))
)
self.qb_selection_filter.append(self.ple.party.isin(customers))
if self.filters.get("territory"):
self.get_hierarchical_filters("Territory", "territory")
@@ -1115,3 +1152,19 @@ class ReceivablePayableReport(object):
.run()
)
self.err_journals = [x[0] for x in results] if results else []
def get_customer_group_with_children(customer_groups):
if not isinstance(customer_groups, list):
customer_groups = [d.strip() for d in customer_groups.strip().split(",") if d]
all_customer_groups = []
for d in customer_groups:
if frappe.db.exists("Customer Group", d):
lft, rgt = frappe.db.get_value("Customer Group", d, ["lft", "rgt"])
children = frappe.get_all("Customer Group", filters={"lft": [">=", lft], "rgt": ["<=", rgt]})
all_customer_groups += [c.name for c in children]
else:
frappe.throw(_("Customer Group: {0} does not exist").format(d))
return list(set(all_customer_groups))

View File

@@ -475,6 +475,30 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
report = execute(filters)[1]
self.assertEqual(len(report), 0)
def test_multi_customer_group_filter(self):
si = self.create_sales_invoice()
cus_group = frappe.db.get_value("Customer", self.customer, "customer_group")
# Create a list of customer groups, e.g., ["Group1", "Group2"]
cus_groups_list = [cus_group, "_Test Customer Group 1"]
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"customer_group": cus_groups_list, # Use the list of customer groups
}
report = execute(filters)[1]
# Assert that the report contains data for the specified customer groups
self.assertTrue(len(report) > 0)
for row in report:
# Assert that the customer group of each row is in the list of customer groups
self.assertIn(row.customer_group, cus_groups_list)
def test_party_account_filter(self):
si1 = self.create_sales_invoice()
self.customer2 = (

View File

@@ -139,6 +139,11 @@ frappe.query_reports["Accounts Receivable Summary"] = {
"label": __("Show GL Balance"),
"fieldtype": "Check",
},
{
"fieldname": "for_revaluation_journals",
"label": __("Revaluation Journals"),
"fieldtype": "Check",
}
],
onload: function(report) {

View File

@@ -31,6 +31,18 @@ frappe.query_reports["Asset Depreciation Ledger"] = {
"fieldtype": "Link",
"options": "Asset"
},
{
"fieldname":"asset_category",
"label": __("Asset Category"),
"fieldtype": "Link",
"options": "Asset Category"
},
{
"fieldname":"cost_center",
"label": __("Cost Center"),
"fieldtype": "Link",
"options": "Cost Center"
},
{
"fieldname":"finance_book",
"label": __("Finance Book"),
@@ -38,10 +50,10 @@ frappe.query_reports["Asset Depreciation Ledger"] = {
"options": "Finance Book"
},
{
"fieldname":"asset_category",
"label": __("Asset Category"),
"fieldtype": "Link",
"options": "Asset Category"
}
"fieldname": "include_default_book_assets",
"label": __("Include Default FB Assets"),
"fieldtype": "Check",
"default": 1
},
]
}

View File

@@ -1,15 +1,15 @@
{
"add_total_row": 1,
"add_total_row": 0,
"columns": [],
"creation": "2016-04-08 14:49:58.133098",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 2,
"idx": 6,
"is_standard": "Yes",
"letterhead": null,
"modified": "2023-07-26 21:05:33.554778",
"modified": "2023-11-08 20:17:05.774211",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Asset Depreciation Ledger",

View File

@@ -4,7 +4,7 @@
import frappe
from frappe import _
from frappe.utils import flt
from frappe.utils import cstr, flt
def execute(filters=None):
@@ -32,7 +32,6 @@ def get_data(filters):
filters_data.append(["against_voucher", "=", filters.get("asset")])
if filters.get("asset_category"):
assets = frappe.db.sql_list(
"""select name from tabAsset
where asset_category = %s and docstatus=1""",
@@ -41,12 +40,27 @@ def get_data(filters):
filters_data.append(["against_voucher", "in", assets])
if filters.get("finance_book"):
filters_data.append(["finance_book", "in", ["", filters.get("finance_book")]])
company_fb = frappe.get_cached_value("Company", filters.get("company"), "default_finance_book")
if filters.get("include_default_book_assets") and company_fb:
if filters.get("finance_book") and cstr(filters.get("finance_book")) != cstr(company_fb):
frappe.throw(_("To use a different finance book, please uncheck 'Include Default FB Assets'"))
else:
finance_book = company_fb
elif filters.get("finance_book"):
finance_book = filters.get("finance_book")
else:
finance_book = None
if finance_book:
or_filters_data = [["finance_book", "in", ["", finance_book]], ["finance_book", "is", "not set"]]
else:
or_filters_data = [["finance_book", "in", [""]], ["finance_book", "is", "not set"]]
gl_entries = frappe.get_all(
"GL Entry",
filters=filters_data,
or_filters=or_filters_data,
fields=["against_voucher", "debit_in_account_currency as debit", "voucher_no", "posting_date"],
order_by="against_voucher, posting_date",
)
@@ -61,7 +75,9 @@ def get_data(filters):
asset_data = assets_details.get(d.against_voucher)
if asset_data:
if not asset_data.get("accumulated_depreciation_amount"):
asset_data.accumulated_depreciation_amount = d.debit
asset_data.accumulated_depreciation_amount = d.debit + asset_data.get(
"opening_accumulated_depreciation"
)
else:
asset_data.accumulated_depreciation_amount += d.debit
@@ -70,7 +86,7 @@ def get_data(filters):
{
"depreciation_amount": d.debit,
"depreciation_date": d.posting_date,
"amount_after_depreciation": (
"value_after_depreciation": (
flt(row.gross_purchase_amount) - flt(row.accumulated_depreciation_amount)
),
"depreciation_entry": d.voucher_no,
@@ -88,10 +104,12 @@ def get_assets_details(assets):
fields = [
"name as asset",
"gross_purchase_amount",
"opening_accumulated_depreciation",
"asset_category",
"status",
"depreciation_method",
"purchase_date",
"cost_center",
]
for d in frappe.get_all("Asset", fields=fields, filters={"name": ("in", assets)}):
@@ -121,6 +139,12 @@ def get_columns():
"fieldtype": "Currency",
"width": 120,
},
{
"label": _("Opening Accumulated Depreciation"),
"fieldname": "opening_accumulated_depreciation",
"fieldtype": "Currency",
"width": 140,
},
{
"label": _("Depreciation Amount"),
"fieldname": "depreciation_amount",
@@ -134,8 +158,8 @@ def get_columns():
"width": 210,
},
{
"label": _("Amount After Depreciation"),
"fieldname": "amount_after_depreciation",
"label": _("Value After Depreciation"),
"fieldname": "value_after_depreciation",
"fieldtype": "Currency",
"width": 180,
},
@@ -153,12 +177,13 @@ def get_columns():
"options": "Asset Category",
"width": 120,
},
{"label": _("Current Status"), "fieldname": "status", "fieldtype": "Data", "width": 120},
{
"label": _("Depreciation Method"),
"fieldname": "depreciation_method",
"fieldtype": "Data",
"width": 130,
"label": _("Cost Center"),
"fieldtype": "Link",
"fieldname": "cost_center",
"options": "Cost Center",
"width": 100,
},
{"label": _("Current Status"), "fieldname": "status", "fieldtype": "Data", "width": 120},
{"label": _("Purchase Date"), "fieldname": "purchase_date", "fieldtype": "Date", "width": 120},
]

View File

@@ -15,7 +15,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
frappe.query_reports["Balance Sheet"]["filters"].push({
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"label": __("Include Default FB Entries"),
"fieldtype": "Check",
"default": 1
});

View File

@@ -16,7 +16,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
frappe.query_reports["Cash Flow"]["filters"].push(
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"label": __("Include Default FB Entries"),
"fieldtype": "Check",
"default": 1
}

View File

@@ -105,7 +105,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
},
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"label": __("Include Default FB Entries"),
"fieldtype": "Check",
"default": 1
},

View File

@@ -561,9 +561,7 @@ def apply_additional_conditions(doctype, query, from_date, ignore_closing_entrie
company_fb = frappe.get_cached_value("Company", filters.company, "default_finance_book")
if filters.finance_book and company_fb and cstr(filters.finance_book) != cstr(company_fb):
frappe.throw(
_("To use a different finance book, please uncheck 'Include Default Book Entries'")
)
frappe.throw(_("To use a different finance book, please uncheck 'Include Default FB Entries'"))
query = query.where(
(gl_entry.finance_book.isin([cstr(filters.finance_book), cstr(company_fb), ""]))

View File

@@ -79,7 +79,9 @@ class General_Payment_Ledger_Comparison(object):
.select(
gle.company,
gle.account,
gle.voucher_type,
gle.voucher_no,
gle.party_type,
gle.party,
outstanding,
)
@@ -89,7 +91,9 @@ class General_Payment_Ledger_Comparison(object):
& (gle.account.isin(val.accounts))
)
.where(Criterion.all(filter_criterion))
.groupby(gle.company, gle.account, gle.voucher_no, gle.party)
.groupby(
gle.company, gle.account, gle.voucher_type, gle.voucher_no, gle.party_type, gle.party
)
.run()
)
@@ -112,7 +116,13 @@ class General_Payment_Ledger_Comparison(object):
self.account_types[acc_type].ple = (
qb.from_(ple)
.select(
ple.company, ple.account, ple.voucher_no, ple.party, Sum(ple.amount).as_("outstanding")
ple.company,
ple.account,
ple.voucher_type,
ple.voucher_no,
ple.party_type,
ple.party,
Sum(ple.amount).as_("outstanding"),
)
.where(
(ple.company == self.filters.company)
@@ -120,7 +130,9 @@ class General_Payment_Ledger_Comparison(object):
& (ple.account.isin(val.accounts))
)
.where(Criterion.all(filter_criterion))
.groupby(ple.company, ple.account, ple.voucher_no, ple.party)
.groupby(
ple.company, ple.account, ple.voucher_type, ple.voucher_no, ple.party_type, ple.party
)
.run()
)
@@ -138,12 +150,12 @@ class General_Payment_Ledger_Comparison(object):
self.diff = frappe._dict({})
for x in self.variation_in_payment_ledger:
self.diff[(x[0], x[1], x[2], x[3])] = frappe._dict({"gl_balance": x[4]})
self.diff[(x[0], x[1], x[2], x[3], x[4], x[5])] = frappe._dict({"gl_balance": x[6]})
for x in self.variation_in_general_ledger:
self.diff.setdefault((x[0], x[1], x[2], x[3]), frappe._dict({"gl_balance": 0.0})).update(
frappe._dict({"pl_balance": x[4]})
)
self.diff.setdefault(
(x[0], x[1], x[2], x[3], x[4], x[5]), frappe._dict({"gl_balance": 0.0})
).update(frappe._dict({"pl_balance": x[6]}))
def generate_data(self):
self.data = []
@@ -151,8 +163,12 @@ class General_Payment_Ledger_Comparison(object):
self.data.append(
frappe._dict(
{
"voucher_no": key[2],
"party": key[3],
"company": key[0],
"account": key[1],
"voucher_type": key[2],
"voucher_no": key[3],
"party_type": key[4],
"party": key[5],
"gl_balance": val.gl_balance,
"pl_balance": val.pl_balance,
}
@@ -162,12 +178,52 @@ class General_Payment_Ledger_Comparison(object):
def get_columns(self):
self.columns = []
options = None
self.columns.append(
dict(
label=_("Company"),
fieldname="company",
fieldtype="Link",
options="Company",
width="100",
)
)
self.columns.append(
dict(
label=_("Account"),
fieldname="account",
fieldtype="Link",
options="Account",
width="100",
)
)
self.columns.append(
dict(
label=_("Voucher Type"),
fieldname="voucher_type",
fieldtype="Link",
options="DocType",
width="100",
)
)
self.columns.append(
dict(
label=_("Voucher No"),
fieldname="voucher_no",
fieldtype="Data",
options=options,
fieldtype="Dynamic Link",
options="voucher_type",
width="100",
)
)
self.columns.append(
dict(
label=_("Party Type"),
fieldname="party_type",
fieldtype="Link",
options="DocType",
width="100",
)
)
@@ -176,8 +232,8 @@ class General_Payment_Ledger_Comparison(object):
dict(
label=_("Party"),
fieldname="party",
fieldtype="Data",
options=options,
fieldtype="Dynamic Link",
options="party_type",
width="100",
)
)

View File

@@ -50,7 +50,11 @@ class TestGeneralAndPaymentLedger(FrappeTestCase, AccountsTestMixin):
self.assertEqual(len(data), 1)
expected = {
"company": sinv.company,
"account": sinv.debit_to,
"voucher_type": sinv.doctype,
"voucher_no": sinv.name,
"party_type": "Customer",
"party": sinv.customer,
"gl_balance": sinv.grand_total,
"pl_balance": sinv.grand_total - 1,

View File

@@ -175,7 +175,7 @@ frappe.query_reports["General Ledger"] = {
},
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"label": __("Include Default FB Entries"),
"fieldtype": "Check",
"default": 1
},
@@ -188,7 +188,13 @@ frappe.query_reports["General Ledger"] = {
"fieldname": "show_net_values_in_party_account",
"label": __("Show Net Values in Party Account"),
"fieldtype": "Check"
},
{
"fieldname": "show_remarks",
"label": __("Show Remarks"),
"fieldtype": "Check"
}
]
}

View File

@@ -163,6 +163,14 @@ def get_gl_entries(filters, accounting_dimensions):
select_fields = """, debit, credit, debit_in_account_currency,
credit_in_account_currency """
if filters.get("show_remarks"):
if remarks_length := frappe.db.get_single_value(
"Accounts Settings", "general_ledger_remarks_length"
):
select_fields += f",substr(remarks, 1, {remarks_length}) as 'remarks'"
else:
select_fields += """,remarks"""
order_by_statement = "order by posting_date, account, creation"
if filters.get("include_dimensions"):
@@ -189,7 +197,7 @@ def get_gl_entries(filters, accounting_dimensions):
voucher_type, voucher_no, {dimension_fields}
cost_center, project,
against_voucher_type, against_voucher, account_currency,
remarks, against, is_opening, creation {select_fields}
against, is_opening, creation {select_fields}
from `tabGL Entry`
where company=%(company)s {conditions}
{order_by_statement}
@@ -249,9 +257,7 @@ def get_conditions(filters):
if filters.get("company_fb") and cstr(filters.get("finance_book")) != cstr(
filters.get("company_fb")
):
frappe.throw(
_("To use a different finance book, please uncheck 'Include Default Book Entries'")
)
frappe.throw(_("To use a different finance book, please uncheck 'Include Default FB Entries'"))
else:
conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)")
else:
@@ -593,8 +599,10 @@ def get_columns(filters):
"width": 100,
},
{"label": _("Supplier Invoice No"), "fieldname": "bill_no", "fieldtype": "Data", "width": 100},
{"label": _("Remarks"), "fieldname": "remarks", "width": 400},
]
)
if filters.get("show_remarks"):
columns.extend([{"label": _("Remarks"), "fieldname": "remarks", "width": 400}])
return columns

View File

@@ -47,6 +47,7 @@ def get_result(
out = []
for name, details in gle_map.items():
tax_amount, total_amount, grand_total, base_total = 0, 0, 0, 0
bill_no, bill_date = "", ""
tax_withholding_category = tax_category_map.get(name)
rate = tax_rate_map.get(tax_withholding_category)
@@ -70,7 +71,10 @@ def get_result(
if net_total_map.get(name):
if voucher_type == "Journal Entry" and tax_amount and rate:
# back calcalute total amount from rate and tax_amount
total_amount = grand_total = base_total = tax_amount / (rate / 100)
if rate:
total_amount = grand_total = base_total = tax_amount / (rate / 100)
elif voucher_type == "Purchase Invoice":
total_amount, grand_total, base_total, bill_no, bill_date = net_total_map.get(name)
else:
total_amount, grand_total, base_total = net_total_map.get(name)
else:
@@ -96,7 +100,7 @@ def get_result(
row.update(
{
"section_code": tax_withholding_category,
"section_code": tax_withholding_category or "",
"entity_type": party_map.get(party, {}).get(party_type),
"rate": rate,
"total_amount": total_amount,
@@ -106,10 +110,14 @@ def get_result(
"transaction_date": posting_date,
"transaction_type": voucher_type,
"ref_no": name,
"supplier_invoice_no": bill_no,
"supplier_invoice_date": bill_date,
}
)
out.append(row)
out.sort(key=lambda x: x["section_code"])
return out
@@ -157,14 +165,14 @@ def get_gle_map(documents):
def get_columns(filters):
pan = "pan" if frappe.db.has_column(filters.party_type, "pan") else "tax_id"
columns = [
{"label": _(frappe.unscrub(pan)), "fieldname": pan, "fieldtype": "Data", "width": 60},
{
"label": _(filters.get("party_type")),
"fieldname": "party",
"fieldtype": "Dynamic Link",
"options": "party_type",
"width": 180,
"label": _("Section Code"),
"options": "Tax Withholding Category",
"fieldname": "section_code",
"fieldtype": "Link",
"width": 90,
},
{"label": _(frappe.unscrub(pan)), "fieldname": pan, "fieldtype": "Data", "width": 60},
]
if filters.naming_series == "Naming Series":
@@ -176,54 +184,73 @@ def get_columns(filters):
"width": 180,
}
)
else:
columns.append(
{
"label": _(filters.get("party_type")),
"fieldname": "party",
"fieldtype": "Dynamic Link",
"options": "party_type",
"width": 180,
}
)
columns.extend(
[
{"label": _("Entity Type"), "fieldname": "entity_type", "fieldtype": "Data", "width": 100},
]
)
if filters.party_type == "Supplier":
columns.extend(
[
{
"label": _("Supplier Invoice No"),
"fieldname": "supplier_invoice_no",
"fieldtype": "Data",
"width": 120,
},
{
"label": _("Supplier Invoice Date"),
"fieldname": "supplier_invoice_date",
"fieldtype": "Date",
"width": 120,
},
]
)
columns.extend(
[
{
"label": _("Date of Transaction"),
"fieldname": "transaction_date",
"fieldtype": "Date",
"width": 100,
"label": _("TDS Rate %") if filters.get("party_type") == "Supplier" else _("TCS Rate %"),
"fieldname": "rate",
"fieldtype": "Percent",
"width": 60,
},
{
"label": _("Section Code"),
"options": "Tax Withholding Category",
"fieldname": "section_code",
"fieldtype": "Link",
"width": 90,
},
{"label": _("Entity Type"), "fieldname": "entity_type", "fieldtype": "Data", "width": 100},
{
"label": _("Total Amount"),
"fieldname": "total_amount",
"fieldtype": "Float",
"width": 90,
},
{
"label": _("TDS Rate %") if filters.get("party_type") == "Supplier" else _("TCS Rate %"),
"fieldname": "rate",
"fieldtype": "Percent",
"width": 90,
},
{
"label": _("Tax Amount"),
"fieldname": "tax_amount",
"fieldtype": "Float",
"width": 90,
},
{
"label": _("Grand Total"),
"fieldname": "grand_total",
"fieldtype": "Float",
"width": 90,
"width": 120,
},
{
"label": _("Base Total"),
"fieldname": "base_total",
"fieldtype": "Float",
"width": 90,
"width": 120,
},
{"label": _("Transaction Type"), "fieldname": "transaction_type", "width": 100},
{
"label": _("Tax Amount"),
"fieldname": "tax_amount",
"fieldtype": "Float",
"width": 120,
},
{
"label": _("Grand Total"),
"fieldname": "grand_total",
"fieldtype": "Float",
"width": 120,
},
{"label": _("Transaction Type"), "fieldname": "transaction_type", "width": 130},
{
"label": _("Reference No."),
"fieldname": "ref_no",
@@ -231,6 +258,12 @@ def get_columns(filters):
"options": "transaction_type",
"width": 180,
},
{
"label": _("Date of Transaction"),
"fieldname": "transaction_date",
"fieldtype": "Date",
"width": 100,
},
]
)
@@ -253,27 +286,7 @@ def get_tds_docs(filters):
"Tax Withholding Account", {"company": filters.get("company")}, pluck="account"
)
query_filters = {
"account": ("in", tds_accounts),
"posting_date": ("between", [filters.get("from_date"), filters.get("to_date")]),
"is_cancelled": 0,
"against": ("not in", bank_accounts),
}
party = frappe.get_all(filters.get("party_type"), pluck="name")
or_filters.update({"against": ("in", party), "voucher_type": "Journal Entry"})
if filters.get("party"):
del query_filters["account"]
del query_filters["against"]
or_filters = {"against": filters.get("party"), "party": filters.get("party")}
tds_docs = frappe.get_all(
"GL Entry",
filters=query_filters,
or_filters=or_filters,
fields=["voucher_no", "voucher_type", "against", "party"],
)
tds_docs = get_tds_docs_query(filters, bank_accounts, tds_accounts).run(as_dict=True)
for d in tds_docs:
if d.voucher_type == "Purchase Invoice":
@@ -309,6 +322,47 @@ def get_tds_docs(filters):
)
def get_tds_docs_query(filters, bank_accounts, tds_accounts):
if not tds_accounts:
frappe.throw(
_("No {0} Accounts found for this company.").format(frappe.bold("Tax Withholding")),
title=_("Accounts Missing Error"),
)
gle = frappe.qb.DocType("GL Entry")
query = (
frappe.qb.from_(gle)
.select("voucher_no", "voucher_type", "against", "party")
.where((gle.is_cancelled == 0))
)
if filters.get("from_date"):
query = query.where(gle.posting_date >= filters.get("from_date"))
if filters.get("to_date"):
query = query.where(gle.posting_date <= filters.get("to_date"))
if bank_accounts:
query = query.where(gle.against.notin(bank_accounts))
if filters.get("party"):
party = [filters.get("party")]
query = query.where(
((gle.account.isin(tds_accounts) & gle.against.isin(party)))
| ((gle.voucher_type == "Journal Entry") & (gle.party == filters.get("party")))
| gle.party.isin(party)
)
else:
party = frappe.get_all(filters.get("party_type"), pluck="name")
query = query.where(
((gle.account.isin(tds_accounts) & gle.against.isin(party)))
| (
(gle.voucher_type == "Journal Entry")
& ((gle.party_type == filters.get("party_type")) | (gle.party_type == ""))
)
| gle.party.isin(party)
)
return query
def get_journal_entry_party_map(journal_entries):
journal_entry_party_map = {}
for d in frappe.db.get_all(
@@ -335,6 +389,8 @@ def get_doc_info(vouchers, doctype, tax_category_map, net_total_map=None):
"base_tax_withholding_net_total",
"grand_total",
"base_total",
"bill_no",
"bill_date",
],
"Sales Invoice": ["base_net_total", "grand_total", "base_total"],
"Payment Entry": [
@@ -353,7 +409,13 @@ def get_doc_info(vouchers, doctype, tax_category_map, net_total_map=None):
for entry in entries:
tax_category_map.update({entry.name: entry.tax_withholding_category})
if doctype == "Purchase Invoice":
value = [entry.base_tax_withholding_net_total, entry.grand_total, entry.base_total]
value = [
entry.base_tax_withholding_net_total,
entry.grand_total,
entry.base_total,
entry.bill_no,
entry.bill_date,
]
elif doctype == "Sales Invoice":
value = [entry.base_net_total, entry.grand_total, entry.base_total]
elif doctype == "Payment Entry":

View File

@@ -96,7 +96,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
},
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"label": __("Include Default FB Entries"),
"fieldtype": "Check",
"default": 1
},

View File

@@ -275,9 +275,7 @@ def get_opening_balance(
company_fb = frappe.get_cached_value("Company", filters.company, "default_finance_book")
if filters.finance_book and company_fb and cstr(filters.finance_book) != cstr(company_fb):
frappe.throw(
_("To use a different finance book, please uncheck 'Include Default Book Entries'")
)
frappe.throw(_("To use a different finance book, please uncheck 'Include Default FB Entries'"))
opening_balance = opening_balance.where(
(closing_balance.finance_book.isin([cstr(filters.finance_book), cstr(company_fb), ""]))

View File

@@ -179,6 +179,7 @@ def get_balance_on(
in_account_currency=True,
cost_center=None,
ignore_account_permission=False,
start_date=None,
):
if not account and frappe.form_dict.get("account"):
account = frappe.form_dict.get("account")
@@ -192,6 +193,8 @@ def get_balance_on(
cost_center = frappe.form_dict.get("cost_center")
cond = ["is_cancelled=0"]
if start_date:
cond.append("posting_date >= %s" % frappe.db.escape(cstr(start_date)))
if date:
cond.append("posting_date <= %s" % frappe.db.escape(cstr(date)))
else:
@@ -511,7 +514,7 @@ def check_if_advance_entry_modified(args):
party_account_field = (
"paid_from" if erpnext.get_party_account_type(args.party_type) == "Receivable" else "paid_to"
)
precision = frappe.get_precision("Payment Entry", "unallocated_amount")
if args.voucher_detail_no:
ret = frappe.db.sql(
"""select t1.name
@@ -533,9 +536,9 @@ def check_if_advance_entry_modified(args):
where
name = %(voucher_no)s and docstatus = 1
and party_type = %(party_type)s and party = %(party)s and {0} = %(account)s
and unallocated_amount = %(unreconciled_amount)s
and round(unallocated_amount, {1}) = round(%(unreconciled_amount)s, {1})
""".format(
party_account_field
party_account_field, precision
),
args,
)
@@ -1617,6 +1620,7 @@ def get_payment_ledger_entries(gl_entries, cancel=0):
due_date=gle.due_date,
voucher_type=gle.voucher_type,
voucher_no=gle.voucher_no,
voucher_detail_no=gle.voucher_detail_no,
against_voucher_type=gle.against_voucher_type
if gle.against_voucher_type
else gle.voucher_type,
@@ -1638,7 +1642,7 @@ def get_payment_ledger_entries(gl_entries, cancel=0):
def create_payment_ledger_entry(
gl_entries, cancel=0, adv_adj=0, update_outstanding="Yes", from_repost=0
gl_entries, cancel=0, adv_adj=0, update_outstanding="Yes", from_repost=0, partial_cancel=False
):
if gl_entries:
ple_map = get_payment_ledger_entries(gl_entries, cancel=cancel)
@@ -1648,7 +1652,7 @@ def create_payment_ledger_entry(
ple = frappe.get_doc(entry)
if cancel:
delink_original_entry(ple)
delink_original_entry(ple, partial_cancel=partial_cancel)
ple.flags.ignore_permissions = 1
ple.flags.adv_adj = adv_adj
@@ -1695,7 +1699,7 @@ def update_voucher_outstanding(voucher_type, voucher_no, account, party_type, pa
ref_doc.set_status(update=True)
def delink_original_entry(pl_entry):
def delink_original_entry(pl_entry, partial_cancel=False):
if pl_entry:
ple = qb.DocType("Payment Ledger Entry")
query = (
@@ -1715,6 +1719,10 @@ def delink_original_entry(pl_entry):
& (ple.against_voucher_no == pl_entry.against_voucher_no)
)
)
if partial_cancel:
query = query.where(ple.voucher_detail_no == pl_entry.voucher_detail_no)
query.run()
@@ -1791,6 +1799,28 @@ class QueryPaymentLedger(object):
Table("outstanding").amount_in_account_currency >= self.max_outstanding
)
if self.limit and self.get_invoices:
outstanding_vouchers = (
qb.from_(ple)
.select(
ple.against_voucher_no.as_("voucher_no"),
Sum(ple.amount_in_account_currency).as_("amount_in_account_currency"),
)
.where(ple.delinked == 0)
.where(Criterion.all(filter_on_against_voucher_no))
.where(Criterion.all(self.common_filter))
.groupby(ple.against_voucher_type, ple.against_voucher_no, ple.party_type, ple.party)
.orderby(ple.posting_date, ple.voucher_no)
.having(qb.Field("amount_in_account_currency") > 0)
.limit(self.limit)
.run()
)
if outstanding_vouchers:
filter_on_voucher_no.append(ple.voucher_no.isin([x[0] for x in outstanding_vouchers]))
filter_on_against_voucher_no.append(
ple.against_voucher_no.isin([x[0] for x in outstanding_vouchers])
)
# build query for voucher amount
query_voucher_amount = (
qb.from_(ple)

View File

@@ -495,11 +495,11 @@
"read_only": 1
},
{
"depends_on": "eval.doc.asset_quantity",
"default": "1",
"fieldname": "asset_quantity",
"fieldtype": "Int",
"label": "Asset Quantity",
"read_only": 1
"read_only_depends_on": "eval:!doc.is_existing_asset && !doc.is_composite_asset"
},
{
"fieldname": "depr_entry_posting_status",
@@ -565,7 +565,7 @@
"link_fieldname": "target_asset"
}
],
"modified": "2023-10-27 17:03:46.629617",
"modified": "2023-11-20 21:05:45.216899",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset",

View File

@@ -1216,11 +1216,12 @@ def get_item_details(item_code, asset_category, gross_purchase_amount):
"depreciation_method": d.depreciation_method,
"total_number_of_depreciations": d.total_number_of_depreciations,
"frequency_of_depreciation": d.frequency_of_depreciation,
"daily_depreciation": d.daily_depreciation,
"daily_prorata_based": d.daily_prorata_based,
"salvage_value_percentage": d.salvage_value_percentage,
"expected_value_after_useful_life": flt(gross_purchase_amount)
* flt(d.salvage_value_percentage / 100),
"depreciation_start_date": d.depreciation_start_date or nowdate(),
"rate_of_depreciation": d.rate_of_depreciation,
}
)
@@ -1396,7 +1397,7 @@ def get_straight_line_or_manual_depr_amount(
)
# if the Depreciation Schedule is being modified after Asset Value Adjustment due to decrease in asset value
elif asset.flags.decrease_in_asset_value_due_to_value_adjustment:
if row.daily_depreciation:
if row.daily_prorata_based:
daily_depr_amount = (
flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)
) / date_diff(
@@ -1441,7 +1442,7 @@ def get_straight_line_or_manual_depr_amount(
) / number_of_pending_depreciations
# if the Depreciation Schedule is being prepared for the first time
else:
if row.daily_depreciation:
if row.daily_prorata_based:
daily_depr_amount = (
flt(asset.gross_purchase_amount)
- flt(asset.opening_accumulated_depreciation)

View File

@@ -464,6 +464,9 @@ def restore_asset(asset_name):
def depreciate_asset(asset, date):
if not asset.calculate_depreciation:
return
asset.flags.ignore_validate_update_after_submit = True
asset.prepare_depreciation_data(date_of_disposal=date)
asset.save()
@@ -472,6 +475,9 @@ def depreciate_asset(asset, date):
def reset_depreciation_schedule(asset, date):
if not asset.calculate_depreciation:
return
asset.flags.ignore_validate_update_after_submit = True
# recreate original depreciation schedule of the asset
@@ -740,6 +746,15 @@ def get_disposal_account_and_cost_center(company):
def get_value_after_depreciation_on_disposal_date(asset, disposal_date, finance_book=None):
asset_doc = frappe.get_doc("Asset", asset)
if asset_doc.available_for_use_date > getdate(disposal_date):
frappe.throw(
"Disposal date {0} cannot be before available for use date {1} of the asset.".format(
disposal_date, asset_doc.available_for_use_date
)
)
elif asset_doc.available_for_use_date == getdate(disposal_date):
return flt(asset_doc.gross_purchase_amount - asset_doc.opening_accumulated_depreciation)
if asset_doc.calculate_depreciation:
asset_doc.prepare_depreciation_data(getdate(disposal_date))

View File

@@ -731,7 +731,9 @@ class TestDepreciationMethods(AssetSetup):
self.assertEqual(schedules, expected_schedules)
def test_schedule_for_straight_line_method_with_daily_depreciation(self):
def test_schedule_for_straight_line_method_with_daily_prorata_based(
self,
):
asset = create_asset(
calculate_depreciation=1,
available_for_use_date="2023-01-01",
@@ -740,7 +742,7 @@ class TestDepreciationMethods(AssetSetup):
depreciation_start_date="2023-01-31",
total_number_of_depreciations=12,
frequency_of_depreciation=1,
daily_depreciation=1,
daily_prorata_based=1,
)
expected_schedules = [
@@ -1703,7 +1705,7 @@ def create_asset(**args):
"total_number_of_depreciations": args.total_number_of_depreciations or 5,
"expected_value_after_useful_life": args.expected_value_after_useful_life or 0,
"depreciation_start_date": args.depreciation_start_date,
"daily_depreciation": args.daily_depreciation or 0,
"daily_prorata_based": args.daily_prorata_based or 0,
},
)

View File

@@ -8,7 +8,7 @@
"finance_book",
"depreciation_method",
"total_number_of_depreciations",
"daily_depreciation",
"daily_prorata_based",
"column_break_5",
"frequency_of_depreciation",
"depreciation_start_date",
@@ -82,23 +82,23 @@
"fieldtype": "Percent",
"label": "Rate of Depreciation"
},
{
"default": "0",
"depends_on": "eval:doc.depreciation_method == \"Straight Line\" || doc.depreciation_method == \"Manual\"",
"fieldname": "daily_depreciation",
"fieldtype": "Check",
"label": "Daily Depreciation"
},
{
"fieldname": "salvage_value_percentage",
"fieldtype": "Percent",
"label": "Salvage Value Percentage"
},
{
"default": "0",
"depends_on": "eval:doc.depreciation_method == \"Straight Line\" || doc.depreciation_method == \"Manual\"",
"fieldname": "daily_prorata_based",
"fieldtype": "Check",
"label": "Depreciate based on daily pro-rata"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-09-29 15:39:52.740594",
"modified": "2023-11-03 22:21:52.090191",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Finance Book",

View File

@@ -52,7 +52,7 @@ frappe.query_reports["Fixed Asset Register"] = {
},
{
"fieldname": "include_default_book_assets",
"label": __("Include Default Book Assets"),
"label": __("Include Default FB Assets"),
"fieldtype": "Check",
"default": 1
},

View File

@@ -223,7 +223,7 @@ def get_assets_linked_to_fb(filters):
company_fb = frappe.get_cached_value("Company", filters.company, "default_finance_book")
if filters.finance_book and company_fb and cstr(filters.finance_book) != cstr(company_fb):
frappe.throw(_("To use a different finance book, please uncheck 'Include Default Book Assets'"))
frappe.throw(_("To use a different finance book, please uncheck 'Include Default FB Assets'"))
query = query.where(
(afb.finance_book.isin([cstr(filters.finance_book), cstr(company_fb), ""]))

View File

@@ -1,30 +1,21 @@
// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Bulk Transaction Log', {
refresh: function(frm) {
frm.disable_save();
frm.add_custom_button(__('Retry Failed Transactions'), ()=>{
frappe.confirm(__("Retry Failing Transactions ?"), ()=>{
query(frm, 1);
}
);
});
}
frappe.ui.form.on("Bulk Transaction Log", {
refresh(frm) {
frm.add_custom_button(__('Succeeded Entries'), function() {
frappe.set_route('List', 'Bulk Transaction Log Detail', {'date': frm.doc.date, 'transaction_status': "Success"});
}, __("View"));
frm.add_custom_button(__('Failed Entries'), function() {
frappe.set_route('List', 'Bulk Transaction Log Detail', {'date': frm.doc.date, 'transaction_status': "Failed"});
}, __("View"));
if (frm.doc.failed) {
frm.add_custom_button(__('Retry Failed Transactions'), function() {
frappe.call({
method: "erpnext.utilities.bulk_transaction.retry",
args: {date: frm.doc.date}
});
});
}
},
});
function query(frm) {
frappe.call({
method: "erpnext.bulk_transaction.doctype.bulk_transaction_log.bulk_transaction_log.retry_failing_transaction",
args: {
log_date: frm.doc.log_date
}
}).then((r) => {
if (r.message === "No Failed Records") {
frappe.show_alert(__(r.message), 5);
} else {
frappe.show_alert(__("Retrying Failed Transactions"), 5);
}
});
}

View File

@@ -1,31 +1,64 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2021-11-30 13:41:16.343827",
"allow_copy": 1,
"creation": "2023-11-09 20:14:45.139593",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"log_date",
"logger_data"
"date",
"column_break_bsan",
"log_entries",
"section_break_mdmv",
"succeeded",
"column_break_qryp",
"failed"
],
"fields": [
{
"fieldname": "log_date",
"fieldname": "date",
"fieldtype": "Date",
"label": "Log Date",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Date",
"read_only": 1
},
{
"fieldname": "logger_data",
"fieldtype": "Table",
"label": "Logger Data",
"options": "Bulk Transaction Log Detail"
"fieldname": "log_entries",
"fieldtype": "Int",
"in_list_view": 1,
"label": "Log Entries",
"read_only": 1
},
{
"fieldname": "column_break_bsan",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_mdmv",
"fieldtype": "Section Break"
},
{
"fieldname": "succeeded",
"fieldtype": "Int",
"label": "Succeeded",
"read_only": 1
},
{
"fieldname": "column_break_qryp",
"fieldtype": "Column Break"
},
{
"fieldname": "failed",
"fieldtype": "Int",
"label": "Failed",
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"in_create": 1,
"is_virtual": 1,
"links": [],
"modified": "2022-02-03 17:23:02.935325",
"modified": "2023-11-11 04:52:49.347376",
"modified_by": "Administrator",
"module": "Bulk Transaction",
"name": "Bulk Transaction Log",
@@ -47,5 +80,5 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
"title_field": "date"
}

View File

@@ -1,67 +1,112 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from datetime import date
import frappe
from frappe import qb
from frappe.model.document import Document
from erpnext.utilities.bulk_transaction import task, update_logger
from frappe.query_builder.functions import Count
from frappe.utils import cint
from pypika import Order
class BulkTransactionLog(Document):
pass
def db_insert(self, *args, **kwargs):
pass
def load_from_db(self):
log_detail = qb.DocType("Bulk Transaction Log Detail")
@frappe.whitelist()
def retry_failing_transaction(log_date=None):
if not log_date:
log_date = str(date.today())
btp = frappe.qb.DocType("Bulk Transaction Log Detail")
data = (
frappe.qb.from_(btp)
.select(btp.transaction_name, btp.from_doctype, btp.to_doctype)
.distinct()
.where(btp.retried != 1)
.where(btp.transaction_status == "Failed")
.where(btp.date == log_date)
).run(as_dict=True)
has_records = frappe.db.sql(
f"select exists (select * from `tabBulk Transaction Log Detail` where date = '{self.name}');"
)[0][0]
if not has_records:
raise frappe.DoesNotExistError
if data:
if len(data) > 10:
frappe.enqueue(job, queue="long", job_name="bulk_retry", data=data, log_date=log_date)
else:
job(data, log_date)
else:
return "No Failed Records"
succeeded_logs = (
qb.from_(log_detail)
.select(Count(log_detail.date).as_("count"))
.where((log_detail.date == self.name) & (log_detail.transaction_status == "Success"))
.run()
)[0][0] or 0
failed_logs = (
qb.from_(log_detail)
.select(Count(log_detail.date).as_("count"))
.where((log_detail.date == self.name) & (log_detail.transaction_status == "Failed"))
.run()
)[0][0] or 0
total_logs = succeeded_logs + failed_logs
transaction_log = frappe._dict(
{
"date": self.name,
"count": total_logs,
"succeeded": succeeded_logs,
"failed": failed_logs,
}
)
super(Document, self).__init__(serialize_transaction_log(transaction_log))
@staticmethod
def get_list(args):
filter_date = parse_list_filters(args)
limit = cint(args.get("page_length")) or 20
log_detail = qb.DocType("Bulk Transaction Log Detail")
def job(data, log_date):
for d in data:
failed = []
try:
frappe.db.savepoint("before_creation_of_record")
task(d.transaction_name, d.from_doctype, d.to_doctype)
except Exception as e:
frappe.db.rollback(save_point="before_creation_of_record")
failed.append(e)
update_logger(
d.transaction_name,
e,
d.from_doctype,
d.to_doctype,
status="Failed",
log_date=log_date,
restarted=1,
dates_query = (
qb.from_(log_detail)
.select(log_detail.date)
.distinct()
.orderby(log_detail.date, order=Order.desc)
.limit(limit)
)
if filter_date:
dates_query = dates_query.where(log_detail.date == filter_date)
dates = dates_query.run()
transaction_logs = []
if dates:
transaction_logs_query = (
qb.from_(log_detail)
.select(log_detail.date.as_("date"), Count(log_detail.date).as_("count"))
.where(log_detail.date.isin(dates))
.orderby(log_detail.date, order=Order.desc)
.groupby(log_detail.date)
.limit(limit)
)
transaction_logs = transaction_logs_query.run(as_dict=True)
if not failed:
update_logger(
d.transaction_name,
None,
d.from_doctype,
d.to_doctype,
status="Success",
log_date=log_date,
restarted=1,
)
return [serialize_transaction_log(x) for x in transaction_logs]
@staticmethod
def get_count(args):
pass
@staticmethod
def get_stats(args):
pass
def db_update(self, *args, **kwargs):
pass
def delete(self):
pass
def serialize_transaction_log(data):
return frappe._dict(
name=data.date,
date=data.date,
log_entries=data.count,
succeeded=data.succeeded,
failed=data.failed,
)
def parse_list_filters(args):
# parse date filter
filter_date = None
for fil in args.get("filters"):
if isinstance(fil, list):
for elem in fil:
if elem == "date":
filter_date = fil[3]
return filter_date

View File

@@ -1,79 +1,9 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from datetime import date
import frappe
from erpnext.utilities.bulk_transaction import transaction_processing
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestBulkTransactionLog(unittest.TestCase):
def setUp(self):
create_company()
create_customer()
create_item()
def test_entry_in_log(self):
so_name = create_so()
transaction_processing([{"name": so_name}], "Sales Order", "Sales Invoice")
doc = frappe.get_doc("Bulk Transaction Log", str(date.today()))
for d in doc.get("logger_data"):
if d.transaction_name == so_name:
self.assertEqual(d.transaction_name, so_name)
self.assertEqual(d.transaction_status, "Success")
self.assertEqual(d.from_doctype, "Sales Order")
self.assertEqual(d.to_doctype, "Sales Invoice")
self.assertEqual(d.retried, 0)
def create_company():
if not frappe.db.exists("Company", "_Test Company"):
frappe.get_doc(
{
"doctype": "Company",
"company_name": "_Test Company",
"country": "India",
"default_currency": "INR",
}
).insert()
def create_customer():
if not frappe.db.exists("Customer", "Bulk Customer"):
frappe.get_doc({"doctype": "Customer", "customer_name": "Bulk Customer"}).insert()
def create_item():
if not frappe.db.exists("Item", "MK"):
frappe.get_doc(
{
"doctype": "Item",
"item_code": "MK",
"item_name": "Milk",
"description": "Milk",
"item_group": "Products",
}
).insert()
def create_so(intent=None):
so = frappe.new_doc("Sales Order")
so.customer = "Bulk Customer"
so.company = "_Test Company"
so.transaction_date = date.today()
so.set_warehouse = "Finished Goods - _TC"
so.append(
"items",
{
"item_code": "MK",
"delivery_date": date.today(),
"qty": 10,
"rate": 80,
},
)
so.insert()
so.submit()
return so.name
class TestBulkTransactionLog(FrappeTestCase):
pass

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Bulk Transaction Log Detail", {
// refresh(frm) {
// },
// });

View File

@@ -6,12 +6,12 @@
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"from_doctype",
"transaction_name",
"date",
"time",
"transaction_status",
"error_description",
"from_doctype",
"to_doctype",
"retried"
],
@@ -20,8 +20,11 @@
"fieldname": "transaction_name",
"fieldtype": "Dynamic Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Name",
"options": "from_doctype"
"options": "from_doctype",
"read_only": 1,
"search_index": 1
},
{
"fieldname": "transaction_status",
@@ -39,9 +42,11 @@
{
"fieldname": "from_doctype",
"fieldtype": "Link",
"in_standard_filter": 1,
"label": "From Doctype",
"options": "DocType",
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "to_doctype",
@@ -54,8 +59,10 @@
"fieldname": "date",
"fieldtype": "Date",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Date ",
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "time",
@@ -66,19 +73,33 @@
{
"fieldname": "retried",
"fieldtype": "Int",
"in_list_view": 1,
"label": "Retried",
"read_only": 1
}
],
"in_create": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2022-02-03 19:57:31.650359",
"modified": "2023-11-10 11:44:10.758342",
"modified_by": "Administrator",
"module": "Bulk Transaction",
"name": "Bulk Transaction Log Detail",
"owner": "Administrator",
"permissions": [],
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"states": [],

View File

@@ -0,0 +1,9 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestBulkTransactionLogDetail(FrappeTestCase):
pass

View File

@@ -17,6 +17,7 @@
"po_required",
"pr_required",
"blanket_order_allowance",
"project_update_frequency",
"column_break_12",
"maintain_same_rate",
"set_landed_cost_based_on_purchase_invoice_rate",
@@ -172,6 +173,14 @@
"fieldname": "blanket_order_allowance",
"fieldtype": "Float",
"label": "Blanket Order Allowance (%)"
},
{
"default": "Each Transaction",
"description": "How often should Project be updated of Total Purchase Cost ?",
"fieldname": "project_update_frequency",
"fieldtype": "Select",
"label": "Update frequency of Project",
"options": "Each Transaction\nManual"
}
],
"icon": "fa fa-cog",
@@ -179,7 +188,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2023-10-25 14:03:32.520418",
"modified": "2023-11-24 10:55:51.287327",
"modified_by": "Administrator",
"module": "Buying",
"name": "Buying Settings",

View File

@@ -16,7 +16,7 @@ from erpnext.buying.doctype.purchase_order.purchase_order import (
make_purchase_invoice as make_pi_from_po,
)
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
from erpnext.controllers.accounts_controller import update_child_qty_rate
from erpnext.controllers.accounts_controller import InvalidQtyError, update_child_qty_rate
from erpnext.manufacturing.doctype.blanket_order.test_blanket_order import make_blanket_order
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.material_request.material_request import make_purchase_order
@@ -27,6 +27,21 @@ from erpnext.stock.doctype.purchase_receipt.purchase_receipt import (
class TestPurchaseOrder(FrappeTestCase):
def test_purchase_order_qty(self):
po = create_purchase_order(qty=1, do_not_save=True)
po.append(
"items",
{
"item_code": "_Test Item",
"qty": -1,
"rate": 10,
},
)
self.assertRaises(frappe.NonNegativeError, po.save)
po.items[1].qty = 0
self.assertRaises(InvalidQtyError, po.save)
def test_make_purchase_receipt(self):
po = create_purchase_order(do_not_submit=True)
self.assertRaises(frappe.ValidationError, make_purchase_receipt, po.name)

View File

@@ -190,6 +190,7 @@
"fieldtype": "Column Break"
},
{
"fetch_from": "item_code.image",
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
@@ -214,6 +215,7 @@
"fieldtype": "Float",
"in_list_view": 1,
"label": "Quantity",
"non_negative": 1,
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"print_width": "60px",
@@ -471,6 +473,7 @@
"fieldname": "material_request",
"fieldtype": "Link",
"label": "Material Request",
"mandatory_depends_on": "eval: doc.material_request_item",
"no_copy": 1,
"oldfieldname": "prevdoc_docname",
"oldfieldtype": "Link",
@@ -486,6 +489,7 @@
"fieldtype": "Data",
"hidden": 1,
"label": "Material Request Item",
"mandatory_depends_on": "eval: doc.material_request",
"no_copy": 1,
"oldfieldname": "prevdoc_detail_docname",
"oldfieldtype": "Data",
@@ -915,7 +919,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-10-27 15:50:42.655573",
"modified": "2023-11-24 19:07:34.921094",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",

View File

@@ -9,6 +9,8 @@
"field_order": [
"naming_series",
"company",
"billing_address",
"billing_address_display",
"vendor",
"column_break1",
"transaction_date",
@@ -292,13 +294,25 @@
"fieldtype": "Check",
"label": "Send Document Print",
"print_hide": 1
},
{
"fieldname": "billing_address",
"fieldtype": "Link",
"label": "Company Billing Address",
"options": "Address"
},
{
"fieldname": "billing_address_display",
"fieldtype": "Small Text",
"label": "Billing Address Details",
"read_only": 1
}
],
"icon": "fa fa-shopping-cart",
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2023-08-09 12:20:26.850623",
"modified": "2023-11-06 12:45:28.898706",
"modified_by": "Administrator",
"module": "Buying",
"name": "Request for Quotation",

View File

@@ -88,6 +88,7 @@
"width": "300px"
},
{
"fetch_from": "item_code.image",
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
@@ -261,13 +262,15 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-09-24 17:26:46.276934",
"modified": "2023-11-14 18:34:48.327224",
"modified_by": "Administrator",
"module": "Buying",
"name": "Request for Quotation Item",
"naming_rule": "Random",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}

View File

@@ -170,7 +170,7 @@
"fieldname": "supplier_type",
"fieldtype": "Select",
"label": "Supplier Type",
"options": "Company\nIndividual",
"options": "Company\nIndividual\nProprietorship\nPartnership",
"reqd": 1
},
{
@@ -457,7 +457,7 @@
"link_fieldname": "party"
}
],
"modified": "2023-05-09 15:34:13.408932",
"modified": "2023-10-19 16:55:15.148325",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier",
@@ -525,4 +525,4 @@
"states": [],
"title_field": "supplier_name",
"track_changes": 1
}
}

View File

@@ -143,16 +143,17 @@ class Supplier(TransactionBase):
@frappe.validate_and_sanitize_search_inputs
def get_supplier_primary_contact(doctype, txt, searchfield, start, page_len, filters):
supplier = filters.get("supplier")
return frappe.db.sql(
"""
SELECT
`tabContact`.name from `tabContact`,
`tabDynamic Link`
WHERE
`tabContact`.name = `tabDynamic Link`.parent
and `tabDynamic Link`.link_name = %(supplier)s
and `tabDynamic Link`.link_doctype = 'Supplier'
and `tabContact`.name like %(txt)s
""",
{"supplier": supplier, "txt": "%%%s%%" % txt},
)
contact = frappe.qb.DocType("Contact")
dynamic_link = frappe.qb.DocType("Dynamic Link")
return (
frappe.qb.from_(contact)
.join(dynamic_link)
.on(contact.name == dynamic_link.parent)
.select(contact.name, contact.email_id)
.where(
(dynamic_link.link_name == supplier)
& (dynamic_link.link_doctype == "Supplier")
& (contact.name.like("%{0}%".format(txt)))
)
).run(as_dict=False)

View File

@@ -20,6 +20,10 @@
"valid_till",
"quotation_number",
"amended_from",
"accounting_dimensions_section",
"cost_center",
"dimension_col_break",
"project",
"currency_and_price_list",
"currency",
"conversion_rate",
@@ -79,6 +83,7 @@
"pricing_rule_details",
"pricing_rules",
"address_and_contact_tab",
"supplier_address_section",
"supplier_address",
"address_display",
"column_break_72",
@@ -86,6 +91,14 @@
"contact_display",
"contact_mobile",
"contact_email",
"shipping_address_section",
"shipping_address",
"column_break_zjaq",
"shipping_address_display",
"company_billing_address_section",
"billing_address",
"column_break_gcth",
"billing_address_display",
"terms_tab",
"tc_name",
"terms",
@@ -837,6 +850,76 @@
"fieldname": "named_place",
"fieldtype": "Data",
"label": "Named Place"
},
{
"fieldname": "shipping_address",
"fieldtype": "Link",
"label": "Shipping Address",
"options": "Address",
"print_hide": 1
},
{
"fieldname": "column_break_zjaq",
"fieldtype": "Column Break"
},
{
"fieldname": "shipping_address_display",
"fieldtype": "Small Text",
"label": "Shipping Address Details",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "shipping_address_section",
"fieldtype": "Section Break",
"label": "Shipping Address"
},
{
"fieldname": "supplier_address_section",
"fieldtype": "Section Break",
"label": "Supplier Address"
},
{
"fieldname": "company_billing_address_section",
"fieldtype": "Section Break",
"label": "Company Billing Address"
},
{
"fieldname": "billing_address",
"fieldtype": "Link",
"label": "Company Billing Address",
"options": "Address"
},
{
"fieldname": "column_break_gcth",
"fieldtype": "Column Break"
},
{
"fieldname": "billing_address_display",
"fieldtype": "Small Text",
"label": "Billing Address Details",
"read_only": 1
},
{
"fieldname": "cost_center",
"fieldtype": "Link",
"label": "Cost Center",
"options": "Cost Center"
},
{
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project"
},
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
},
{
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
"label": "Accounting Dimensions"
}
],
"icon": "fa fa-shopping-cart",
@@ -844,7 +927,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2023-04-14 16:43:41.714832",
"modified": "2023-11-20 11:15:30.083077",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation",

View File

@@ -68,6 +68,8 @@
"column_break_15",
"manufacturer_part_no",
"ad_sec_break",
"cost_center",
"dimension_col_break",
"project",
"section_break_44",
"page_break"
@@ -134,6 +136,7 @@
"fieldtype": "Column Break"
},
{
"fetch_from": "item_code.image",
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
@@ -554,19 +557,31 @@
"fieldname": "expected_delivery_date",
"fieldtype": "Date",
"label": "Expected Delivery Date"
},
{
"fieldname": "cost_center",
"fieldtype": "Link",
"label": "Cost Center",
"options": "Cost Center"
},
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
}
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-10-19 12:36:26.913211",
"modified": "2023-11-17 12:25:26.235367",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation Item",
"naming_rule": "Random",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}

View File

@@ -70,6 +70,10 @@ class AccountMissingError(frappe.ValidationError):
pass
class InvalidQtyError(frappe.ValidationError):
pass
force_item_fields = (
"item_group",
"brand",
@@ -238,7 +242,7 @@ class AccountsController(TransactionBase):
references_map.setdefault(x.parent, []).append(x.name)
for doc, rows in references_map.items():
unreconcile_doc = frappe.get_doc("Unreconcile Payments", doc)
unreconcile_doc = frappe.get_doc("Unreconcile Payment", doc)
for row in rows:
unreconcile_doc.remove(unreconcile_doc.get("allocations", {"name": row})[0])
@@ -247,9 +251,9 @@ class AccountsController(TransactionBase):
unreconcile_doc.save(ignore_permissions=True)
# delete docs upon parent doc deletion
unreconcile_docs = frappe.db.get_all("Unreconcile Payments", filters={"voucher_no": self.name})
unreconcile_docs = frappe.db.get_all("Unreconcile Payment", filters={"voucher_no": self.name})
for x in unreconcile_docs:
_doc = frappe.get_doc("Unreconcile Payments", x.name)
_doc = frappe.get_doc("Unreconcile Payment", x.name)
if _doc.docstatus == 1:
_doc.cancel()
_doc.delete()
@@ -895,10 +899,16 @@ class AccountsController(TransactionBase):
return gl_dict
def validate_qty_is_not_zero(self):
if self.doctype != "Purchase Receipt":
for item in self.items:
if not item.qty:
frappe.throw(_("Item quantity can not be zero"))
if self.doctype == "Purchase Receipt":
return
for item in self.items:
if not flt(item.qty):
frappe.throw(
msg=_("Row #{0}: Item quantity cannot be zero").format(item.idx),
title=_("Invalid Quantity"),
exc=InvalidQtyError,
)
def validate_account_currency(self, account, account_currency=None):
valid_currency = [self.company_currency]
@@ -2249,6 +2259,7 @@ class AccountsController(TransactionBase):
repost_ledger = frappe.new_doc("Repost Accounting Ledger")
repost_ledger.company = self.company
repost_ledger.append("vouchers", {"voucher_type": self.doctype, "voucher_no": self.name})
repost_ledger.flags.ignore_permissions = True
repost_ledger.insert()
repost_ledger.submit()
self.db_set("repost_required", 0)
@@ -3022,16 +3033,19 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
conv_fac_precision = child_item.precision("conversion_factor") or 2
qty_precision = child_item.precision("qty") or 2
if flt(child_item.billed_amt, rate_precision) > flt(
flt(d.get("rate"), rate_precision) * flt(d.get("qty"), qty_precision), rate_precision
):
# Amount cannot be lesser than billed amount, except for negative amounts
row_rate = flt(d.get("rate"), rate_precision)
amount_below_billed_amt = flt(child_item.billed_amt, rate_precision) > flt(
row_rate * flt(d.get("qty"), qty_precision), rate_precision
)
if amount_below_billed_amt and row_rate > 0.0:
frappe.throw(
_("Row #{0}: Cannot set Rate if amount is greater than billed amount for Item {1}.").format(
child_item.idx, child_item.item_code
)
)
else:
child_item.rate = flt(d.get("rate"), rate_precision)
child_item.rate = row_rate
if d.get("conversion_factor"):
if child_item.stock_uom == child_item.uom:

View File

@@ -4,7 +4,7 @@
import frappe
from frappe import ValidationError, _, msgprint
from frappe.contacts.doctype.address.address import get_address_display
from frappe.contacts.doctype.address.address import render_address
from frappe.utils import cint, cstr, flt, getdate
from frappe.utils.data import nowtime
@@ -78,26 +78,27 @@ class BuyingController(SubcontractingController):
def set_rate_for_standalone_debit_note(self):
if self.get("is_return") and self.get("update_stock") and not self.return_against:
for row in self.items:
if row.rate <= 0:
# override the rate with valuation rate
row.rate = get_incoming_rate(
{
"item_code": row.item_code,
"warehouse": row.warehouse,
"posting_date": self.get("posting_date"),
"posting_time": self.get("posting_time"),
"qty": row.qty,
"serial_no": row.serial_no,
"batch_no": row.batch_no,
"company": self.company,
"voucher_type": self.doctype,
"voucher_no": self.name,
},
raise_error_if_no_rate=False,
)
# override the rate with valuation rate
row.rate = get_incoming_rate(
{
"item_code": row.item_code,
"warehouse": row.warehouse,
"posting_date": self.get("posting_date"),
"posting_time": self.get("posting_time"),
"qty": row.qty,
"serial_and_batch_bundle": row.get("serial_and_batch_bundle"),
"company": self.company,
"voucher_type": self.doctype,
"voucher_no": self.name,
},
raise_error_if_no_rate=False,
)
row.discount_percentage = 0.0
row.discount_amount = 0.0
row.margin_rate_or_amount = 0.0
row.discount_percentage = 0.0
row.discount_amount = 0.0
row.margin_rate_or_amount = 0.0
def set_missing_values(self, for_validate=False):
super(BuyingController, self).set_missing_values(for_validate)
@@ -219,7 +220,9 @@ class BuyingController(SubcontractingController):
for address_field, address_display_field in address_dict.items():
if self.get(address_field):
self.set(address_display_field, get_address_display(self.get(address_field)))
self.set(
address_display_field, render_address(self.get(address_field), check_permissions=False)
)
def set_total_in_words(self):
from frappe.utils import money_in_words
@@ -336,7 +339,7 @@ class BuyingController(SubcontractingController):
{
"item_code": d.item_code,
"warehouse": d.get("from_warehouse"),
"posting_date": self.get("posting_date") or self.get("transation_date"),
"posting_date": self.get("posting_date") or self.get("transaction_date"),
"posting_time": posting_time,
"qty": -1 * flt(d.get("stock_qty")),
"serial_no": d.get("serial_no"),
@@ -743,7 +746,7 @@ class BuyingController(SubcontractingController):
"calculate_depreciation": 1,
"purchase_receipt_amount": purchase_amount,
"gross_purchase_amount": purchase_amount,
"asset_quantity": row.qty if is_grouped_asset else 0,
"asset_quantity": row.qty if is_grouped_asset else 1,
"purchase_receipt": self.name if self.doctype == "Purchase Receipt" else None,
"purchase_invoice": self.name if self.doctype == "Purchase Invoice" else None,
"cost_center": row.cost_center,

View File

@@ -560,6 +560,8 @@ def get_income_account(doctype, txt, searchfield, start, page_len, filters):
if filters.get("company"):
condition += "and tabAccount.company = %(company)s"
condition += f"and tabAccount.disabled = {filters.get('disabled', 0)}"
return frappe.db.sql(
"""select tabAccount.name from `tabAccount`
where (tabAccount.report_type = "Profit and Loss"

View File

@@ -356,6 +356,7 @@ def make_return_doc(doctype: str, source_name: str, target_doc=None):
if doc.doctype == "Sales Invoice" or doc.doctype == "POS Invoice":
doc.consolidated_invoice = ""
doc.set("payments", [])
doc.update_billed_amount_in_delivery_note = True
for data in source.payments:
paid_amount = 0.00
base_paid_amount = 0.00

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