Compare commits

..

396 Commits

Author SHA1 Message Date
Frappe PR Bot
e0060f8ffe chore(release): Bumped to Version 15.43.1
## [15.43.1](https://github.com/frappe/erpnext/compare/v15.43.0...v15.43.1) (2024-11-21)

### Bug Fixes

* no permission to read Doctype (backport [#44256](https://github.com/frappe/erpnext/issues/44256)) ([#44258](https://github.com/frappe/erpnext/issues/44258)) ([b047425](b047425a6f))
2024-11-21 09:44:42 +00:00
rohitwaghchaure
3518991ff0 Merge pull request #44259 from frappe/mergify/bp/version-15/pr-44258
fix: no permission to read Doctype (backport #44256) (backport #44258)
2024-11-21 15:13:16 +05:30
mergify[bot]
b047425a6f fix: no permission to read Doctype (backport #44256) (#44258)
fix: no permission to read Doctype (#44256)

(cherry picked from commit 57293aa18a)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 8b15a965dd)
2024-11-21 09:22:50 +00:00
Frappe PR Bot
ccf99cf985 chore(release): Bumped to Version 15.43.0
# [15.43.0](https://github.com/frappe/erpnext/compare/v15.42.0...v15.43.0) (2024-11-20)

### Bug Fixes

* added disable_rounded_total field ([c98a0cc](c98a0ccd1d))
* added test cases ([234741f](234741f35f))
* apply posting date sorting to invoices in Payment Reconciliation similar to payments ([41c8cfa](41c8cfac73))
* broken apply on other item pricing rule ([5d6451f](5d6451fca7))
* broken UI on currency exchange ([f460391](f4603910e4))
* bulk update invoice remarks during site upgrade ([cc07402](cc07402b5e)), closes [#43634](https://github.com/frappe/erpnext/issues/43634)
* check if pricing rule matches with coupon code ([#44104](https://github.com/frappe/erpnext/issues/44104)) ([6089661](608966158a))
* correctly set 'cannot_add_rows' property on allocations table field ([c59a778](c59a778503))
* disable conversion to user tz for sales order calender ([83b9680](83b9680318))
* Get Entries not showing accounts with no gain or loss in Exchange Rate Revaluation issue ([1fe5342](1fe534290d))
* linters ([381101f](381101f552))
* non group pos warehouse ([4335659](4335659905))
* payment reco for jv with negative dr or cr amount ([7483839](7483839418))
* remove trailing whitespace ([5bd633b](5bd633b40f))
* remove validate_name_in_customer function ([6bff9d3](6bff9d39e3))
* set conversion factor before applying price list ([5848de7](5848de76ea))
* set debit in transaction currency in GL Entry ([c0d3f8c](c0d3f8cbbe))
* set default party type in Payment Entry ([08f6cee](08f6ceeb50))
* **setup:** Fix typo in COA setup ([7abcfca](7abcfca1cb))
* stock ledger variance report filter options (backport [#44137](https://github.com/frappe/erpnext/issues/44137)) ([#44150](https://github.com/frappe/erpnext/issues/44150)) ([b6fe1f5](b6fe1f5842))
* update project cost from timesheet (backport [#44211](https://github.com/frappe/erpnext/issues/44211)) ([#44212](https://github.com/frappe/erpnext/issues/44212)) ([ad0c655](ad0c65500a))
* validate sales team to ensure all sales person are enabled ([f3c3f17](f3c3f170a7))
* validation for serial no (backport [#44133](https://github.com/frappe/erpnext/issues/44133)) ([#44151](https://github.com/frappe/erpnext/issues/44151)) ([725d107](725d107288))

### Features

* inventory dimension for rejected materials (backport [#44156](https://github.com/frappe/erpnext/issues/44156)) ([#44165](https://github.com/frappe/erpnext/issues/44165)) ([d61f696](d61f696f85))
* new DocTypes "Code List" and "Common Code" (backport [#43425](https://github.com/frappe/erpnext/issues/43425)) ([#44173](https://github.com/frappe/erpnext/issues/44173)) ([b130e20](b130e2065b))
* round off for opening entries ([8e6249d](8e6249d361))
2024-11-20 08:41:13 +00:00
ruthra kumar
9b690e9ae6 Merge pull request #44209 from frappe/version-15-hotfix
chore: release v15
2024-11-20 14:09:56 +05:30
ruthra kumar
d0e2b7c341 Merge pull request #44183 from frappe/mergify/bp/version-15-hotfix/pr-44025
fix: `Disable Rounded Total` in Quotation DocType (backport #44025)
2024-11-20 13:14:16 +05:30
ruthra kumar
4afd4b4044 Merge pull request #44245 from frappe/mergify/bp/version-15-hotfix/pr-44197
fix: payment reco for jv with negative dr or cr amount (backport #44197)
2024-11-20 13:12:44 +05:30
ruthra kumar
80f0d5b5ec chore: resolve conflict 2024-11-20 12:51:29 +05:30
ljain112
234741f35f fix: added test cases
(cherry picked from commit 6f9ea6422d)
2024-11-20 07:18:27 +00:00
ljain112
7483839418 fix: payment reco for jv with negative dr or cr amount
(cherry picked from commit fee79b9445)
2024-11-20 07:18:26 +00:00
ruthra kumar
9e7e6041ed Merge pull request #44242 from frappe/mergify/bp/version-15-hotfix/pr-44240
fix: non group pos warehouse (backport #44240)
2024-11-20 12:18:02 +05:30
ruthra kumar
9ce1c25c04 Merge pull request #44239 from frappe/mergify/bp/version-15-hotfix/pr-44220
refactor: Update `Payment Request` search query in PE's reference (backport #44220)
2024-11-20 12:16:07 +05:30
Nihantra C. Patel
4335659905 fix: non group pos warehouse
(cherry picked from commit d526be0394)
2024-11-20 06:41:56 +00:00
Abdeali Chharchhoda
514fe69b65 refactor: Update Payment Request search query in PE's reference
(cherry picked from commit 4ab3499a17)
2024-11-20 06:22:17 +00:00
ruthra kumar
a0ea68499b Merge pull request #44233 from frappe/mergify/bp/version-15-hotfix/pr-44207
fix: validate sales team to ensure all sales person are enabled (backport #44207)
2024-11-20 11:51:33 +05:30
ruthra kumar
76d6dd346c Merge pull request #44235 from frappe/mergify/bp/version-15-hotfix/pr-44203
fix: disable conversion to user tz for sales order calender (backport #44203)
2024-11-20 11:51:09 +05:30
ljain112
83b9680318 fix: disable conversion to user tz for sales order calender
(cherry picked from commit cdf098c193)
2024-11-20 05:17:57 +00:00
ljain112
f3c3f170a7 fix: validate sales team to ensure all sales person are enabled
(cherry picked from commit 548dbb33eb)
2024-11-20 05:11:41 +00:00
ruthra kumar
bc03b68b13 Merge pull request #44221 from frappe/mergify/bp/version-15-hotfix/pr-41025
fix: remove validate_name_in_customer function (backport #41025)
2024-11-20 10:19:28 +05:30
mergify[bot]
ad0c65500a fix: update project cost from timesheet (backport #44211) (#44212)
fix: update project cost from timesheet (#44211)

(cherry picked from commit b21fb8f8b6)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-19 22:59:16 +05:30
RitvikSardana
6bff9d39e3 fix: remove validate_name_in_customer function
(cherry picked from commit 2b32d3644f)
2024-11-19 14:22:34 +00:00
ruthra kumar
704452a9fa Merge pull request #44218 from frappe/mergify/bp/version-15-hotfix/pr-44190
fix(setup): Fix typo in COA setup (backport #44190)
2024-11-19 19:51:41 +05:30
Corentin Forler
7abcfca1cb fix(setup): Fix typo in COA setup
(cherry picked from commit a245cc6b07)
2024-11-19 12:15:15 +00:00
ruthra kumar
610c483d83 Merge pull request #44217 from frappe/mergify/bp/version-15-hotfix/pr-44104
fix: check if pricing rule matches with coupon code (backport #44104)
2024-11-19 17:37:55 +05:30
Nikolas Beckel
608966158a fix: check if pricing rule matches with coupon code (#44104)
* fix: check if pricing rule matches with coupon code

* fix: correct linting error

(cherry picked from commit 9d31bf7647)
2024-11-19 11:42:04 +00:00
ruthra kumar
efdbe93cf0 Merge pull request #44206 from frappe/mergify/bp/version-15-hotfix/pr-44145
fix: updated label "Is short year" to "Is Short/Long year" for both short and long fiscal years (backport #44145)
2024-11-19 14:47:19 +05:30
ajiragroup
c2748e923e refactor: update label and description on short year checkbox
Is short/long year.

(cherry picked from commit 1d6b9b405f)
2024-11-19 08:56:54 +00:00
ruthra kumar
a17e1f6b6d Merge pull request #44202 from frappe/mergify/bp/version-15-hotfix/pr-44188
chore: update oldest_items.json, change owner back to administrator (backport #44188)
2024-11-19 12:30:49 +05:30
Ismail Arif
0ea6691189 chore: update oldest_items.json, change owner back to administrator
Signed-off-by: Ismail Arif <38789073+ismxilxrif@users.noreply.github.com>
(cherry picked from commit 7ceb24fb4c)
2024-11-19 06:33:18 +00:00
ruthra kumar
eca43916f0 Merge pull request #44193 from frappe/mergify/bp/version-15-hotfix/pr-44134
fix: set debit in transaction currency in GL Entry (backport #44134)
2024-11-19 11:58:14 +05:30
ruthra kumar
8cc59e3be7 refactor: update test case
(cherry picked from commit 4aab6f55f5)
2024-11-19 11:40:37 +05:30
mergify[bot]
b130e2065b feat: new DocTypes "Code List" and "Common Code" (backport #43425) (#44173)
Co-authored-by: David <dgx.arnold@gmail.com>
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2024-11-18 21:08:21 +01:00
ruthra kumar
d7deed6c45 refactor: assume any of the foreign currency as transaction currency
On a foreign currency payment entry, assume any one of the foreign
currency as the transaction currency

(cherry picked from commit 6681882bd8)
2024-11-18 11:42:49 +00:00
sudarsan2001
7cc31df587 chore: change account name
(cherry picked from commit 4a1cd5a8d6)
2024-11-18 11:42:49 +00:00
sudarsan2001
c30a17cd7a test: add unit test to validate gl values
(cherry picked from commit e8b8a589be)
2024-11-18 11:42:49 +00:00
sudarsan2001
c0d3f8cbbe fix: set debit in transaction currency in GL Entry
(cherry picked from commit 29a6eb21a3)
2024-11-18 11:42:49 +00:00
Ninad1306
b6524946bc test: test to validate rounded total
(cherry picked from commit 5a6261d3b4)
2024-11-18 06:00:12 +00:00
Ninad1306
c98a0ccd1d fix: added disable_rounded_total field
(cherry picked from commit f8524d526b)

# Conflicts:
#	erpnext/selling/doctype/quotation/quotation.json
2024-11-18 06:00:12 +00:00
ruthra kumar
73a31cb395 Merge pull request #44182 from frappe/mergify/bp/version-15-hotfix/pr-44127
fix: set default Party Type based on Payment Type in Payment Entry (backport #44127)
2024-11-18 10:49:24 +05:30
vishakhdesai
08f6ceeb50 fix: set default party type in Payment Entry
(cherry picked from commit 19222690d3)
2024-11-18 04:44:58 +00:00
ruthra kumar
f04a934ed1 Merge pull request #44180 from frappe/mergify/bp/version-15-hotfix/pr-44147
fix: set conversion factor before applying price list (backport #44147)
2024-11-18 10:14:45 +05:30
ruthra kumar
c6bfaa41be Merge pull request #44178 from frappe/mergify/bp/version-15-hotfix/pr-44157
fix: apply "cannot_add_rows" directly to table field for more efficient solution (backport #44157)
2024-11-18 10:14:23 +05:30
vishakhdesai
5848de76ea fix: set conversion factor before applying price list
(cherry picked from commit 9749fe23cc)
2024-11-18 04:38:37 +00:00
UmakanthKaspa
2a54cd5004 refactor: set 'cannot_add_rows' directly in the allocations table field (optimized approach)
(cherry picked from commit 5dd8eafdfc)
2024-11-18 04:36:19 +00:00
mergify[bot]
d61f696f85 feat: inventory dimension for rejected materials (backport #44156) (#44165)
feat: inventory dimension for rejected materials (#44156)

(cherry picked from commit 9bf16df41e)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-15 17:28:41 +05:30
mergify[bot]
725d107288 fix: validation for serial no (backport #44133) (#44151)
* fix: validation for serial no (#44133)

(cherry picked from commit 93c8b4c39a)

# Conflicts:
#	erpnext/stock/doctype/stock_entry/test_stock_entry.py

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-15 16:55:32 +05:30
mergify[bot]
b6fe1f5842 fix: stock ledger variance report filter options (backport #44137) (#44150)
fix: stock ledger variance report filter options (#44137)

(cherry picked from commit e8bbf6492f)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-15 15:04:48 +05:30
ruthra kumar
5b3f0825af Merge pull request #44162 from frappe/mergify/bp/version-15-hotfix/pr-43414
fix: Get Entries not showing accounts with no gain or loss in Exchange Rate Revaluation issue fixed (backport #43414)
2024-11-15 13:09:45 +05:30
Vishakh Desai
381101f552 fix: linters
(cherry picked from commit 9cc22b4cac)
2024-11-15 07:19:01 +00:00
Vishakh Desai
1fe534290d fix: Get Entries not showing accounts with no gain or loss in Exchange Rate Revaluation issue
(cherry picked from commit 6de6f55b39)
2024-11-15 07:19:01 +00:00
ruthra kumar
5004b8fbc9 Merge pull request #44160 from frappe/mergify/bp/version-15-hotfix/pr-44158
fix: broken UI on currency exchange (backport #44158)
2024-11-15 12:29:32 +05:30
ruthra kumar
f4603910e4 fix: broken UI on currency exchange
(cherry picked from commit e91b65e7bd)
2024-11-15 06:52:46 +00:00
ruthra kumar
50d15249fc Merge pull request #44155 from frappe/mergify/bp/version-15-hotfix/pr-44089
fix: apply posting date sorting to invoices in Payment Reconciliation similar to payments (backport #44089)
2024-11-15 10:49:12 +05:30
UmakanthKaspa
5bd633b40f fix: remove trailing whitespace
(cherry picked from commit d6703eb88b)
2024-11-15 05:00:07 +00:00
UmakanthKaspa
41c8cfac73 fix: apply posting date sorting to invoices in Payment Reconciliation similar to payments
(cherry picked from commit 0bd83d920d)
2024-11-15 05:00:06 +00:00
ruthra kumar
68f3dd848a Merge pull request #44153 from frappe/mergify/bp/version-15-hotfix/pr-44148
Fix: Disable "Add Row" button in allocations table during UnReconcile process (backport #44148)
2024-11-15 10:24:16 +05:30
UmakanthKaspa
c59a778503 fix: correctly set 'cannot_add_rows' property on allocations table field
(cherry picked from commit 13ca2700f8)
2024-11-15 04:47:53 +00:00
ruthra kumar
8ee7e7d828 Merge pull request #44140 from frappe/mergify/bp/version-15-hotfix/pr-43189
fix: broken apply on other item (backport #43189)
2024-11-14 13:45:29 +05:30
ruthra kumar
5d6451fca7 fix: broken apply on other item pricing rule
(cherry picked from commit e5119a749c)
2024-11-14 07:54:15 +00:00
ruthra kumar
90b7ce2dd6 Merge pull request #44136 from frappe/mergify/bp/version-15-hotfix/pr-42588
refactor: separate round off account for opening (backport #42588)
2024-11-14 13:04:13 +05:30
ruthra kumar
7b77128aab Merge pull request #43651 from vv-varun/erpnext_issue_43634
fix: bulk update invoice remarks during site upgrade
2024-11-14 12:48:50 +05:30
ruthra kumar
9598b1fc0f chore: resolve conflicts 2024-11-14 12:36:56 +05:30
ruthra kumar
ba79560c0c refactor(test): filter for active ledger entries
(cherry picked from commit cf11ac87fb)
2024-11-14 07:01:54 +00:00
ruthra kumar
9bfd5cdb2b test: opening purchase invoice with rounding adjustment
(cherry picked from commit b7edc6dea9)

# Conflicts:
#	erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
2024-11-14 07:01:54 +00:00
ruthra kumar
8bec67cbcf refactor: handle opening round off on purchase invoice
(cherry picked from commit a5d6a25a96)
2024-11-14 07:01:53 +00:00
ruthra kumar
7eb4b42280 refactor: filter on account_type
(cherry picked from commit 193ea9ad8f)
2024-11-14 07:01:53 +00:00
ruthra kumar
da2f6a045a test: opening round off with inclusive tax
(cherry picked from commit 79267358d0)
2024-11-14 07:01:53 +00:00
ruthra kumar
820692f246 test: rounding adjustment validation and posting
(cherry picked from commit 5021c7ca2c)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
2024-11-14 07:01:53 +00:00
ruthra kumar
186b646dee refactor: handle opening round off from sales invoice
(cherry picked from commit 96e3c2ad10)
2024-11-14 07:01:52 +00:00
ruthra kumar
b28ff25180 chore: default should return 3 elements
(cherry picked from commit fc46ebcd7c)
2024-11-14 07:01:52 +00:00
ruthra kumar
9a3e9c4c9a refactor: use separate round off for opening entries
(cherry picked from commit 88e68168e3)

# Conflicts:
#	erpnext/accounts/general_ledger.py
2024-11-14 07:01:52 +00:00
ruthra kumar
8e6249d361 feat: round off for opening entries
(cherry picked from commit a5b228549c)
2024-11-14 07:01:51 +00:00
Varun Verma
cc07402b5e fix: bulk update invoice remarks during site upgrade
fixes issue #43634
2024-11-14 12:01:16 +05:30
Frappe PR Bot
7c78e0025d chore(release): Bumped to Version 15.42.0
# [15.42.0](https://github.com/frappe/erpnext/compare/v15.41.2...v15.42.0) (2024-11-13)

### Bug Fixes

* add default height to POS item card selector (backport [#44071](https://github.com/frappe/erpnext/issues/44071)) ([#44075](https://github.com/frappe/erpnext/issues/44075)) ([65ec7c5](65ec7c5604))
* add field conversion_factor when include_uom is settled ([#43701](https://github.com/frappe/erpnext/issues/43701)) ([f387a8f](f387a8fceb))
* better gls for purchases with tax witholding ([#42743](https://github.com/frappe/erpnext/issues/42743)) ([705a26a](705a26a2fa))
* bind this object explicitly on callback event function ([3423d3c](3423d3c13d))
* calculate percentage received and delivered considering over-receipt and over-delivery (backport [#43870](https://github.com/frappe/erpnext/issues/43870)) ([#44030](https://github.com/frappe/erpnext/issues/44030)) ([5958d0c](5958d0c257))
* Cannot read properties of undefined (reading 'work_order_closed') (backport [#44117](https://github.com/frappe/erpnext/issues/44117)) ([#44122](https://github.com/frappe/erpnext/issues/44122)) ([c1983a4](c1983a4846))
* consider service item cost in the RM cost of the BOM (backport [#43962](https://github.com/frappe/erpnext/issues/43962)) ([#44111](https://github.com/frappe/erpnext/issues/44111)) ([6e83fec](6e83fec5ca))
* Drop Shipping address based on customer shopping address ([8af005c](8af005cef0))
* duplicate items and outdated item price in POS (backport [#42978](https://github.com/frappe/erpnext/issues/42978)) ([#44038](https://github.com/frappe/erpnext/issues/44038)) ([4cde77d](4cde77d8d8))
* exception on register reports when filtered on cost center ([be07421](be07421ab7))
* improved the conditions for determining voucher subtypes ([58ca4a2](58ca4a2b99))
* incorrect produced qty in Production Plan Summary (backport [#44112](https://github.com/frappe/erpnext/issues/44112)) ([#44113](https://github.com/frappe/erpnext/issues/44113)) ([bce7acf](bce7acf9cc))
* item mapping from modal to batch form ([#44090](https://github.com/frappe/erpnext/issues/44090)) ([9ac54f6](9ac54f694c))
* item not set in the batch quick entry form (backport [#44028](https://github.com/frappe/erpnext/issues/44028)) ([#44031](https://github.com/frappe/erpnext/issues/44031)) ([6dcd015](6dcd015a39))
* Negative stock validation against inventory dimension (backport [#43834](https://github.com/frappe/erpnext/issues/43834)) ([#43846](https://github.com/frappe/erpnext/issues/43846)) ([b314f38](b314f3839b))
* NoneType while updating ordered_qty in SO for removed items ([978a007](978a0078d8))
* not able to cancel DN (backport [#44108](https://github.com/frappe/erpnext/issues/44108)) ([#44109](https://github.com/frappe/erpnext/issues/44109)) ([290bdde](290bddea77))
* not able to reconcile expired batches ([#44012](https://github.com/frappe/erpnext/issues/44012)) ([4ba07a4](4ba07a40eb))
* patch ([107d53b](107d53b358))
* populate payment schedule from payment terms (backport [#44082](https://github.com/frappe/erpnext/issues/44082)) ([#44083](https://github.com/frappe/erpnext/issues/44083)) ([363f151](363f15124e))
* purchase receipt creation from SCR ([#44095](https://github.com/frappe/erpnext/issues/44095)) ([e3d7468](e3d74684d5))
* slow reposting due to SABB update ([3e29ae8](3e29ae8534))
* sort by ascending to get the first period closing voucher (backport [#44029](https://github.com/frappe/erpnext/issues/44029)) ([#44035](https://github.com/frappe/erpnext/issues/44035)) ([56f25ae](56f25ae065))
* task path (backport [#44073](https://github.com/frappe/erpnext/issues/44073)) ([#44078](https://github.com/frappe/erpnext/issues/44078)) ([34b5639](34b5639d1c))
* tyeerror while saving pick list ([7d09832](7d098328d0))
* update payment amount for partial pos return ([61559be](61559be8a4))
* update per_billed value in Purchase Receipt while creating Debit Note ([#43977](https://github.com/frappe/erpnext/issues/43977)) ([a833dd6](a833dd67f3))
* when company is created with other company template Chart of Account  the Create Taxe Template failed ([#42755](https://github.com/frappe/erpnext/issues/42755)) ([e6894b9](e6894b949c))

### Features

* Add item group filtering for search results ([2754793](2754793ff9))
* add template taxe for charts of account France - Plan Comptable General avec code ([#42757](https://github.com/frappe/erpnext/issues/42757)) ([865786e](865786e0b6))
2024-11-13 15:02:57 +00:00
ruthra kumar
d8d8330123 Merge pull request #44103 from frappe/version-15-hotfix
chore: release v15
2024-11-13 20:31:36 +05:30
ruthra kumar
825571ac98 Merge pull request #44115 from frappe/mergify/bp/version-15-hotfix/pr-43977
fix: update per_billed value in Purchase Receipt while creating Debit Note (backport #43977)
2024-11-13 19:01:53 +05:30
ruthra kumar
836a05d07f Merge pull request #44125 from frappe/mergify/copy/version-15-hotfix/pr-44124
refactor: 'Partly Billed' status for Purchase Receipt (copy #44124)
2024-11-13 17:22:36 +05:30
ruthra kumar
b9ec43c354 refactor: 'Partly Billed' status for Purchase Receipt
(cherry picked from commit c58bbd25f2)
2024-11-13 11:28:52 +00:00
mergify[bot]
c1983a4846 fix: Cannot read properties of undefined (reading 'work_order_closed') (backport #44117) (#44122)
fix: Cannot read properties of undefined (reading 'work_order_closed') (#44117)

(cherry picked from commit 13834014b5)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-13 16:24:12 +05:30
Nihantra C. Patel
b65b57c054 Merge pull request #44120 from frappe/mergify/bp/version-15-hotfix/pr-44116
fix: Drop Shipping address based on customer shopping address (backport #44116)
2024-11-13 15:51:28 +05:30
Nihantra Patel
8af005cef0 fix: Drop Shipping address based on customer shopping address
(cherry picked from commit c7499f3528)
2024-11-13 10:02:20 +00:00
mergify[bot]
bce7acf9cc fix: incorrect produced qty in Production Plan Summary (backport #44112) (#44113)
fix: incorrect produced qty in Production Plan Summary (#44112)

(cherry picked from commit 0828c74fe3)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-13 12:31:31 +05:30
NaviN
a833dd67f3 fix: update per_billed value in Purchase Receipt while creating Debit Note (#43977)
* fix: update per_billed value in Purchase Receipt while creating Debit Note

* test: add unit test for validating per_billed value for partial Debit Note

(cherry picked from commit 494fd7ceea)
2024-11-13 06:54:54 +00:00
mergify[bot]
6e83fec5ca fix: consider service item cost in the RM cost of the BOM (backport #43962) (#44111)
fix: consider service item cost in the RM cost of the BOM (#43962)

(cherry picked from commit c0ffaa444c)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-12 23:22:18 +05:30
mergify[bot]
290bddea77 fix: not able to cancel DN (backport #44108) (#44109)
fix: not able to cancel DN (#44108)

(cherry picked from commit e8882718c9)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-12 18:12:13 +05:30
ruthra kumar
5fea0b5525 Merge pull request #44107 from frappe/mergify/bp/version-15-hotfix/pr-44012
fix: not able to reconcile expired batches (backport #44012)
2024-11-12 16:34:15 +05:30
ruthra kumar
c2f7615eeb Merge pull request #44106 from frappe/mergify/bp/version-15-hotfix/pr-44095
fix: purchase receipt creation from SCR (backport #44095)
2024-11-12 16:33:45 +05:30
rohitwaghchaure
4ba07a40eb fix: not able to reconcile expired batches (#44012)
(cherry picked from commit 8805e74784)
2024-11-12 10:19:19 +00:00
rohitwaghchaure
e3d74684d5 fix: purchase receipt creation from SCR (#44095)
(cherry picked from commit 774845f886)
2024-11-12 10:14:17 +00:00
ruthra kumar
73661ac633 Merge pull request #44100 from frappe/mergify/bp/version-15-hotfix/pr-44053
Pos barcode search fix (backport #44053)
2024-11-12 13:54:03 +05:30
ruthra kumar
55f7f63e6e refactor: simpler filtering
(cherry picked from commit f072b1266e)
2024-11-12 07:16:09 +00:00
Bhavan23
aca1577040 refactor: Relocate doc variable for better scope management
(cherry picked from commit 488b60fc27)
2024-11-12 07:16:08 +00:00
Bhavan23
2754793ff9 feat: Add item group filtering for search results
(cherry picked from commit 5e7cf3899b)
2024-11-12 07:16:08 +00:00
ruthra kumar
5e196b9f8b Merge pull request #44098 from frappe/mergify/bp/version-15-hotfix/pr-44065
fix: update payment amount for partial pos return (backport #44065)
2024-11-12 10:10:58 +05:30
Kavin
61559be8a4 fix: update payment amount for partial pos return
(cherry picked from commit 53ef6336b6)
2024-11-12 04:20:31 +00:00
ruthra kumar
07dcf3fac2 Merge pull request #44040 from ruthra-kumar/manual_backport_pr_39481
fix: specify precision for net_amount (backport #39481)
2024-11-11 17:11:11 +05:30
ruthra kumar
471781a47e Merge pull request #44088 from frappe/mergify/bp/version-15-hotfix/pr-43695
fix: exception on register reports when filtered on cost center (backport #43695)
2024-11-11 17:00:23 +05:30
ruthra kumar
0afe893a83 Merge pull request #44093 from frappe/mergify/bp/version-15-hotfix/pr-44072
fix: bind this object explicitly on callback event function (backport #44072)
2024-11-11 17:00:10 +05:30
ruthra kumar
92551751bf Merge pull request #44063 from frappe/mergify/bp/version-15-hotfix/pr-42757
feat: add template taxe for charts of account France - Plan Comptable General avec code (backport #42757)
2024-11-11 16:53:15 +05:30
ruthra kumar
c8682d33d0 Merge pull request #44062 from frappe/mergify/bp/version-15-hotfix/pr-42755
fix: when company is created with other company template Chart of Account  the Create Taxe Template failed (backport #42755)
2024-11-11 16:52:54 +05:30
Kavin
3423d3c13d fix: bind this object explicitly on callback event function
(cherry picked from commit 5e790a0fce)
2024-11-11 11:21:09 +00:00
ruthra kumar
f3ee439b33 Merge pull request #44091 from frappe/mergify/bp/version-15-hotfix/pr-44090
fix: item mapping from modal to batch form (backport #44090)
2024-11-11 16:50:18 +05:30
ruthra kumar
ba6e068abc refactor(test): update tests for new rounding logic 2024-11-11 16:47:38 +05:30
ruthra kumar
34f64f02bf Merge pull request #44092 from frappe/mergify/bp/version-15-hotfix/pr-43701
fix: add field conversion_factor when include_uom is settled (backport #43701)
2024-11-11 16:45:25 +05:30
ruthra kumar
762f3bac65 chore: filter report output on document name 2024-11-11 16:42:13 +05:30
mergify[bot]
b314f3839b fix: Negative stock validation against inventory dimension (backport #43834) (#43846)
fix: Negative stock validation against inventory dimension (#43834)

(cherry picked from commit c330a292d2)

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2024-11-11 16:12:01 +05:30
HarryPaulo
f387a8fceb fix: add field conversion_factor when include_uom is settled (#43701)
(cherry picked from commit cfe6af1f68)
2024-11-11 10:41:40 +00:00
rohitwaghchaure
9ac54f694c fix: item mapping from modal to batch form (#44090)
(cherry picked from commit 9223ef2f37)
2024-11-11 10:38:42 +00:00
ruthra kumar
2bce735300 chore: use FrappeTestCase 2024-11-11 15:06:55 +05:30
ruthra kumar
2de9292ac0 refactor(test): assertion refactoring and exact decimals
(cherry picked from commit 1d11131afe)
2024-11-11 09:18:14 +00:00
ruthra kumar
d0e5568010 refactor(test): pass all mandatory fields
(cherry picked from commit c53e9637dd)
2024-11-11 09:18:14 +00:00
ruthra kumar
9724cefce8 refactor(test): fix incorrect assertion
(cherry picked from commit d6030e7112)
2024-11-11 09:18:14 +00:00
ruthra kumar
2affa60ea9 test: journals with cost center
(cherry picked from commit c255f34eea)
2024-11-11 09:18:14 +00:00
ruthra kumar
2183b99330 test: basic report output
(cherry picked from commit 657201b324)
2024-11-11 09:18:13 +00:00
Vishv-silveroak
be07421ab7 fix: exception on register reports when filtered on cost center
1

(cherry picked from commit f01e1a8e20)
2024-11-11 09:18:13 +00:00
mergify[bot]
363f15124e fix: populate payment schedule from payment terms (backport #44082) (#44083)
fix: populate payment schedule from payment terms (#44082)

(cherry picked from commit c81eb6c824)

Co-authored-by: Nihantra C. Patel <141945075+Nihantra-Patel@users.noreply.github.com>
2024-11-11 13:12:30 +05:30
mergify[bot]
34b5639d1c fix: task path (backport #44073) (#44078)
fix: task path (#44073)

(cherry picked from commit 8c99acb1b9)

Co-authored-by: Nihantra C. Patel <141945075+Nihantra-Patel@users.noreply.github.com>
2024-11-11 13:00:27 +05:30
mergify[bot]
4cfeb79355 chore: update CODEOWNERS (backport #44074) (#44081)
chore: update `CODEOWNERS` (#44074)

(cherry picked from commit 9a758ea826)

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2024-11-11 12:51:48 +05:30
mergify[bot]
65ec7c5604 fix: add default height to POS item card selector (backport #44071) (#44075)
fix: add default height to POS item card selector

(cherry picked from commit 5f5a514d6f)

Co-authored-by: Kavin <78342682+kavin0411@users.noreply.github.com>
2024-11-11 12:27:26 +05:30
rohitwaghchaure
593428b16d Merge pull request #44070 from frappe/mergify/bp/version-15-hotfix/pr-44058
fix: type error while saving pick list (backport #44058)
2024-11-11 12:26:43 +05:30
rohitwaghchaure
3c0623f593 Merge pull request #44068 from frappe/mergify/bp/version-15-hotfix/pr-44064
fix: slow reposting due to SABB update (backport #44064)
2024-11-11 12:10:12 +05:30
vishnu
7d098328d0 fix: tyeerror while saving pick list
(cherry picked from commit 22de0ecbdc)
2024-11-11 06:24:54 +00:00
Rohit Waghchaure
3e29ae8534 fix: slow reposting due to SABB update
(cherry picked from commit 2447b3f424)
2024-11-11 06:23:40 +00:00
ruthra kumar
d648875681 Merge pull request #44010 from frappe/mergify/bp/version-15-hotfix/pr-43689
refactor: allow multiple payment requests through customer portal (backport #43689)
2024-11-11 11:35:11 +05:30
HENRY Florian
865786e0b6 feat: add template taxe for charts of account France - Plan Comptable General avec code (#42757)
* feat: add template taxe for charts of account France - Plan Comptable General avec code

* feat: add template taxe for charts of account France - Plan Comptable General avec code

* feat: add template taxe for charts of account France - Plan Comptable General avec code

* feat: add template taxe for charts of account France - Plan Comptable General avec code

* feat: add template taxe for charts of account France - Plan Comptable General avec code

(cherry picked from commit 1fe6efdeb9)
2024-11-11 04:48:37 +00:00
HENRY Florian
e6894b949c fix: when company is created with other company template Chart of Account the Create Taxe Template failed (#42755)
fix: when company if create with other company template Created Template Taxe failed
(cherry picked from commit 8383883977)
2024-11-11 04:47:02 +00:00
Sagar Vora
11745add18 Merge pull request #44048 from frappe/mergify/bp/version-15-hotfix/pr-42743
fix: better gls for purchases with tax witholding (backport #42743)
2024-11-09 20:14:08 +05:30
Smit Vora
705a26a2fa fix: better gls for purchases with tax witholding (#42743)
* fix: better gls for purchases with tax witholding

* test: test case for purchase invoice gl entries with tax witholding

* fix: use flag `_skip_merge` instead of skipping merge based on against account

* test: fix test `test_single_threshold_tds` for newer implementation

(cherry picked from commit e3cd6539c3)
2024-11-09 09:45:25 +00:00
ruthra kumar
50fa77276e refactor: depracate old method and handle inclusive tax 2024-11-08 16:14:13 +05:30
mergify[bot]
4cde77d8d8 fix: duplicate items and outdated item price in POS (backport #42978) (#44038)
fix: duplicate items and outdated item price in POS (#42978)

* fix: duplicate items and outdated item price in POS

* fix: duplicate items and outdated item price in POS --formatter

(cherry picked from commit 4ea2071265)

Co-authored-by: Nihantra C. Patel <141945075+Nihantra-Patel@users.noreply.github.com>
2024-11-08 13:05:48 +05:30
Nabin Hait
f5610e29be Release v15.41.2 (#44037)
* fix: improved the conditions for determining voucher subtypes

(cherry picked from commit 00eee16190)

* fix: patch

(cherry picked from commit d76cc21086)

# Conflicts:
#	erpnext/patches.txt

* test: test voucher subtype for sales invoice

(cherry picked from commit ad6cc352f1)

* chore: resolve conflict

* fix: NoneType while updating ordered_qty in SO for removed items

(cherry picked from commit 442cdd7ce4)

* refactor: add "margin_type" and "margin_rate_or_amount" to no copy

(cherry picked from commit 70f090c1ec)

* fix: item not set in the batch quick entry form (backport #44028) (#44031)

fix: item not set in the batch quick entry form (#44028)

(cherry picked from commit 0399ccc51e)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>

* fix: calculate percentage received and delivered considering over-receipt and over-delivery (backport #43870) (#44030)

fix: calculate percentage received and delivered considering over-receipt and over-delivery (#43870)

(cherry picked from commit adba1168c1)

Co-authored-by: Nabin Hait <nabinhait@gmail.com>

* fix: sort by ascending to get the first period closing voucher (backport #44029) (#44035)

fix: sort by ascending to get the first period closing voucher (#44029)

(cherry picked from commit 42dcdcde1a)

Co-authored-by: Venkatesh <47534423+venkat102@users.noreply.github.com>

---------

Co-authored-by: ljain112 <ljain112@gmail.com>
Co-authored-by: Smit Vora <smitvora203@gmail.com>
Co-authored-by: ruthra kumar <ruthra@erpnext.com>
Co-authored-by: bhaveshkumar.j <bhaveshkumar.j@sritindia.com>
Co-authored-by: Ravindu Nethmina <117300601+NethminaHiker360@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
Co-authored-by: Venkatesh <47534423+venkat102@users.noreply.github.com>
2024-11-08 13:02:23 +05:30
mergify[bot]
56f25ae065 fix: sort by ascending to get the first period closing voucher (backport #44029) (#44035)
fix: sort by ascending to get the first period closing voucher (#44029)

(cherry picked from commit 42dcdcde1a)

Co-authored-by: Venkatesh <47534423+venkat102@users.noreply.github.com>
2024-11-08 12:34:47 +05:30
mergify[bot]
5958d0c257 fix: calculate percentage received and delivered considering over-receipt and over-delivery (backport #43870) (#44030)
fix: calculate percentage received and delivered considering over-receipt and over-delivery (#43870)

(cherry picked from commit adba1168c1)

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2024-11-08 12:24:21 +05:30
mergify[bot]
6dcd015a39 fix: item not set in the batch quick entry form (backport #44028) (#44031)
fix: item not set in the batch quick entry form (#44028)

(cherry picked from commit 0399ccc51e)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-08 12:23:50 +05:30
ruthra kumar
489fde8220 Merge pull request #44027 from frappe/mergify/bp/version-15-hotfix/pr-43873
fix: add missing fields to field_no_map array (backport #43873)
2024-11-08 11:52:13 +05:30
Ravindu Nethmina
487b5776e6 refactor: add "margin_type" and "margin_rate_or_amount" to no copy
(cherry picked from commit 70f090c1ec)
2024-11-08 06:00:33 +00:00
ruthra kumar
f397361ba7 Merge pull request #44024 from frappe/mergify/bp/version-15-hotfix/pr-43762
fix: handle NoneType error when updating ordered_qty in SO for remove… (backport #43762)
2024-11-08 10:58:57 +05:30
ruthra kumar
23e9a4607e Merge pull request #44022 from frappe/mergify/bp/version-15-hotfix/pr-43273
fix: improved the conditions for determining voucher subtypes (backport #43273)
2024-11-08 10:55:33 +05:30
bhaveshkumar.j
978a0078d8 fix: NoneType while updating ordered_qty in SO for removed items
(cherry picked from commit 442cdd7ce4)
2024-11-08 05:11:25 +00:00
ruthra kumar
6649d17b06 chore: resolve conflict 2024-11-08 10:33:56 +05:30
Smit Vora
d7f91824c0 test: test voucher subtype for sales invoice
(cherry picked from commit ad6cc352f1)
2024-11-08 04:51:12 +00:00
ljain112
107d53b358 fix: patch
(cherry picked from commit d76cc21086)

# Conflicts:
#	erpnext/patches.txt
2024-11-08 04:51:12 +00:00
ljain112
58ca4a2b99 fix: improved the conditions for determining voucher subtypes
(cherry picked from commit 00eee16190)
2024-11-08 04:51:11 +00:00
Frappe PR Bot
4819535a52 chore(release): Bumped to Version 15.41.1
## [15.41.1](https://github.com/frappe/erpnext/compare/v15.41.0...v15.41.1) (2024-11-07)

### Bug Fixes

* ensure list has items ([633997b](633997b1b0))
* error when saving POS merge log ([#43989](https://github.com/frappe/erpnext/issues/43989)) ([c3e61ae](c3e61aebd2))
* removed single quotes from deferred revenue ([#43985](https://github.com/frappe/erpnext/issues/43985)) ([20033ee](20033eef9b))
* task showing limit in customer portal (backport [#44003](https://github.com/frappe/erpnext/issues/44003)) ([#44005](https://github.com/frappe/erpnext/issues/44005)) ([47a8fc2](47a8fc28df))
* Update `dimension_filter_map` query ([318830c](318830c57d))
2024-11-07 12:44:29 +00:00
Sagar Vora
7d8d9cfdfe Merge pull request #44008 from frappe/version-15-hotfix 2024-11-07 18:13:13 +05:30
ruthra kumar
ff4751c9e8 refactor: handle PR's in advance stage
(cherry picked from commit 18c13a2cff)
2024-11-07 09:51:10 +00:00
ruthra kumar
eeff0a1252 refactor: cancel old PR and invalidate tokens
(cherry picked from commit cda7800777)
2024-11-07 09:51:10 +00:00
mergify[bot]
47a8fc28df fix: task showing limit in customer portal (backport #44003) (#44005)
fix: task showing limit in customer portal (#44003)

(cherry picked from commit 44832c3b5c)

Co-authored-by: Nihantra C. Patel <141945075+Nihantra-Patel@users.noreply.github.com>
2024-11-07 12:49:27 +05:30
Smit Vora
5dca98a1cf Merge pull request #43997 from Abdeali099/update-dimension-filter-query 2024-11-06 19:36:46 +05:30
Abdeali Chharchhoda
318830c57d fix: Update dimension_filter_map query 2024-11-06 19:16:01 +05:30
Sagar Vora
f4d2ba5bbd Merge pull request #43995 from frappe/mergify/bp/version-15-hotfix/pr-43993
fix: ensure list has items (backport #43993)
2024-11-06 14:08:33 +05:30
Sagar Vora
633997b1b0 fix: ensure list has items
(cherry picked from commit e13e688987)
2024-11-06 08:38:09 +00:00
Sagar Vora
36b22e290a Merge pull request #43991 from frappe/mergify/bp/version-15-hotfix/pr-43989
fix: error when saving POS merge log (backport #43989)
2024-11-06 13:26:02 +05:30
Sagar Vora
c3e61aebd2 fix: error when saving POS merge log (#43989)
(cherry picked from commit c62596b323)
2024-11-06 07:52:15 +00:00
Sagar Vora
de0c6f2ca9 Merge pull request #43987 from frappe/mergify/bp/version-15-hotfix/pr-43985
fix: removed single quotes from deferred revenue (backport #43985)
2024-11-06 12:05:17 +05:30
Nihantra C. Patel
20033eef9b fix: removed single quotes from deferred revenue (#43985)
(cherry picked from commit 834d18840c)
2024-11-06 06:33:34 +00:00
Frappe PR Bot
9ccdb987d9 chore(release): Bumped to Version 15.41.0
# [15.41.0](https://github.com/frappe/erpnext/compare/v15.40.0...v15.41.0) (2024-11-06)

### Bug Fixes

* add precision validation ([b665e4e](b665e4e24a))
* deleting SO/PO will remove its advance payment ledger entry ([d84a3c4](d84a3c4f29))
* map reference number while reversing journal ([10d8cc9](10d8cc9d66))
* **return:** set default return warehouse ([e730b8c](e730b8c6e4))
* SO link on PO and add in missing dashboard references on both ([9f7afda](9f7afda4db))
* validation trigger (backport [#43926](https://github.com/frappe/erpnext/issues/43926)) ([#43943](https://github.com/frappe/erpnext/issues/43943)) ([a689830](a689830bff))
* valuation rate for sales / purchase return for serial / batch nos (backport [#43925](https://github.com/frappe/erpnext/issues/43925)) ([#43942](https://github.com/frappe/erpnext/issues/43942)) ([ce42d84](ce42d847b3))

### Features

* advance payment ledger doctype ([b343334](b343334f69))
* remove Payroll Entry from Bank Account dashboard (backport [#43931](https://github.com/frappe/erpnext/issues/43931)) ([#43933](https://github.com/frappe/erpnext/issues/43933)) ([4a749ce](4a749cec72))

### Performance Improvements

* avoid reposting of entries created after stock reco (backport [#43950](https://github.com/frappe/erpnext/issues/43950)) ([#43961](https://github.com/frappe/erpnext/issues/43961)) ([7ad664d](7ad664d89a))
* too many writes error during reposting (backport [#43978](https://github.com/frappe/erpnext/issues/43978)) ([#43983](https://github.com/frappe/erpnext/issues/43983)) ([a38819c](a38819cbd5))
2024-11-06 05:21:49 +00:00
ruthra kumar
a6c58a3542 Merge pull request #43975 from frappe/version-15-hotfix
chore: release v15
2024-11-06 10:50:24 +05:30
mergify[bot]
ceccd8c2dc chore: update serial_batch_bundle.py (backport #43981) (#43984)
chore: update serial_batch_bundle.py (#43981)

Avaliable -> Available

(cherry picked from commit 30954ed645)

Co-authored-by: Ikko Eltociear Ashimine <eltociear@gmail.com>
2024-11-06 10:30:06 +05:30
mergify[bot]
a38819cbd5 perf: too many writes error during reposting (backport #43978) (#43983)
perf: too many writes error during reposting (#43978)

perf: too many writes error
(cherry picked from commit 134c24b9c5)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-06 10:05:44 +05:30
Khushi Rawat
801940912a Merge pull request #43980 from frappe/mergify/bp/version-15-hotfix/pr-43979
fix: added precision validation (backport #43979)
2024-11-06 01:45:53 +05:30
Khushi Rawat
b665e4e24a fix: add precision validation
(cherry picked from commit 7daadcf420)
2024-11-05 19:03:26 +00:00
ruthra kumar
e4d94af019 Merge pull request #43973 from frappe/mergify/bp/version-15-hotfix/pr-43971
refactor: update permission requirement for advance ledger (backport #43971)
2024-11-05 11:20:10 +05:30
ruthra kumar
eaf6d0d7d8 refactor: update advance ledger role requirement
(cherry picked from commit e41560d30b)
2024-11-05 05:30:13 +00:00
ruthra kumar
1b8bd0e1f3 refactor: avoid permission issue for non-admin
(cherry picked from commit c832d9fb9a)
2024-11-05 05:30:13 +00:00
ruthra kumar
ce817cbc12 Merge pull request #43965 from frappe/mergify/bp/version-15-hotfix/pr-43388
fix: SO link on PO and add in missing dashboard references on both (backport #43388)
2024-11-04 14:27:34 +05:30
CaseSolved
84a40c282b chore: linting
(cherry picked from commit be6970c850)
2024-11-04 08:32:21 +00:00
CaseSolved
9f7afda4db fix: SO link on PO and add in missing dashboard references on both
(cherry picked from commit 2017fd80d1)
2024-11-04 08:32:21 +00:00
ruthra kumar
ddd50167a5 Merge pull request #43447 from frappe/mergify/bp/version-15-hotfix/pr-43446
fix(return): set default return warehouse (backport #43446)
2024-11-04 13:26:01 +05:30
mergify[bot]
7ad664d89a perf: avoid reposting of entries created after stock reco (backport #43950) (#43961)
perf: avoid reposting of entries created after stock reco (#43950)

(cherry picked from commit 7cfe1c8d59)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-04 13:23:44 +05:30
ruthra kumar
5eb252215c Merge pull request #43959 from frappe/mergify/bp/version-15-hotfix/pr-43929
fix: Map reference number while reversing Journal Entry (backport #43929)
2024-11-04 13:15:31 +05:30
ramyasusee
10d8cc9d66 fix: map reference number while reversing journal
(cherry picked from commit 77de783cd4)
2024-11-04 06:58:58 +00:00
ruthra kumar
64f616b8a7 Merge pull request #43956 from frappe/mergify/bp/version-15-hotfix/pr-43835
Update fiscal_year.js (backport #43835)
2024-11-04 11:26:03 +05:30
hyaray
9a2b0a965d refactor: use year current year start date as default
(cherry picked from commit d54283ded5)
2024-11-04 05:48:42 +00:00
ruthra kumar
ec465571d8 Merge pull request #43946 from frappe/mergify/bp/version-15-hotfix/pr-43709
feat: Ledger for advance payment (backport #43709)
2024-11-04 10:53:21 +05:30
mergify[bot]
ce42d847b3 fix: valuation rate for sales / purchase return for serial / batch nos (backport #43925) (#43942)
fix: valuation rate for sales / purchase return for serial / batch nos (#43925)

(cherry picked from commit 01bb1612da)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-03 04:20:20 +05:30
mergify[bot]
a689830bff fix: validation trigger (backport #43926) (#43943)
fix: validation trigger (#43926)

(cherry picked from commit ba9fb4effc)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-03 04:20:01 +05:30
ruthra kumar
9bfcad31fd refactor: replace non-existant IntegrationTestCase 2024-11-01 20:08:07 +05:30
ruthra kumar
426010e21a refactor: fetch correct hook variable 2024-11-01 14:14:03 +05:30
ruthra kumar
ba09ddcc3a chore: resolve conflict 2024-11-01 14:10:45 +05:30
ruthra kumar
d0a655d5ae test: PO advance and currency from journal
(cherry picked from commit cf7b8f1b41)
2024-11-01 08:35:08 +00:00
ruthra kumar
91a276d4ed test: PO 'Advance Paid' and curreny when using payment
(cherry picked from commit ca85c75e39)
2024-11-01 08:35:08 +00:00
ruthra kumar
16c1fc75b5 chore: move tests to advance payment ledger doctype
(cherry picked from commit 14cef3d4c4)
2024-11-01 08:35:08 +00:00
ruthra kumar
7f9ae4e044 test: advance and currency from Journal
(cherry picked from commit 1825082512)
2024-11-01 08:35:07 +00:00
ruthra kumar
c8be4f3f78 refactor: use dr / cr account currency field for journals
(cherry picked from commit 9c1a4e284c)
2024-11-01 08:35:07 +00:00
ruthra kumar
d830ce1d88 test: USD Sales Order with advance payment
(cherry picked from commit 6c731561f3)
2024-11-01 08:35:07 +00:00
ruthra kumar
07a394a1c5 refactor: handle currency on advance payment ledger
(cherry picked from commit ae6a81cd07)
2024-11-01 08:35:07 +00:00
ruthra kumar
68a95c7dbc refactor: move creation logic to controller
(cherry picked from commit ad88bde448)
2024-11-01 08:35:07 +00:00
ruthra kumar
164d7cc896 refactor: handle 'no data' situation in patch
(cherry picked from commit 8e3bf7dc09)
2024-11-01 08:35:07 +00:00
ruthra kumar
063cef576c chore: update ignore_linked_doctypes for Journal Entry
(cherry picked from commit 767ae6a372)
2024-11-01 08:35:06 +00:00
ruthra kumar
c6bfdcf503 chore: update patchex.txt
(cherry picked from commit 8ab7194b1d)
2024-11-01 08:35:06 +00:00
ruthra kumar
085e0455d8 refactor: patch to migrating old SO / PO to advance ledger
(cherry picked from commit b927f2f4a0)
2024-11-01 08:35:06 +00:00
ruthra kumar
cb36dcb382 refactor(test): reconciliation shouldn't affect advance paid
(cherry picked from commit 35a8a18728)
2024-11-01 08:35:06 +00:00
ruthra kumar
ffd426d43d refactor: link journal entry to advance payment ledger
(cherry picked from commit fca5e95248)
2024-11-01 08:35:06 +00:00
ruthra kumar
d84a3c4f29 fix: deleting SO/PO will remove its advance payment ledger entry
(cherry picked from commit 14357bccba)
2024-11-01 08:35:06 +00:00
ruthra kumar
a12df122a9 refactor(test): advance_paid stays after reconciliation
(cherry picked from commit c4197c3f31)
2024-11-01 08:35:05 +00:00
ruthra kumar
df25d33735 chore: remove duplicate test class
(cherry picked from commit e2891a60d5)
2024-11-01 08:35:05 +00:00
ruthra kumar
a6c26874c7 refactor: remove advance payment ledgers on document deletion
(cherry picked from commit 3c53b92f05)
2024-11-01 08:35:05 +00:00
ruthra kumar
54f758c327 refactor: calculate advance from advance ledger
(cherry picked from commit 2b2360bf7b)

# Conflicts:
#	erpnext/controllers/accounts_controller.py
2024-11-01 08:35:05 +00:00
ruthra kumar
bf0b74bcbd refactor: create advance ledger entries on submit and cancel
(cherry picked from commit 575ca5b900)
2024-11-01 08:35:04 +00:00
ruthra kumar
0d02f8b5d1 refactor: make all fields readonly
(cherry picked from commit f176a82198)
2024-11-01 08:35:04 +00:00
ruthra kumar
b343334f69 feat: advance payment ledger doctype
(cherry picked from commit 2d6efd7cc8)
2024-11-01 08:35:04 +00:00
mergify[bot]
4a749cec72 feat: remove Payroll Entry from Bank Account dashboard (backport #43931) (#43933)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2024-10-30 15:49:26 +01:00
Frappe PR Bot
3648f3816f chore(release): Bumped to Version 15.40.0
# [15.40.0](https://github.com/frappe/erpnext/compare/v15.39.6...v15.40.0) (2024-10-30)

### Bug Fixes

* add company filter for project ([33fa1e4](33fa1e45ad))
* add parenttype clause to invoice tax query in sales_register report ([603d2cf](603d2cf77d))
* backport translations from develop ([#43849](https://github.com/frappe/erpnext/issues/43849)) ([11dd196](11dd1968c7))
* basic rate not editable in Stock Entry Detail (backport [#43837](https://github.com/frappe/erpnext/issues/43837)) ([#43838](https://github.com/frappe/erpnext/issues/43838)) ([20478b6](20478b632f))
* better implementation, handle missing purchase order ([41db040](41db040a60))
* Calculate gross margin on update of project costing from invoices (backport [#43876](https://github.com/frappe/erpnext/issues/43876)) ([#43900](https://github.com/frappe/erpnext/issues/43900)) ([93d0db2](93d0db2910))
* calculate tds with net amount when invoice exceeds single threshold amount (backport [#43869](https://github.com/frappe/erpnext/issues/43869)) ([#43920](https://github.com/frappe/erpnext/issues/43920)) ([9a52661](9a526611e0))
* cannot create opp from lead without prospect ([4dcaf42](4dcaf42bc5))
* consider gle based on balances in company currency ([#43805](https://github.com/frappe/erpnext/issues/43805)) ([2fb4417](2fb441763a))
* consider opening asset values while calculating asset depreciation rate ([1af2326](1af2326a52))
* correct garbage value on Razorpay Payments Page ([2c21df2](2c21df2ad9))
* do not check for payment terms details for return invoices. ([9a5604c](9a5604c5bb))
* do not copy serial numbers from DN to SI (backport [#43885](https://github.com/frappe/erpnext/issues/43885)) ([#43893](https://github.com/frappe/erpnext/issues/43893)) ([d06831e](d06831ea94))
* do not set payment terms for return invoices ([a826a89](a826a894f4))
* find first PCV to consider opening entries ([8218ca9](8218ca990c))
* Handle None value for item description in customer portal invoice view (backport [#43823](https://github.com/frappe/erpnext/issues/43823)) ([#43889](https://github.com/frappe/erpnext/issues/43889)) ([8a72845](8a72845ee6))
* hide payment terms for return and paid purchase invoices ([29aa5d6](29aa5d6468))
* incorrect value of available_qty_for_consumption in subcontracti… (backport [#43836](https://github.com/frappe/erpnext/issues/43836)) ([#43861](https://github.com/frappe/erpnext/issues/43861)) ([cd4746a](cd4746ad2a))
* map doc from purchase order ([58a3ef7](58a3ef7aa6))
* Patch for reposting account closing balance (backport [#43905](https://github.com/frappe/erpnext/issues/43905)) ([#43910](https://github.com/frappe/erpnext/issues/43910)) ([ab16207](ab162070a6))
* post account closing balance against pcv closing account (backport [#43887](https://github.com/frappe/erpnext/issues/43887)) ([#43898](https://github.com/frappe/erpnext/issues/43898)) ([e22d0a3](e22d0a3406))
* purchase return validation issue (backport [#43871](https://github.com/frappe/erpnext/issues/43871)) (backport [#43874](https://github.com/frappe/erpnext/issues/43874)) ([#43879](https://github.com/frappe/erpnext/issues/43879)) ([db3be41](db3be4195c))
* recalculate outstanding after save on checkout for POS Invoice ([63668eb](63668eb855))
* remarks field in payment reconciliation ([8707090](870709079b))
* **RFQ:** make strings translatable (backport [#43843](https://github.com/frappe/erpnext/issues/43843)) ([#43848](https://github.com/frappe/erpnext/issues/43848)) ([07aaef2](07aaef2af2))
* rounding issue of required qty in subcontracting order ([#43908](https://github.com/frappe/erpnext/issues/43908)) ([9ac87bd](9ac87bd3b1))
* scrub "-" from fieldname in accounting dimension ([c702826](c70282663c))
* set bill_no before `against_voucher` gets concatenated ([81297ce](81297ce168))
* set default warehouse for pos invoice ([b80a5f2](b80a5f27a9))
* set proper currency format ([9f97018](9f970189fe))
* Unnecessary validation for non deferred sales invoices ([#43816](https://github.com/frappe/erpnext/issues/43816)) ([bf4fb53](bf4fb53575))
* use period closing voucher object to call get_account_closing_ba… (backport [#43880](https://github.com/frappe/erpnext/issues/43880)) ([#43883](https://github.com/frappe/erpnext/issues/43883)) ([8bfc212](8bfc212e26))
* validate fieldname ([b21abf4](b21abf4d90))
* work order finish button not showing (backport [#43875](https://github.com/frappe/erpnext/issues/43875)) (backport [#43877](https://github.com/frappe/erpnext/issues/43877)) ([#43904](https://github.com/frappe/erpnext/issues/43904)) ([7189dab](7189daba19))

### Features

* add party name in payment request ([935f2e1](935f2e11e8))

### Performance Improvements

* performance optimizations for accounting reports by refactoring account closing balance and period closing voucher ([#43798](https://github.com/frappe/erpnext/issues/43798)) ([ced76ca](ced76ca5c0))
2024-10-30 09:55:19 +00:00
ruthra kumar
6da359a839 Merge pull request #43891 from frappe/version-15-hotfix
chore: release v15
2024-10-30 15:23:57 +05:30
Shariq Ansari
5ea498062c Merge pull request #43927 from frappe/mergify/bp/version-15-hotfix/pr-43921
fix: cannot create opp from lead without prospect (backport #43921)
2024-10-30 14:40:00 +05:30
Shariq Ansari
4dcaf42bc5 fix: cannot create opp from lead without prospect
(cherry picked from commit 603383bca7)
2024-10-30 08:18:53 +00:00
mergify[bot]
db3be4195c fix: purchase return validation issue (backport #43871) (backport #43874) (#43879)
fix: purchase return validation issue (backport #43871) (#43874)

fix: purchase return validation issue (#43871)

(cherry picked from commit a7cc7b28c0)

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

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-10-30 12:17:46 +05:30
mergify[bot]
9a526611e0 fix: calculate tds with net amount when invoice exceeds single threshold amount (backport #43869) (#43920)
* fix: calculate tds with net amount when invoice exceeds single threshold amount

(cherry picked from commit ef694a40a1)

* test: add unit test to validate purchase invoice exceeding single threshold value

(cherry picked from commit 94badb464d)

---------

Co-authored-by: venkat102 <venkatesharunachalam659@gmail.com>
2024-10-30 11:25:56 +05:30
Nabin Hait
9ac87bd3b1 fix: rounding issue of required qty in subcontracting order (#43908)
* fix: rounding issue of required qty in subcontracting order

* fix: uom issue in test case

* fix: test case

* fix: restored report tests for manufacturing
2024-10-30 11:25:08 +05:30
Nabin Hait
0171af4604 Merge branch 'version-15' into version-15-hotfix 2024-10-30 11:23:52 +05:30
ruthra kumar
3ab31dcb92 Merge pull request #43917 from frappe/mergify/bp/version-15-hotfix/pr-43886
fix: remarks field in payment reconciliation (backport #43886)
2024-10-30 10:43:58 +05:30
ruthra kumar
63ecf13058 Merge pull request #43918 from frappe/mergify/bp/version-15-hotfix/pr-43913
fix: find first PCV to consider opening entries (backport #43913)
2024-10-30 10:43:47 +05:30
Nabin Hait
8218ca990c fix: find first PCV to consider opening entries
(cherry picked from commit 2201fc62a2)
2024-10-30 04:55:31 +00:00
ruthra kumar
ac121dd4e3 chore: resolve conflict 2024-10-30 10:23:41 +05:30
Ahmed Shareef
870709079b fix: remarks field in payment reconciliation
(cherry picked from commit 2d5b079949)

# Conflicts:
#	erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json
2024-10-30 04:50:27 +00:00
ruthra kumar
302f049025 Merge pull request #43915 from frappe/mergify/bp/version-15-hotfix/pr-43884
fix: recalculate outstanding after save on checkout for POS Invoice (backport #43884)
2024-10-30 10:19:50 +05:30
ljain112
63668eb855 fix: recalculate outstanding after save on checkout for POS Invoice
(cherry picked from commit 9ce2184c66)
2024-10-30 04:37:19 +00:00
Khushi Rawat
9a93c892be Merge pull request #43912 from frappe/mergify/bp/version-15-hotfix/pr-43899
fix: consider opening asset values while calculating depreciation rate (backport #43899)
2024-10-30 00:24:47 +05:30
Khushi Rawat
1af2326a52 fix: consider opening asset values while calculating asset depreciation rate
(cherry picked from commit 9d0fe7aa56)
2024-10-29 18:36:31 +00:00
mergify[bot]
ab162070a6 fix: Patch for reposting account closing balance (backport #43905) (#43910)
fix: Patch for reposting account closing balance (#43905)

(cherry picked from commit 3a0d27b393)

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2024-10-29 23:22:29 +05:30
Frappe PR Bot
d8e1a21bdc chore(release): Bumped to Version 15.39.6
## [15.39.6](https://github.com/frappe/erpnext/compare/v15.39.5...v15.39.6) (2024-10-29)

### Bug Fixes

* Patch for reposting account closing balance (backport [#43905](https://github.com/frappe/erpnext/issues/43905)) ([#43909](https://github.com/frappe/erpnext/issues/43909)) ([c2eb771](c2eb771c4d))
2024-10-29 17:39:33 +00:00
mergify[bot]
c2eb771c4d fix: Patch for reposting account closing balance (backport #43905) (#43909)
fix: Patch for reposting account closing balance (#43905)

(cherry picked from commit 3a0d27b393)

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2024-10-29 23:07:58 +05:30
mergify[bot]
8a72845ee6 fix: Handle None value for item description in customer portal invoice view (backport #43823) (#43889)
fix: Handle None value for item description in customer portal invoice view

(cherry picked from commit ceb449c75b)

Co-authored-by: ljain112 <ljain112@gmail.com>
2024-10-29 22:38:41 +05:30
mergify[bot]
7189daba19 fix: work order finish button not showing (backport #43875) (backport #43877) (#43904)
fix: work order finish button not showing (backport #43875) (#43877)

* fix: work order finish button not showing (#43875)

(cherry picked from commit 0a70be5b99)

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

* chore: fix conflicts

* chore: fix conflicts

* chore: fix conflicts

---------

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

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-10-29 22:37:26 +05:30
mergify[bot]
93d0db2910 fix: Calculate gross margin on update of project costing from invoices (backport #43876) (#43900)
* fix: Calculate gross margin on update of project costing from invoices (#43876)

* fix: Calculate gross margin on update of project costing from invoices

* chore: linter issues

(cherry picked from commit 0bba6442c0)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json

* fix: merge conflict

---------

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2024-10-29 22:36:39 +05:30
Frappe PR Bot
50db0aca61 chore(release): Bumped to Version 15.39.5
## [15.39.5](https://github.com/frappe/erpnext/compare/v15.39.4...v15.39.5) (2024-10-29)

### Bug Fixes

* post account closing balance against pcv closing account ([#43887](https://github.com/frappe/erpnext/issues/43887)) ([becfd98](becfd980b2))
2024-10-29 15:39:40 +00:00
ruthra kumar
b5d2708f69 Merge pull request #43902 from frappe/mergify/bp/version-15/pr-43887
fix: post account closing balance against pcv closing account (backport #43887)
2024-10-29 21:08:20 +05:30
Nabin Hait
becfd980b2 fix: post account closing balance against pcv closing account (#43887)
(cherry picked from commit 34295d0344)
2024-10-29 15:37:05 +00:00
Frappe PR Bot
be6cd6adc3 chore(release): Bumped to Version 15.39.4
## [15.39.4](https://github.com/frappe/erpnext/compare/v15.39.3...v15.39.4) (2024-10-29)

### Bug Fixes

* use period closing voucher object to call get_account_closing_ba… ([#43880](https://github.com/frappe/erpnext/issues/43880)) ([94a03c6](94a03c6e17))
2024-10-29 15:34:46 +00:00
ruthra kumar
48939f25c8 Merge pull request #43901 from frappe/mergify/bp/version-15/pr-43880
fix: use period closing voucher object to call get_account_closing_ba… (backport #43880)
2024-10-29 21:03:20 +05:30
Venkatesh
94a03c6e17 fix: use period closing voucher object to call get_account_closing_ba… (#43880)
fix: use period closing voucher object to call get_account_closing_balances method
(cherry picked from commit 99d1c5f342)
2024-10-29 15:15:11 +00:00
mergify[bot]
cd4746ad2a fix: incorrect value of available_qty_for_consumption in subcontracti… (backport #43836) (#43861)
fix: incorrect value of available_qty_for_consumption in subcontracti… (#43836)

fix: incorrect value of available_qty_for_consumption in subcontracting receipt
(cherry picked from commit ad6ce09b86)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-10-29 17:58:40 +05:30
mergify[bot]
e22d0a3406 fix: post account closing balance against pcv closing account (backport #43887) (#43898)
fix: post account closing balance against pcv closing account (#43887)

(cherry picked from commit 34295d0344)

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2024-10-29 17:25:40 +05:30
ruthra kumar
1755006445 Merge pull request #43897 from frappe/mergify/bp/version-15-hotfix/pr-43856
fix: add parenttype clause to invoice tax query in sales_register report (backport #43856)
2024-10-29 16:13:02 +05:30
ruthra kumar
4c9e17fbd3 Merge pull request #43895 from frappe/mergify/bp/version-15-hotfix/pr-43698
fix: Project name instead of ID in chart (backport #43698)
2024-10-29 16:12:23 +05:30
mergify[bot]
d06831ea94 fix: do not copy serial numbers from DN to SI (backport #43885) (#43893)
fix: do not copy serial numbers from DN to SI (#43885)

(cherry picked from commit 0c93bc31a5)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-10-29 15:48:40 +05:30
Imesha Sudasingha
603d2cf77d fix: add parenttype clause to invoice tax query in sales_register report
(cherry picked from commit e30ab141f4)
2024-10-29 10:10:41 +00:00
lukas.brandhoff
13557a2c10 refactor: include 'Project Name' in Project summary report
Keep name field for backwards compatibility

(cherry picked from commit 736d1a1105)
2024-10-29 09:54:25 +00:00
ruthra kumar
218c51cdcf Merge pull request #43812 from frappe/mergify/bp/version-15-hotfix/pr-43793
chore(Timesheet): add type hints (backport #43793)
2024-10-29 14:46:45 +05:30
ruthra kumar
61a11c8f1f Merge pull request #43888 from frappe/mergify/bp/version-15-hotfix/pr-43824
fix: accounting dimension fieldname (backport #43824)
2024-10-29 14:35:30 +05:30
ljain112
b21abf4d90 fix: validate fieldname
(cherry picked from commit ca31a19eb7)
2024-10-29 08:16:31 +00:00
ljain112
c70282663c fix: scrub "-" from fieldname in accounting dimension
(cherry picked from commit 023b7b9a60)
2024-10-29 08:16:31 +00:00
ruthra kumar
87e0d2f7f4 Merge pull request #43882 from frappe/mergify/bp/version-15-hotfix/pr-43803
feat: add party name in payment request (backport #43803)
2024-10-29 12:15:48 +05:30
mergify[bot]
8bfc212e26 fix: use period closing voucher object to call get_account_closing_ba… (backport #43880) (#43883)
fix: use period closing voucher object to call get_account_closing_ba… (#43880)

fix: use period closing voucher object to call get_account_closing_balances method
(cherry picked from commit 99d1c5f342)

Co-authored-by: Venkatesh <47534423+venkat102@users.noreply.github.com>
2024-10-29 12:08:24 +05:30
ruthra kumar
a937e32989 chore: resolve conflict 2024-10-29 11:55:50 +05:30
RAVIBHARATHI P C
935f2e11e8 feat: add party name in payment request
(cherry picked from commit 0acb609d97)

# Conflicts:
#	erpnext/accounts/doctype/payment_request/payment_request.py
2024-10-29 05:48:18 +00:00
ruthra kumar
7202939e0d Merge pull request #40813 from frappe/mergify/bp/version-15-hotfix/pr-40720
Set default warehouse for pos invoice (backport #40720)
2024-10-29 10:05:32 +05:30
ruthra kumar
73a8b6a7d7 Merge pull request #43864 from frappe/mergify/bp/version-15-hotfix/pr-43685
fix: do not check for payment terms details for return invoices. (backport #43685)
2024-10-28 15:52:45 +05:30
ruthra kumar
303ae8321b chore: resolve conflict 2024-10-28 13:33:24 +05:30
ruthra kumar
d5e1a46588 Merge pull request #43866 from ruthra-kumar/fix_whitespace
chore: fix whitespace
2024-10-28 12:10:52 +05:30
ruthra kumar
27108874ea chore: replace whitespace with tab 2024-10-28 11:50:55 +05:30
ljain112
29aa5d6468 fix: hide payment terms for return and paid purchase invoices
(cherry picked from commit 912e1e3f3d)

# Conflicts:
#	erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
2024-10-28 05:55:07 +00:00
ljain112
a826a894f4 fix: do not set payment terms for return invoices
(cherry picked from commit 8b700eadc7)
2024-10-28 05:55:07 +00:00
ljain112
9a5604c5bb fix: do not check for payment terms details for return invoices.
(cherry picked from commit 6703b7d1ae)
2024-10-28 05:55:07 +00:00
ruthra kumar
b95dfcbce0 Merge pull request #42607 from Abhishek-Chougule/version-15-hotfix
fix: correct garbage value on Razorpay Payments Page
2024-10-28 10:07:25 +05:30
ruthra kumar
ed01b4c161 Merge pull request #43857 from frappe/mergify/bp/version-15-hotfix/pr-43833
refactor: query for expense_account moved to setup hook in purchase invoice (backport #43833)
2024-10-28 09:53:03 +05:30
ljain112
19db526fdd refactor: query for expense_account moved to setup hook in purchase invoice
(cherry picked from commit a9ac0cc223)
2024-10-28 04:14:13 +00:00
Raffael Meyer
11dd1968c7 fix: backport translations from develop (#43849) 2024-10-26 20:25:30 +02:00
mergify[bot]
07aaef2af2 fix(RFQ): make strings translatable (backport #43843) (#43848)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
fix(RFQ): make strings translatable (#43843)
2024-10-26 19:43:23 +02:00
mergify[bot]
20478b632f fix: basic rate not editable in Stock Entry Detail (backport #43837) (#43838)
fix: basic rate not editable in Stock Entry Detail (#43837)

(cherry picked from commit 5a967bc868)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-10-25 20:21:01 +05:30
ruthra kumar
18f32b8de6 Merge pull request #43831 from frappe/mergify/bp/version-15-hotfix/pr-43830
fix: set bill_no before `against_voucher` gets concatenated (backport #43830)
2024-10-25 14:28:36 +05:30
ruthra kumar
81297ce168 fix: set bill_no before against_voucher gets concatenated
(cherry picked from commit 7bade7f1fe)
2024-10-25 08:31:43 +00:00
Frappe PR Bot
f48ce90658 chore(release): Bumped to Version 15.39.3
## [15.39.3](https://github.com/frappe/erpnext/compare/v15.39.2...v15.39.3) (2024-10-24)

### Bug Fixes

* Unnecessary validation for non deferred sales invoices ([#43816](https://github.com/frappe/erpnext/issues/43816)) ([a79bc4d](a79bc4d35a))
2024-10-24 08:22:31 +00:00
Deepesh Garg
3df68e462f Merge pull request #43818 from frappe/mergify/bp/version-15/pr-43817
fix: Unnecessary validation for non-deferred sales invoices (#43816)
2024-10-24 13:51:15 +05:30
mergify[bot]
a79bc4d35a fix: Unnecessary validation for non deferred sales invoices (#43816)
fix: Unnecessary validation for non deferred sales invoices (#43816)

(cherry picked from commit af472054f6)

Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
(cherry picked from commit bf4fb53575)
2024-10-24 08:14:16 +00:00
mergify[bot]
bf4fb53575 fix: Unnecessary validation for non deferred sales invoices (#43816)
fix: Unnecessary validation for non deferred sales invoices (#43816)

(cherry picked from commit af472054f6)

Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
2024-10-24 13:37:57 +05:30
Raffael Meyer
cf25f4c579 chore(Timesheet): add type hints (#43793)
(cherry picked from commit fe1e1b12c3)
2024-10-23 22:54:04 +00:00
Frappe PR Bot
188645bfd6 chore(release): Bumped to Version 15.39.2
## [15.39.2](https://github.com/frappe/erpnext/compare/v15.39.1...v15.39.2) (2024-10-23)

### Bug Fixes

* consider gle based on balances in company currency (copy [#43805](https://github.com/frappe/erpnext/issues/43805)) ([#43809](https://github.com/frappe/erpnext/issues/43809)) ([1c4eef2](1c4eef2ef6))
2024-10-23 12:12:56 +00:00
mergify[bot]
1c4eef2ef6 fix: consider gle based on balances in company currency (copy #43805) (#43809)
fix: consider gle based on balances in company currency (#43805)

(cherry picked from commit 2fb441763a)

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2024-10-23 17:41:41 +05:30
ruthra kumar
a3bf320add Merge pull request #42764 from frappe/mergify/bp/version-15-hotfix/pr-42458
fix: use company default currency in report (backport #42458)
2024-10-23 17:33:53 +05:30
ruthra kumar
d0db3b08d7 Merge pull request #43807 from frappe/mergify/bp/version-15-hotfix/pr-43755
fix: Add Company Filter (backport #43755)
2024-10-23 17:30:31 +05:30
Nabin Hait
2fb441763a fix: consider gle based on balances in company currency (#43805) 2024-10-23 17:08:52 +05:30
IamSaiyyamChhetri
33fa1e45ad fix: add company filter for project
- In Project dt Sales Order field
- In Sales Order dt Project field

(cherry picked from commit 9909d760a5)
2024-10-23 11:21:18 +00:00
Nabin Hait
d392660d45 chore: release version 15.39.1 (#43800)
* fix: map doc from purchase order

(cherry picked from commit 60ceb91ace)

* test: auto create purchase receipt

(cherry picked from commit 59887bbc13)

* fix: better implementation, handle missing purchase order

(cherry picked from commit 66211dafd6)

* perf: performance optimizations for accounting reports by refactoring account closing balance and period closing voucher (#43798)

* fix: Gl Entry form cleanup

* fix: Added indexes in gl entry table

* perf: Refactored period closing voucher to handle large volume of gle

* fix: fixes as per new period start and end date fields in PCV

* perf: performance optimization for  accounting reports

* perf: performance optimizations for account closing balance patch

* fix: test cases

* fix: lenter issues - direct use of sql query

* fix: test cases

* fix: test cases

* fix: test cases

* fix: wrong fieldname

* fix: test cases

---------

Co-authored-by: Ninad1306 <ninad_1063@yahoo.com>
Co-authored-by: Smit Vora <smitvora203@gmail.com>
2024-10-23 14:27:10 +05:30
Nabin Hait
ced76ca5c0 perf: performance optimizations for accounting reports by refactoring account closing balance and period closing voucher (#43798)
* fix: Gl Entry form cleanup

* fix: Added indexes in gl entry table

* perf: Refactored period closing voucher to handle large volume of gle

* fix: fixes as per new period start and end date fields in PCV

* perf: performance optimization for  accounting reports

* perf: performance optimizations for account closing balance patch

* fix: test cases

* fix: lenter issues - direct use of sql query

* fix: test cases

* fix: test cases

* fix: test cases

* fix: wrong fieldname

* fix: test cases
2024-10-23 13:07:16 +05:30
Smit Vora
9c0f17e13d Merge pull request #43788 from frappe/mergify/bp/version-15-hotfix/pr-43769
fix: mapping purchase receipt from subcontracting receipt is not required (backport #43769)
2024-10-23 10:36:48 +05:30
Frappe PR Bot
e0a45a5a54 chore(release): Bumped to Version 15.39.0
# [15.39.0](https://github.com/frappe/erpnext/compare/v15.38.4...v15.39.0) (2024-10-23)

### Bug Fixes

* "show_remarks" checkbox in Process statement of accounts ([f7717c9](f7717c91bc))
* added validation for UOM must be whole number (backport [#43710](https://github.com/frappe/erpnext/issues/43710)) ([#43712](https://github.com/frappe/erpnext/issues/43712)) ([60ffcd0](60ffcd0574))
* Call super onload_post_render inside pos_invoice.js ([1281d9d](1281d9d21d))
* coupon code validation logic ([aeaadb1](aeaadb1e30))
* **deferred_revenue:** Escape account in query ([fac27d9](fac27d9dff))
* do not make new depreciation for fully depreciated asset ([ddb38db](ddb38db5c4))
* Freeze Screen on load invoices on POS Closing Entry ([f343d5a](f343d5a24d))
* get party advance amount based on account ([b673377](b673377b70))
* get period estimate till service end date ([148d7e7](148d7e798b))
* get stock accounts from the doc instead of db in validate_stock_accounts ([39387e9](39387e9f54))
* incorrect amount in bank clearance ([52be45c](52be45c5df))
* lead create opp from connection not working ([9e56f21](9e56f213a3))
* list view and form status not same for purchase order (backport [#43690](https://github.com/frappe/erpnext/issues/43690)) ([#43692](https://github.com/frappe/erpnext/issues/43692)) ([a33d553](a33d5535a7))
* only show pay button for specific doctype in portal ([d2e5b2a](d2e5b2aa1d))
* party_balance based on company in payment entry ([04fbcc6](04fbcc64ff))
* remove extra space ([50dd8d9](50dd8d9df7))
* removed unmerged patches ([2e0cf36](2e0cf36901))
* Required Changes to Support e-Waybill Generation for Material Transfer Return ([#43061](https://github.com/frappe/erpnext/issues/43061)) ([2205ae8](2205ae8e54))
* show total amount on report summary ([ab20344](ab20344141))
* use correct variable in error message (backport [#43790](https://github.com/frappe/erpnext/issues/43790)) ([#43792](https://github.com/frappe/erpnext/issues/43792)) ([879b2b7](879b2b778a))
* Workspace link for Work Order Consumed Materials report (backport [#43753](https://github.com/frappe/erpnext/issues/43753)) ([#43754](https://github.com/frappe/erpnext/issues/43754)) ([1fa9030](1fa9030aee))

### Features

* added assignee email field in asset maintenance log ([a3b8f97](a3b8f9759d))
2024-10-23 04:48:23 +00:00
ruthra kumar
692de892ae Merge pull request #43774 from frappe/version-15-hotfix
chore: release v15
2024-10-23 10:17:07 +05:30
mergify[bot]
879b2b778a fix: use correct variable in error message (backport #43790) (#43792)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
fix: use correct variable in error message (#43790)
2024-10-22 19:43:16 +02:00
Smit Vora
12530616a7 Merge pull request #43786 from ljain112/fix-manual-backport 2024-10-22 20:12:53 +05:30
Ninad1306
41db040a60 fix: better implementation, handle missing purchase order
(cherry picked from commit 66211dafd6)
2024-10-22 14:42:51 +00:00
Ninad1306
40927c7413 test: auto create purchase receipt
(cherry picked from commit 59887bbc13)
2024-10-22 14:42:51 +00:00
Ninad1306
58a3ef7aa6 fix: map doc from purchase order
(cherry picked from commit 60ceb91ace)
2024-10-22 14:42:51 +00:00
Smit Vora
9ddf1ccedd Merge pull request #43785 from frappe/mergify/bp/version-15-hotfix/pr-43462
fix: get stock accounts from the doc in `validate_stock_accounts` in Journal Entry (backport #43462)
2024-10-22 19:59:31 +05:30
Smit Vora
0495160f81 Merge pull request #43783 from frappe/mergify/bp/version-15-hotfix/pr-43061
fix: Required Changes to Support e-Waybill Generation for Material Transfer Return (backport #43061)
2024-10-22 19:59:19 +05:30
ljain112
d2e5b2aa1d fix: only show pay button for specific doctype in portal 2024-10-22 19:49:37 +05:30
Vishakh Desai
39387e9f54 fix: get stock accounts from the doc instead of db in validate_stock_accounts
(cherry picked from commit 30954586d8)
2024-10-22 14:07:43 +00:00
Ninad Parikh
2205ae8e54 fix: Required Changes to Support e-Waybill Generation for Material Transfer Return (#43061)
(cherry picked from commit 004c4e21d4)
2024-10-22 13:59:31 +00:00
Frappe PR Bot
08cabd1717 chore(release): Bumped to Version 15.38.4
## [15.38.4](https://github.com/frappe/erpnext/compare/v15.38.3...v15.38.4) (2024-10-17)

### Bug Fixes

* list view and form status not same for purchase order (backport [#43690](https://github.com/frappe/erpnext/issues/43690)) ([#43692](https://github.com/frappe/erpnext/issues/43692)) ([752d175](752d175d22))
2024-10-17 16:05:56 +00:00
rohitwaghchaure
6f98fe15e4 Merge pull request #43706 from frappe/mergify/bp/version-15/pr-43692
fix: list view and form status not same for purchase order (backport #43690) (backport #43692)
2024-10-17 21:34:34 +05:30
mergify[bot]
752d175d22 fix: list view and form status not same for purchase order (backport #43690) (#43692)
* fix: list view and form status not same for purchase order (#43690)

(cherry picked from commit a671fe13d4)

# Conflicts:
#	erpnext/buying/doctype/purchase_order/purchase_order.js
#	erpnext/buying/doctype/purchase_order/purchase_order_list.js

* chore: fix conflicts

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit a33d5535a7)
2024-10-17 04:44:18 +00:00
Frappe PR Bot
99ead94ffe chore(release): Bumped to Version 15.38.3
## [15.38.3](https://github.com/frappe/erpnext/compare/v15.38.2...v15.38.3) (2024-10-16)

### Bug Fixes

* added parentheses for correct query formation for logical OR condition ([21a7dd4](21a7dd43a9))
* added string for translation in bank reconciliation statement ([e10a580](e10a58074f))
* conversion factor issue (backport [#43645](https://github.com/frappe/erpnext/issues/43645)) ([#43674](https://github.com/frappe/erpnext/issues/43674)) ([b2deb89](b2deb89826))
* delete invalid pricing rule on change of applicable_for ([5d6fc71](5d6fc71556))
* don't update reference to SI / PI on advances ([b72906a](b72906a7a1))
* ignore free item when qty is zero ([e5aaa5b](e5aaa5b6e5))
* incorrect warehouse in the serial no selector for rejection (backport [#43671](https://github.com/frappe/erpnext/issues/43671)) ([#43673](https://github.com/frappe/erpnext/issues/43673)) ([c490a66](c490a66540))
* Link opportunity from RFQ to supplier quotation ([eb1f125](eb1f1255eb))
* missing child company accounts in consolidated balance sheet ([4db12fe](4db12fe2da))
* quotation to so frappe crm (backport [#43644](https://github.com/frappe/erpnext/issues/43644)) ([#43646](https://github.com/frappe/erpnext/issues/43646)) ([f3ceb4a](f3ceb4ac7d))
* refetch items from BOM if 'Use Multi-Level BOM' has changed usin… (backport [#43672](https://github.com/frappe/erpnext/issues/43672)) ([#43676](https://github.com/frappe/erpnext/issues/43676)) ([492ba53](492ba539e8))
* removed unused query ([8668ae9](8668ae92d8))
* run gl_entries and closing voucher processes in same function ([ea12897](ea12897ce9))
* show incorrect entries filter in Stock Ledger Invariant Check report (backport [#43619](https://github.com/frappe/erpnext/issues/43619)) ([#43622](https://github.com/frappe/erpnext/issues/43622)) ([d604b12](d604b12d51))
* **stock:** Grab posting date/time from SABB (backport [#43493](https://github.com/frappe/erpnext/issues/43493)) ([#43502](https://github.com/frappe/erpnext/issues/43502)) ([cd9f949](cd9f949b12))
* update formatings ([c2c6d27](c2c6d27625))
* update formatings ([a70181e](a70181e025))
* update item details with actual quantity. ([930e79c](930e79c351))
* Use `ref_doc.get()` for `party_account_currency` ([928b6b1](928b6b1510))
* zero incoming rate for delivery note return ([#43642](https://github.com/frappe/erpnext/issues/43642)) ([85088e4](85088e4aff))
2024-10-16 05:01:44 +00:00
ruthra kumar
e05ae14d49 Merge pull request #43667 from frappe/version-15-hotfix
chore: release v15
2024-10-16 10:30:25 +05:30
Frappe PR Bot
ef1e121bd4 chore(release): Bumped to Version 15.38.2
## [15.38.2](https://github.com/frappe/erpnext/compare/v15.38.1...v15.38.2) (2024-10-13)

### Bug Fixes

* don't update reference to SI / PI on advances ([8bf8bcf](8bf8bcf739))
2024-10-13 05:23:41 +00:00
ruthra kumar
68f1b41969 Merge pull request #43633 from frappe/mergify/bp/version-15/pr-43627
fix: reconciled advance from reported in reconciliation tool (backport #43627)
2024-10-13 10:52:21 +05:30
ruthra kumar
a329003f7f chore: use correct hook for advance payment doctypes 2024-10-13 10:35:48 +05:30
ruthra kumar
cf1eabe049 chore: resolve conflict 2024-10-13 10:35:14 +05:30
ruthra kumar
4c78a682ad chore: better comments for context
(cherry picked from commit e7505e92c9)
2024-10-13 04:59:58 +00:00
ruthra kumar
4752ed2483 test: reconciled Invoice should not showup in tool
Scenario should be tested on 'Advance in separate party account'

(cherry picked from commit f1ec61c19e)
2024-10-13 04:59:58 +00:00
ruthra kumar
e56dd8268b test: unreconciliation of individual SO from Advance Payment
(cherry picked from commit 8a6978e550)
2024-10-13 04:59:58 +00:00
ruthra kumar
e0477cf59f refactor(test): utility methods for enabling advance in separate acc
(cherry picked from commit a21a406d04)

# Conflicts:
#	erpnext/accounts/test/accounts_mixin.py
2024-10-13 04:59:58 +00:00
ruthra kumar
8c115e146b refactor: use hooks to identify advance doctypes
(cherry picked from commit e7bb960bb5)
2024-10-13 04:59:58 +00:00
ruthra kumar
6267ab994c refactor: reference update logic in advance
(cherry picked from commit a112581acd)
2024-10-13 04:59:58 +00:00
ruthra kumar
8bf8bcf739 fix: don't update reference to SI / PI on advances
(cherry picked from commit b409f74620)
2024-10-13 04:59:57 +00:00
Frappe PR Bot
d46cf46375 chore(release): Bumped to Version 15.38.1
## [15.38.1](https://github.com/frappe/erpnext/compare/v15.38.0...v15.38.1) (2024-10-09)

### Bug Fixes

* 'NoneType' object has no attribute 'has_serial_no' (backport [#43514](https://github.com/frappe/erpnext/issues/43514)) ([#43574](https://github.com/frappe/erpnext/issues/43574)) ([60508a9](60508a9706))
* [#42014](https://github.com/frappe/erpnext/issues/42014) --resolve conflicts ([85d7405](85d74050e1))
* Accepted and Rejected warehouse cannot be same (backport [#43568](https://github.com/frappe/erpnext/issues/43568)) ([#43573](https://github.com/frappe/erpnext/issues/43573)) ([83ce3dd](83ce3dd915))
* add include closed orders option in so/po trends report v15 ([5660e8b](5660e8b26d))
* add parenttype condition for item table in Purchase Register Report ([8ce81a0](8ce81a058a))
* Add removed test code `b41f10c1b9` ([30fd11f](30fd11f138))
* allow to change the batch in the subcontracting receipt (backport [#43584](https://github.com/frappe/erpnext/issues/43584)) ([#43588](https://github.com/frappe/erpnext/issues/43588)) ([9e109ac](9e109acec7))
* create Account Closing Balance even though there are no transaction in period ([d6f70f5](d6f70f533a))
* creation of contact, customer, opportunity, quotation and prospect from lead ([ef10c4e](ef10c4ea4f))
* creation of contact, customer, opportunity, quotation and prospect from lead --prettier ([5a2a404](5a2a404a50))
* deduct advances adjusted for threshold check for tcs ([6decb7c](6decb7cc34))
* do not include advances for tds vouchers ([ee8485a](ee8485a54a))
* frappe dependency update ([0a70b3f](0a70b3ffcc))
* include parent item group in query ([55464c7](55464c79c4))
* make LCV button not working for PI and PR (backport [#43592](https://github.com/frappe/erpnext/issues/43592)) ([#43593](https://github.com/frappe/erpnext/issues/43593)) ([120b481](120b481c4a))
* multiple issues in Payment Request ([#42427](https://github.com/frappe/erpnext/issues/42427)) ([ea69ba7](ea69ba7cd8))
* production plan bom error (backport [#43591](https://github.com/frappe/erpnext/issues/43591)) ([#43594](https://github.com/frappe/erpnext/issues/43594)) ([029021f](029021f035))
* read only filters in multidialog fields (backport [#43503](https://github.com/frappe/erpnext/issues/43503)) ([#43513](https://github.com/frappe/erpnext/issues/43513)) ([d69a974](d69a974a4d))
* Remove `advance_payment_status` uses ([907e3af](907e3af1b0))
* Remove unreference method ([770bc1c](770bc1c293))
* Remove unused  field ([e785928](e785928c0f))
* Remove unused function `get_paid_amount_against_order` ([7591662](75916629c8))
* Separate `on_submit` and `before_submit` of PR ([dbd7b83](dbd7b83204))
* the purchase receipt trends and delivery note trends report (backport [#43585](https://github.com/frappe/erpnext/issues/43585)) ([#43587](https://github.com/frappe/erpnext/issues/43587)) ([355ba2f](355ba2f632))
* Unknown column 'serial_no' in 'field list' (backport [#43515](https://github.com/frappe/erpnext/issues/43515)) ([#43569](https://github.com/frappe/erpnext/issues/43569)) ([fc9a3c0](fc9a3c0c92))
* Update Values before `after_mapping` hook is called ([#42682](https://github.com/frappe/erpnext/issues/42682)) ([6770610](6770610c6d))
* validation for corrective job card (backport [#43555](https://github.com/frappe/erpnext/issues/43555)) ([#43558](https://github.com/frappe/erpnext/issues/43558)) ([cf0fa0d](cf0fa0db7b))
2024-10-09 12:02:42 +00:00
rohitwaghchaure
c3f6edcd01 Merge pull request #43563 from frappe/version-15-hotfix
chore: release v15
2024-10-09 17:31:15 +05:30
mergify[bot]
05db28c64f chore: Allow apps to extend voucher subtypes (backport #43528) (backport #43550) (#43551)
chore: Allow apps to extend voucher subtypes (#43528)

* chore: Allow apps to extend voucher subtypes

(cherry picked from commit a1525d9b8e)

* chore: Allow apps to extend voucher subtypes

(cherry picked from commit 8a1e38a43b)

* chore: Allow apps to extend voucher subtypes

(cherry picked from commit ca8820b566)

---------

Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
(cherry picked from commit bcd0105915)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-10-08 09:20:34 +05:30
Frappe PR Bot
edfa6e41e1 chore(release): Bumped to Version 15.38.0
# [15.38.0](https://github.com/frappe/erpnext/compare/v15.37.0...v15.38.0) (2024-10-04)

### Bug Fixes

* 'NoneType' object has no attribute 'has_serial_no' ([21a0157](21a01575b6))
* add company filter in Warehouse wise Item Balance Age and Value ([4fc6d3e](4fc6d3ef64))
* adjustmen entry for stock reco ([c551c27](c551c2714c))
* Cannot read properties of undefined (reading 'price_list_rate') (backport [#43376](https://github.com/frappe/erpnext/issues/43376)) ([#43377](https://github.com/frappe/erpnext/issues/43377)) ([47f06dc](47f06dc180))
* Data missing in table: None, MandatoryError (backport [#43422](https://github.com/frappe/erpnext/issues/43422)) ([#43429](https://github.com/frappe/erpnext/issues/43429)) ([4b3f143](4b3f143f83))
* **Dunning:** logic for fetching text (backport [#43160](https://github.com/frappe/erpnext/issues/43160)) ([#43490](https://github.com/frappe/erpnext/issues/43490)) ([1b28a4e](1b28a4e928))
* Fix API endpoint for Frankfurter ([d96cee8](d96cee8779))
* Ignore transaction deletion check on ledger entry insertion ([1d6f97a](1d6f97ad94))
* **Item:** error message on tax rate (backport [#42955](https://github.com/frappe/erpnext/issues/42955)) ([#42956](https://github.com/frappe/erpnext/issues/42956)) ([5fc5934](5fc5934942))
* last purchase rate for purchase invoice (backport [#43448](https://github.com/frappe/erpnext/issues/43448)) ([#43452](https://github.com/frappe/erpnext/issues/43452)) ([ee2c8c8](ee2c8c869a))
* negative stock error for batch (backport [#43450](https://github.com/frappe/erpnext/issues/43450)) ([#43454](https://github.com/frappe/erpnext/issues/43454)) ([7bf6251](7bf6251c21))
* patch to update Currency Exchange Settings for `frankfurter.app` (backport [#43481](https://github.com/frappe/erpnext/issues/43481)) ([#43483](https://github.com/frappe/erpnext/issues/43483)) ([35a08f8](35a08f8830))
* quality inspection creation (backport [#43416](https://github.com/frappe/erpnext/issues/43416)) ([#43417](https://github.com/frappe/erpnext/issues/43417)) ([a1b6628](a1b6628c41))
* **Quotation:** calculate row values for alternative items (backport [#43054](https://github.com/frappe/erpnext/issues/43054)) ([#43495](https://github.com/frappe/erpnext/issues/43495)) ([4fa5131](4fa5131590))
* removed validation for materials return (backport [#43461](https://github.com/frappe/erpnext/issues/43461)) ([#43463](https://github.com/frappe/erpnext/issues/43463)) ([9c0a17e](9c0a17e4d5))
* serial and batch no selector (backport [#43387](https://github.com/frappe/erpnext/issues/43387)) ([#43390](https://github.com/frappe/erpnext/issues/43390)) ([74c880c](74c880c232))
* set margin fields for purchase documents when updating items ([6516e68](6516e68fa0))
* Stock Ledger Invariant Check report ([2984bad](2984bad2c0))
* Stock UOM not fetched when Stock Entry create from Item Dashboard (backport [#43457](https://github.com/frappe/erpnext/issues/43457)) ([#43465](https://github.com/frappe/erpnext/issues/43465)) ([f2a72e5](f2a72e5f82))
* tests for work order consumption (backport [#41814](https://github.com/frappe/erpnext/issues/41814)) ([#43430](https://github.com/frappe/erpnext/issues/43430)) ([86b10ce](86b10ce9bb))
* use serial and batch fields (backport [#43421](https://github.com/frappe/erpnext/issues/43421)) ([#43423](https://github.com/frappe/erpnext/issues/43423)) ([d495d93](d495d93840))

### Features

* added 'cost of new capitalized asset' column ([27cd51e](27cd51e267))
* provide hook point for bulk transaction tasks ([50e47e7](50e47e796d))
2024-10-04 03:07:05 +00:00
ruthra kumar
5a9522e70f Merge pull request #43467 from frappe/version-15-hotfix
chore: release v15
2024-10-04 08:35:53 +05:30
Frappe PR Bot
01f9139ebd chore(release): Bumped to Version 15.37.0
# [15.37.0](https://github.com/frappe/erpnext/compare/v15.36.4...v15.37.0) (2024-09-30)

### Features

* added 'cost of new capitalized asset' column ([96d8b52](96d8b5242d))
2024-09-30 17:21:09 +00:00
rohitwaghchaure
4be557bdce Merge pull request #43453 from frappe/mergify/bp/version-15/pr-43412
feat: added 'cost of new capitalized asset' column (backport #43399) (backport #43412)
2024-09-30 22:49:53 +05:30
Khushi Rawat
96d8b5242d feat: added 'cost of new capitalized asset' column
(cherry picked from commit 1eb9cc33fc)
(cherry picked from commit 27cd51e267)
2024-09-30 15:45:59 +00:00
David
e730b8c6e4 fix(return): set default return warehouse
This captures the case of manual modifications to the return and ensures
that by default, the correct return warehouse will be set

(cherry picked from commit fa65291e98)
2024-09-30 12:28:14 +00:00
Frappe PR Bot
2d09ef2509 chore(release): Bumped to Version 15.36.4
## [15.36.4](https://github.com/frappe/erpnext/compare/v15.36.3...v15.36.4) (2024-09-29)

### Bug Fixes

* Data missing in table: None, MandatoryError (backport [#43422](https://github.com/frappe/erpnext/issues/43422)) ([#43429](https://github.com/frappe/erpnext/issues/43429)) ([2c4610c](2c4610c021))
2024-09-29 16:38:13 +00:00
rohitwaghchaure
8b5997e38f Merge pull request #43431 from frappe/mergify/bp/version-15/pr-43429
fix: Data missing in table: None, MandatoryError (backport #43422) (backport #43429)
2024-09-29 22:07:02 +05:30
mergify[bot]
2c4610c021 fix: Data missing in table: None, MandatoryError (backport #43422) (#43429)
fix: Data missing in table: None, MandatoryError (#43422)

(cherry picked from commit 8e33e0e1d2)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 4b3f143f83)
2024-09-29 15:57:24 +00:00
Frappe PR Bot
e706aa692a chore(release): Bumped to Version 15.36.3
## [15.36.3](https://github.com/frappe/erpnext/compare/v15.36.2...v15.36.3) (2024-09-27)

### Bug Fixes

* Ignore transaction deletion check on ledger entry insertion ([c1f14f2](c1f14f2991))
2024-09-27 18:30:37 +00:00
Deepesh Garg
a5fa287dad Merge pull request #43413 from frappe/mergify/bp/version-15/pr-43411
fix: Ignore transaction deletion check on ledger entry insertion (#43410)
2024-09-27 23:58:16 +05:30
Deepesh Garg
c1f14f2991 fix: Ignore transaction deletion check on ledger entry insertion
(cherry picked from commit 998f6a92a4)
(cherry picked from commit 1d6f97ad94)
2024-09-27 18:25:49 +00:00
Frappe PR Bot
8d188dccd7 chore(release): Bumped to Version 15.36.2
## [15.36.2](https://github.com/frappe/erpnext/compare/v15.36.1...v15.36.2) (2024-09-25)

### Bug Fixes

* add currency in financial statement ([927f800](927f80035d))
* added date condition ([0e18845](0e1884539e))
* AR / AP report to ignore 0.0 outstanding ([979d801](979d801de5))
* **Bank Account:** dashboard connections (backport [#43365](https://github.com/frappe/erpnext/issues/43365)) ([#43367](https://github.com/frappe/erpnext/issues/43367)) ([cfea2de](cfea2de131))
* change dynamic link doctype fieldtype to data ([05c92cc](05c92cce71))
* closing amount reset to expected amount on save (backport [#43358](https://github.com/frappe/erpnext/issues/43358)) ([#43368](https://github.com/frappe/erpnext/issues/43368)) ([0722aa5](0722aa5a3f))
* create_address is failing ([557ef5d](557ef5d214))
* handle missing liability account scenario in `set_liability_account` ([4045928](40459288f6))
* incorrect outstanding on non-pos invoice with write_off_account ([f89a3db](f89a3dbb65))
* incorrect stock balance for inventory dimension (backport [#43284](https://github.com/frappe/erpnext/issues/43284)) ([#43290](https://github.com/frappe/erpnext/issues/43290)) ([f6725e2](f6725e2eed))
* item_query in pos_invoice ([99e004b](99e004b619))
* make to tax category on tax rule to filter with percent ([63d4fdd](63d4fddb49))
* **minor:** include condition to check docstatus ([1f42302](1f42302997))
* not able to cancel Quality Inspection (backport [#43374](https://github.com/frappe/erpnext/issues/43374)) ([#43375](https://github.com/frappe/erpnext/issues/43375)) ([40fbb1d](40fbb1d6ff))
* partial return on POS invoice ([998fef7](998fef779b))
* partial return on POS invoice ([b99ca7d](b99ca7d9e9))
* Payment Ledger Report currency fieldtype fix ([ad2d6a1](ad2d6a1625))
* **Payment Reconciliation:** German translations ([e06a01f](e06a01fae5))
* set group_by condition if empty and voucher_no is set ([ec27077](ec27077d9c))
* shipping rule must match the company ([085a4c6](085a4c61ac))
* show chart tool tip in report currency ([e5ae828](e5ae828580))
* stock dashboard (backport [#43347](https://github.com/frappe/erpnext/issues/43347)) ([#43349](https://github.com/frappe/erpnext/issues/43349)) ([176feb2](176feb20ad))
* transaction exchange rate on GL's for Multi currency Journals ([a7ccc94](a7ccc9420b))
* translate in js ([84e26e2](84e26e21ab))
* Translation for button SO to PO ([73d98ad](73d98addbc))
* ui clean-up (backport [#43305](https://github.com/frappe/erpnext/issues/43305)) ([#43312](https://github.com/frappe/erpnext/issues/43312)) ([7e6d6f0](7e6d6f08a2))
* update clearance date in invoice payment table ([10ecdb9](10ecdb99fe))
2024-09-25 04:40:17 +00:00
ruthra kumar
9de0d4329c Merge pull request #43361 from frappe/version-15-hotfix
chore: release v15
2024-09-25 10:09:04 +05:30
Frappe PR Bot
34ca0c3bb6 chore(release): Bumped to Version 15.36.1
## [15.36.1](https://github.com/frappe/erpnext/compare/v15.36.0...v15.36.1) (2024-09-19)

### Bug Fixes

* create_address is failing ([17ad402](17ad402695))
2024-09-19 01:43:11 +00:00
ruthra kumar
42e4b8a68c Merge pull request #43287 from frappe/mergify/bp/version-15/pr-43279
fix: create_address is failing while creating customer (backport #43279)
2024-09-19 07:11:56 +05:30
Shariq Ansari
17ad402695 fix: create_address is failing
(cherry picked from commit acc1d52ac8)
2024-09-19 01:21:13 +00:00
Frappe PR Bot
479e8573c2 chore(release): Bumped to Version 15.36.0
# [15.36.0](https://github.com/frappe/erpnext/compare/v15.35.2...v15.36.0) (2024-09-18)

### Bug Fixes

* A project without tasks should be able to complete ([dea735d](dea735de4d))
* add currency in options for rate field in pricing rule ([782c9dd](782c9dda1a))
* batch based item price not working (backport [#43172](https://github.com/frappe/erpnext/issues/43172)) ([#43206](https://github.com/frappe/erpnext/issues/43206)) ([61a42ea](61a42ea5d7))
* cancel cost center allocation and journal entry after test ([3d29007](3d29007aeb))
* consistent behaviour on refresh ([01f3068](01f30682ee))
* create and link address while creating prospect & customer ([d6a3d0d](d6a3d0d468))
* create fiscal year without overlapping existing Fiscal Years ([78768f8](78768f883c))
* currency changing while making PO from Supplier Quotation (backport [#43187](https://github.com/frappe/erpnext/issues/43187)) ([#43205](https://github.com/frappe/erpnext/issues/43205)) ([ef6b172](ef6b172616))
* delete exchange gain loss journal entry while deleting payment entry ([5789de2](5789de25b9))
* do not auto apply tds in purchase order ([741c18b](741c18b144))
* do not check appy_tds in Purchase Order Automatically ([5edebb2](5edebb28a5))
* do not validate purchase document for composite asset ([c505156](c5051561e4))
* fetch cost center allocation percentage only from the applicable allocation ([0fe901a](0fe901a137))
* hide and reset discount control on new POS order ([42494db](42494db3c7))
* **holiday-list:** use same date format for same holiday error message (backport [#42606](https://github.com/frappe/erpnext/issues/42606)) ([#43222](https://github.com/frappe/erpnext/issues/43222)) ([f101a1c](f101a1ce3b))
* ignore repost logic on Payment Reconciliation ([d91013a](d91013a467))
* invalid gp calculation ([291f0a5](291f0a580b))
* item list view in website (backport [#43165](https://github.com/frappe/erpnext/issues/43165)) ([#43207](https://github.com/frappe/erpnext/issues/43207)) ([c1a6c56](c1a6c56217))
* map rows on journal entry by validating account, party, debit and credit value ([86e1818](86e1818420))
* prevent KeyError by checking `report_filter` existence ([984acb6](984acb661d))
* revert 091c5496b2 ([2ad6d63](2ad6d637ee))
* set party_type null when payment_type is changed to Internal Transfer ([45ff8fa](45ff8fa296))
* set tax_withholding_category from Purchase Order while creating pi form po ([7027be8](7027be8fbc))
* tds workflow in purchase order ([11359bd](11359bd235))
* typo with po_date when creating remarks ([1657a83](1657a83151))
* updated filtering in depreciation and balances report ([78c6839](78c68397d9))
* **ux:** set amount based on account currency while adding new row ([f7cedac](f7cedac526))
* **ux:** set amount on foreign currency when foreign currency account is selected on last row of journal ([d8d4cd2](d8d4cd23a5))

### Features

* API for crm integration ([f060534](f060534625))
2024-09-18 07:32:30 +00:00
ruthra kumar
6a0b15211a Merge pull request #43254 from frappe/version-15-hotfix
chore: release v15
2024-09-18 13:01:08 +05:30
Frappe PR Bot
28f1f9355d chore(release): Bumped to Version 15.35.2
## [15.35.2](https://github.com/frappe/erpnext/compare/v15.35.1...v15.35.2) (2024-09-17)

### Bug Fixes

* currency changing while making PO from Supplier Quotation (backport [#43187](https://github.com/frappe/erpnext/issues/43187)) ([#43205](https://github.com/frappe/erpnext/issues/43205)) ([2f56ba7](2f56ba7f42))
2024-09-17 05:00:07 +00:00
ruthra kumar
41db9d3886 Merge pull request #43209 from frappe/mergify/bp/version-15/pr-43205
fix: currency changing while making PO from Supplier Quotation (backport #43187) (backport #43205)
2024-09-17 10:28:43 +05:30
mergify[bot]
2f56ba7f42 fix: currency changing while making PO from Supplier Quotation (backport #43187) (#43205)
fix: currency changing while making PO from Supplier Quotation (#43187)

(cherry picked from commit 2b96e37c34)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit ef6b172616)
2024-09-13 08:01:44 +00:00
Frappe PR Bot
7f95e42bec chore(release): Bumped to Version 15.35.1
## [15.35.1](https://github.com/frappe/erpnext/compare/v15.35.0...v15.35.1) (2024-09-12)

### Bug Fixes

* typo with po_date when creating remarks ([31e0bb4](31e0bb477e))
2024-09-12 06:11:04 +00:00
ruthra kumar
578ddb9be4 Merge pull request #43184 from frappe/mergify/bp/version-15/pr-43182
fix: typo with po_date when creating remarks (backport #43182)
2024-09-12 11:39:39 +05:30
Smit Vora
31e0bb477e fix: typo with po_date when creating remarks
(cherry picked from commit a55502e0f1)
2024-09-12 05:47:40 +00:00
Frappe PR Bot
d9d86dae35 chore(release): Bumped to Version 15.35.0
# [15.35.0](https://github.com/frappe/erpnext/compare/v15.34.2...v15.35.0) (2024-09-11)

### Bug Fixes

* `default_advance_account` field in Process Payment Reconciliation ([75cb298](75cb29890d))
* bom cost update is not working (backport [#43155](https://github.com/frappe/erpnext/issues/43155)) ([#43157](https://github.com/frappe/erpnext/issues/43157)) ([8c8dc24](8c8dc241e5))
* cancel common party advance jv while canceling the invoice ([9bd3d7a](9bd3d7a020))
* Cannot read properties of null (reading 'doc') (backport [#43071](https://github.com/frappe/erpnext/issues/43071)) ([#43118](https://github.com/frappe/erpnext/issues/43118)) ([80b5c16](80b5c16a2e))
* check multi-currency on jv for common party accounting with foreign currency ([d17badd](d17baddb0d))
* concurrency issue while picking materials (backport [#43087](https://github.com/frappe/erpnext/issues/43087)) ([#43152](https://github.com/frappe/erpnext/issues/43152)) ([cd57e00](cd57e009dd))
* **Delivery Note:** translatability of validation errors ([ea4f736](ea4f7365ea))
* ensure `SellingController.onload` gets called for SO & DN ([2c1f72e](2c1f72e44c))
* incorrect actual cost in Procurement Tracker report (backport [#43109](https://github.com/frappe/erpnext/issues/43109)) ([#43138](https://github.com/frappe/erpnext/issues/43138)) ([5110975](5110975c6d))
* incorrect qty after transaction in SLE (backport [#43103](https://github.com/frappe/erpnext/issues/43103)) ([#43105](https://github.com/frappe/erpnext/issues/43105)) ([8447bf3](8447bf34f0))
* **minor:** reorder expected value validation ([6fde07d](6fde07da0e))
* multiple fixes related to remarks for GL Report ([#42753](https://github.com/frappe/erpnext/issues/42753)) ([f45b1db](f45b1db1a4))
* **Opening Invoice Creation Tool:** translatability of messages ([3fd9df0](3fd9df0d2e))
* pass company from asset to asset capitalization ([9e72a84](9e72a844f7))
* permission on guest PR creation ([a23e8b1](a23e8b13be))
* return type of `get_party_details` (backport [#43131](https://github.com/frappe/erpnext/issues/43131)) ([#43134](https://github.com/frappe/erpnext/issues/43134)) ([d2923ba](d2923bae85))
* set today in 'On This Date' in Available Batch Report ([03e3374](03e3374a8b))
* uncomment internal parties ([33174b1](33174b1ba2))
* unhide action button after form redirect ([208bd2b](208bd2b8ff))
* unreconcile allocation child table redirect url voucher no issue ([2dddd79](2dddd7906b))
* validate the item code when updating the other item's price rule ([8f4dc80](8f4dc8048d))

### Features

* added revaluation surplus and impairment acc in standard charts… ([#43022](https://github.com/frappe/erpnext/issues/43022)) ([ea86bc2](ea86bc2235))
* utility report to identify invalid ledger entries ([5929d50](5929d50c72))

### Performance Improvements

* timeout error (backport [#43154](https://github.com/frappe/erpnext/issues/43154)) ([#43158](https://github.com/frappe/erpnext/issues/43158)) ([c9f49ca](c9f49caecc))
2024-09-11 05:11:52 +00:00
ruthra kumar
d61f38b8ed Merge pull request #43151 from frappe/version-15-hotfix
chore: release v15
2024-09-11 10:40:35 +05:30
Frappe PR Bot
829660e7f3 chore(release): Bumped to Version 15.34.2
## [15.34.2](https://github.com/frappe/erpnext/compare/v15.34.1...v15.34.2) (2024-09-07)

### Bug Fixes

* incorrect qty after transaction in SLE (backport [#43103](https://github.com/frappe/erpnext/issues/43103)) ([#43105](https://github.com/frappe/erpnext/issues/43105)) ([0bc947f](0bc947f30d))
2024-09-07 12:40:39 +00:00
rohitwaghchaure
4649cf0a25 Merge pull request #43107 from frappe/mergify/bp/version-15/pr-43105
fix: incorrect qty after transaction in SLE (backport #43103) (backport #43105)
2024-09-07 18:09:17 +05:30
mergify[bot]
0bc947f30d fix: incorrect qty after transaction in SLE (backport #43103) (#43105)
fix: incorrect qty after transaction in SLE (#43103)

(cherry picked from commit 5ff87edc85)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 8447bf34f0)
2024-09-07 12:04:01 +00:00
Frappe PR Bot
7f261f3448 chore(release): Bumped to Version 15.34.1
## [15.34.1](https://github.com/frappe/erpnext/compare/v15.34.0...v15.34.1) (2024-09-05)

### Bug Fixes

* add the company in payment request bcz delete company transactions (backport [#42664](https://github.com/frappe/erpnext/issues/42664)) ([#42982](https://github.com/frappe/erpnext/issues/42982)) ([42e7725](42e7725442))
* added app permission check for apps page ([a35ce12](a35ce12d60))
* adjust price insertion logic for internal suppliers/customers ([#42988](https://github.com/frappe/erpnext/issues/42988)) ([daa75ee](daa75eea00))
* auto reorder material request mail issue (backport [#43066](https://github.com/frappe/erpnext/issues/43066)) ([#43068](https://github.com/frappe/erpnext/issues/43068)) ([d2b2002](d2b2002664))
* **capitalization:** debit cwip account instead of fixed asset account ([#42857](https://github.com/frappe/erpnext/issues/42857)) ([f3c60ea](f3c60ea0a7))
* company accounts setup_queries ([b99cdb5](b99cdb5be7))
* disabled batches showing in the list (backport [#43024](https://github.com/frappe/erpnext/issues/43024)) ([#43069](https://github.com/frappe/erpnext/issues/43069)) ([56dad7d](56dad7d365))
* don't allow capitalizing only service item for new composite asset ([a833010](a833010d2b))
* improve asset item matching logic ([3bb1867](3bb186736d))
* indentation ([4d7c0c0](4d7c0c004a))
* link Purchase Invoice and Receipt Items to Asset ([1121c66](1121c6663f))
* retain date filter when redirecting in Profit and Loss report ([f0e3fb4](f0e3fb466a))
* typeerror on Payment Entry ([6d51d14](6d51d14dfd))
* typerror on default_currency ([7d6984c](7d6984c873))
* update develop_version in hooks ([6c8e0fd](6c8e0fd1fb))
* validate component quantity according to BOM (backport [#43011](https://github.com/frappe/erpnext/issues/43011)) ([#43014](https://github.com/frappe/erpnext/issues/43014)) ([fee2255](fee2255661))
2024-09-05 11:44:28 +00:00
ruthra kumar
11a6ebaeef Merge pull request #43026 from frappe/version-15-hotfix
chore: release v15
2024-09-05 17:13:12 +05:30
Frappe PR Bot
cb2cb4447a chore(release): Bumped to Version 15.34.0
# [15.34.0](https://github.com/frappe/erpnext/compare/v15.33.5...v15.34.0) (2024-08-28)

### Bug Fixes

* calculation correction for annual depreciation ([fa85482](fa85482662))
* call 'process' directly instead of creating 'process_subscripti ([7582827](758282739e))
* Cannot read properties of null (reading 'doctype') (backport [#42941](https://github.com/frappe/erpnext/issues/42941)) ([#42943](https://github.com/frappe/erpnext/issues/42943)) ([2c99075](2c99075899))
* Column 'valuation_rate' cannot be null (backport [#42909](https://github.com/frappe/erpnext/issues/42909)) ([#42913](https://github.com/frappe/erpnext/issues/42913)) ([8c350d4](8c350d43b2))
* custom stock entry type issue (backport [#42835](https://github.com/frappe/erpnext/issues/42835)) ([#42846](https://github.com/frappe/erpnext/issues/42846)) ([831e2aa](831e2aaf18))
* do not copy date fields in opportunity doctype ([7401dc4](7401dc4015))
* get amount with taxes and charges from payment entry ([c54e97b](c54e97b89a))
* include erpnext in apps page ([7428df8](7428df8778))
* incorrect in and out qty in the Batch-Wise Balance History (backport [#42866](https://github.com/frappe/erpnext/issues/42866)) ([#42876](https://github.com/frappe/erpnext/issues/42876)) ([d9ca680](d9ca680a29))
* incorrect Received Qty Amount in Purchase Order Analysis (backport [#42852](https://github.com/frappe/erpnext/issues/42852)) ([#42854](https://github.com/frappe/erpnext/issues/42854)) ([72c1609](72c16097d6))
* last purchase rate not updated from purchase invoice (backport [#42847](https://github.com/frappe/erpnext/issues/42847)) ([#42853](https://github.com/frappe/erpnext/issues/42853)) ([2203ea9](2203ea9301))
* LCV based on purchase invoice amount with multi-currency (backport [#42890](https://github.com/frappe/erpnext/issues/42890)) ([#42894](https://github.com/frappe/erpnext/issues/42894)) ([ff868a9](ff868a9290))
* make party naming sequential when naming_by set as auto name ([0650c22](0650c22b53))
* not able to make stock entry against MR (backport [#42874](https://github.com/frappe/erpnext/issues/42874)) ([#42875](https://github.com/frappe/erpnext/issues/42875)) ([08bed61](08bed618f6))
* same posting date and time, creation causing incorrect balance qty (backport [#42904](https://github.com/frappe/erpnext/issues/42904)) ([#42920](https://github.com/frappe/erpnext/issues/42920)) ([2624892](26248924b6))
* spec mobile and email fields for notifications ([f56ee58](f56ee58e81))
* timeout while submitting stock entry (backport [#42929](https://github.com/frappe/erpnext/issues/42929)) ([#42931](https://github.com/frappe/erpnext/issues/42931)) ([ec26c92](ec26c92263))
* unsupported operand type(s) for *: 'float' and 'NoneType' (backport [#42916](https://github.com/frappe/erpnext/issues/42916)) ([#42918](https://github.com/frappe/erpnext/issues/42918)) ([8d29dc6](8d29dc6a81))
* update dimesions in exchange_gain_loss jv based on base document ([caa6ca1](caa6ca1d0b))
* Update get_amount to return currency precision grand total ([976abf7](976abf7b3c))
* use of incorrect attribute ([80244ba](80244bafa4))

### Features

* added finance book filter in depreciation and balances report ([5bdd298](5bdd2989c6))
* Disassembly Order (backport [#42655](https://github.com/frappe/erpnext/issues/42655)) ([#42957](https://github.com/frappe/erpnext/issues/42957)) ([8d8dd0c](8d8dd0cd2b))
* report to identify incorrectly cleared cheques ([25193c5](25193c5e92))
2024-08-28 05:04:27 +00:00
ruthra kumar
b3a8fe9391 Merge pull request #42937 from frappe/version-15-hotfix
chore: release v15
2024-08-28 10:33:09 +05:30
Frappe PR Bot
eb7e063d5c chore(release): Bumped to Version 15.33.5
## [15.33.5](https://github.com/frappe/erpnext/compare/v15.33.4...v15.33.5) (2024-08-23)

### Bug Fixes

* include erpnext in apps page ([be736cf](be736cf641))
2024-08-23 00:37:45 +00:00
ruthra kumar
0dbe79645c Merge pull request #42882 from frappe/mergify/bp/version-15/pr-42727
fix: include erpnext in apps page (backport #42727)
2024-08-23 06:05:20 +05:30
Shariq Ansari
995773088a chore: renamed include_as_app to include_in_apps_screen
(cherry picked from commit 5280132423)
2024-08-23 00:19:55 +00:00
Shariq Ansari
be736cf641 fix: include erpnext in apps page
(cherry picked from commit 1d52ef7afe)
2024-08-23 00:19:54 +00:00
Frappe PR Bot
9ac665b4bd chore(release): Bumped to Version 15.33.4
## [15.33.4](https://github.com/frappe/erpnext/compare/v15.33.3...v15.33.4) (2024-08-21)

### Bug Fixes

* incorrect Received Qty Amount in Purchase Order Analysis (backport [#42852](https://github.com/frappe/erpnext/issues/42852)) (backport [#42854](https://github.com/frappe/erpnext/issues/42854)) ([#42856](https://github.com/frappe/erpnext/issues/42856)) ([8d8d84b](8d8d84bae4))
* last purchase rate not updated from purchase invoice (backport [#42847](https://github.com/frappe/erpnext/issues/42847)) (backport [#42853](https://github.com/frappe/erpnext/issues/42853)) ([#42855](https://github.com/frappe/erpnext/issues/42855)) ([9f4cb98](9f4cb98de6))
2024-08-21 11:08:23 +00:00
mergify[bot]
8d8d84bae4 fix: incorrect Received Qty Amount in Purchase Order Analysis (backport #42852) (backport #42854) (#42856)
fix: incorrect Received Qty Amount in Purchase Order Analysis (backport #42852) (#42854)

fix: incorrect Received Qty Amount in Purchase Order Analysis (#42852)

(cherry picked from commit fb846ffa12)

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

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-08-21 16:37:08 +05:30
mergify[bot]
9f4cb98de6 fix: last purchase rate not updated from purchase invoice (backport #42847) (backport #42853) (#42855)
fix: last purchase rate not updated from purchase invoice (backport #42847) (#42853)

fix: last purchase rate not updated from purchase invoice (#42847)

(cherry picked from commit 5b9309cf34)

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

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-08-21 16:37:00 +05:30
Frappe PR Bot
28c9f2adab chore(release): Bumped to Version 15.33.3
## [15.33.3](https://github.com/frappe/erpnext/compare/v15.33.2...v15.33.3) (2024-08-21)

### Bug Fixes

* Auto Create Serial and Batch Bundle For Outward (backport [#42778](https://github.com/frappe/erpnext/issues/42778)) ([#42792](https://github.com/frappe/erpnext/issues/42792)) ([7cc7179](7cc7179b05))
* backport german translations from develop ([9e9de4c](9e9de4c99e))
* bank reconcilation tool cost center company filter adding ([cd59940](cd5994017c))
* Create Sales Order from Quotation for Prospect ([f547bef](f547befeb9))
* create SO from Quot for Prospect --conflicts ([ec0201c](ec0201cb85))
* create SO from Quot for Prospect --conflicts ([5d7fb1d](5d7fb1d945))
* disable rename from warehouse ([3a1ad6e](3a1ad6e844))
* disable rename from warehouse ([40abd82](40abd82e2d))
* dropping index to improve performance (backport [#42820](https://github.com/frappe/erpnext/issues/42820)) ([#42821](https://github.com/frappe/erpnext/issues/42821)) ([b24de3e](b24de3e35b))
* german translations ([751c209](751c20984f))
* german translations of "HR" ([6f7fdbe](6f7fdbefac))
* ignore pricing rule while making DN from Pick List (backport [#42763](https://github.com/frappe/erpnext/issues/42763)) ([#42768](https://github.com/frappe/erpnext/issues/42768)) ([aba54ba](aba54ba18f))
* not able to create the batch (backport [#42784](https://github.com/frappe/erpnext/issues/42784)) ([#42785](https://github.com/frappe/erpnext/issues/42785)) ([0f9849e](0f9849e672))
* **patch:** replace repost with direct sql to update 'against_voucher ([e420fa9](e420fa9779))
* removed extra filter condition ([b84ca04](b84ca04975))
* set up filters for dimensions ([abb8866](abb88662c1))
* translatability of boldened text ([4914481](4914481105))
* update the testcase format ([33542cb](33542cb909))
* update the testcase format ([549dc28](549dc286d0))

### Performance Improvements

* asset creation from purchase receipt ([1040198](1040198ce1))
* data import for stock entries (backport [#42711](https://github.com/frappe/erpnext/issues/42711)) ([#42819](https://github.com/frappe/erpnext/issues/42819)) ([0344442](0344442d42))
2024-08-21 05:22:44 +00:00
ruthra kumar
d04f7ffe87 Merge pull request #42832 from frappe/version-15-hotfix
chore: release v15
2024-08-21 10:51:29 +05:30
Frappe PR Bot
81b1cbd367 chore(release): Bumped to Version 15.33.2
## [15.33.2](https://github.com/frappe/erpnext/compare/v15.33.1...v15.33.2) (2024-08-16)

### Bug Fixes

* **patch:** replace repost with direct sql to update 'against_voucher ([4d9f522](4d9f522f22))
2024-08-16 11:09:43 +00:00
ruthra kumar
a72383da0e Merge pull request #42796 from frappe/mergify/bp/version-15/pr-42791
fix(patch): Use sql to update 'against_voucher' rather than reposting (backport #42791)
2024-08-16 16:38:27 +05:30
ruthra kumar
eb8213c4e7 chore: update patches.txt
(cherry picked from commit 1721175a20)
2024-08-16 10:26:26 +00:00
ruthra kumar
4d9f522f22 fix(patch): replace repost with direct sql to update 'against_voucher
(cherry picked from commit 13bb48434f)
2024-08-16 10:26:26 +00:00
Frappe PR Bot
fbf1160357 chore(release): Bumped to Version 15.33.1
## [15.33.1](https://github.com/frappe/erpnext/compare/v15.33.0...v15.33.1) (2024-08-16)

### Bug Fixes

* not able to create the batch (backport [#42784](https://github.com/frappe/erpnext/issues/42784)) (backport [#42785](https://github.com/frappe/erpnext/issues/42785)) ([#42786](https://github.com/frappe/erpnext/issues/42786)) ([a3e3585](a3e3585e50))
2024-08-16 06:19:07 +00:00
mergify[bot]
a3e3585e50 fix: not able to create the batch (backport #42784) (backport #42785) (#42786)
fix: not able to create the batch (backport #42784) (#42785)

fix: not able to create the batch (#42784)

(cherry picked from commit 32c4fab14f)

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

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-08-16 11:47:53 +05:30
Sanket322
9f970189fe fix: set proper currency format
(cherry picked from commit 2533808f1e)
2024-08-14 08:10:05 +00:00
Frappe PR Bot
73af5be1c3 chore(release): Bumped to Version 15.33.0
# [15.33.0](https://github.com/frappe/erpnext/compare/v15.32.1...v15.33.0) (2024-08-14)

### Bug Fixes

* allow sale of asset for internal transfer ([97cadfe](97cadfe5d3))
* cancel Journal Entry on cancellation of asset value adjustment ([a429f2f](a429f2f626))
* currency changing while making PR from the PO (backport [#42718](https://github.com/frappe/erpnext/issues/42718)) ([#42721](https://github.com/frappe/erpnext/issues/42721)) ([50b1fa5](50b1fa5deb))
* delivery note creation issue (backport [#42696](https://github.com/frappe/erpnext/issues/42696)) ([#42697](https://github.com/frappe/erpnext/issues/42697)) ([6f16ae3](6f16ae3e00))
* dimensions in common party journal entry ([fd4143e](fd4143e686))
* duplicate labels in stock entry (backport [#42756](https://github.com/frappe/erpnext/issues/42756)) ([#42758](https://github.com/frappe/erpnext/issues/42758)) ([8624a0a](8624a0abce))
* error message in coa importer ([20c1bcd](20c1bcd654))
* **Exchange Rate Revaluation:** translatable strings ([da6eea7](da6eea7743))
* fetch months last date to avoid miscalculation ([765c110](765c1104c4))
* force fetch updates for subcription ([582fffc](582fffca93))
* german translation of exit ([a2df276](a2df276880))
* german translations for incoterms ([9789648](9789648175))
* ledger entries for pos return with update outstanding for self ([8cd1952](8cd1952da3))
* Maintain same rate on qty change on Quotation to Sales Order ([7ed7c22](7ed7c22469))
* patch to fix incorrect against_voucher references in ledger ([389227b](389227bce8))
* pre-commit for better code formatting ([94f4c92](94f4c92a03))
* price list when invoice created from timesheet ([2926915](2926915a06))
* price list when invoice created from timesheet ([536dc47](536dc47eb0))
* promotional scheme doctype fields in consitency with pricing rule ([#42432](https://github.com/frappe/erpnext/issues/42432)) ([87d8603](87d8603d1d))
* resolved conflict ([defd554](defd5541b0))
* Sort lists before calling itertools.groupby ([d8939e0](d8939e0bb0))
* text color in sales funnel report based on theme ([a8de8ae](a8de8aecf5))
* typeerror on payment entry ([64e75a8](64e75a8e08))
* update 'Paid Amount' on forex payment request ([c71f06b](c71f06be9e))
* Update Rate as per Valuation Rate for Internal Transfers only if Setting is Enabled ([#42050](https://github.com/frappe/erpnext/issues/42050)) ([6e833cc](6e833cce6a))
* warning message for negative stock (backport [#42683](https://github.com/frappe/erpnext/issues/42683)) ([#42710](https://github.com/frappe/erpnext/issues/42710)) ([a990577](a99057754d))

### Features

* changes in opportunity.py to show contacts and addresses from referenced and opportunities ([3cac4a5](3cac4a598f))
2024-08-14 08:02:34 +00:00
ruthra kumar
81e3d269dc Merge pull request #42745 from frappe/version-15-hotfix
chore: release v15
2024-08-14 13:31:20 +05:30
Frappe PR Bot
6a4f06cf4a chore(release): Bumped to Version 15.32.1
## [15.32.1](https://github.com/frappe/erpnext/compare/v15.32.0...v15.32.1) (2024-08-08)

### Bug Fixes

* promotional scheme doctype fields in consitency with pricing rule ([#42432](https://github.com/frappe/erpnext/issues/42432)) ([2aa90fd](2aa90fdc14))
2024-08-08 07:06:38 +00:00
ruthra kumar
dfe0079573 Merge pull request #42674 from frappe/mergify/bp/version-15/pr-42550
fix: promotional scheme doctype fields in consitency with pricing rule (backport #42432) (backport #42550)
2024-08-08 12:35:25 +05:30
Lakshit Jain
a983d65404 chore: resolve conflicts (#42553)
(cherry picked from commit 78eb443614)
2024-08-08 06:43:38 +00:00
Lakshit Jain
2aa90fdc14 fix: promotional scheme doctype fields in consitency with pricing rule (#42432)
* fix: add "round_free_qty" check box in promotional scheme

* fix: add `add_for_price_list` field

* fix: set_query in setup for promotional scheme

---------

(cherry picked from commit 8624aeca54)

# Conflicts:
#	erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.json
#	erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.json
(cherry picked from commit 87d8603d1d)
2024-08-08 06:43:38 +00:00
Frappe PR Bot
2e3b2db03b chore(release): Bumped to Version 15.32.0
# [15.32.0](https://github.com/frappe/erpnext/compare/v15.31.5...v15.32.0) (2024-08-07)

### Bug Fixes

* 'undefined' in PL and BS report summary on Consolidated report ([3da7071](3da7071327))
* all warehouse filter for the stock report (backport [#42584](https://github.com/frappe/erpnext/issues/42584)) ([#42604](https://github.com/frappe/erpnext/issues/42604)) ([830b95b](830b95bdcb))
* company filter for filtring tax withheld vouchers ([3ad1f2d](3ad1f2d0d0))
* disable primary action button only when there are no active capitalization ([2d644ac](2d644ac066))
* Discount and taxes in return document should follow the reference document (backport [#41911](https://github.com/frappe/erpnext/issues/41911)) ([#42574](https://github.com/frappe/erpnext/issues/42574)) ([9321408](9321408154))
* do not update item price and last purchase rate for inter transf… (backport [#42616](https://github.com/frappe/erpnext/issues/42616)) ([#42633](https://github.com/frappe/erpnext/issues/42633)) ([59b9b7d](59b9b7dc91))
* german translations ([f27e9f3](f27e9f3089))
* inter transfer delivery note issue with batch (backport [#42552](https://github.com/frappe/erpnext/issues/42552)) ([#42556](https://github.com/frappe/erpnext/issues/42556)) ([97cc308](97cc3082e1))
* min height for rows in sales funnel ([2f81c99](2f81c99143))
* resolved conflict ([#42557](https://github.com/frappe/erpnext/issues/42557)) ([c3293d1](c3293d110c))
* reverse debit credit for party gl entry in payment entry based on negative amount ([#42367](https://github.com/frappe/erpnext/issues/42367)) ([14f9aef](14f9aef55c))
* set currency on change of company considering customer default currency (backport [#42405](https://github.com/frappe/erpnext/issues/42405)) ([#42547](https://github.com/frappe/erpnext/issues/42547)) ([7c8d13c](7c8d13c51a))
* set query filters for sales / purchase tax template on PE ([dc9cf74](dc9cf74be8))
* use get_last_day to get the correct date (backport [#42564](https://github.com/frappe/erpnext/issues/42564)) ([#42598](https://github.com/frappe/erpnext/issues/42598)) ([2de86eb](2de86eb0f4))

### Features

* expiry date column in Available Batch Report (backport [#42628](https://github.com/frappe/erpnext/issues/42628)) ([#42642](https://github.com/frappe/erpnext/issues/42642)) ([d8768c5](d8768c5377))
2024-08-07 09:30:48 +00:00
ruthra kumar
51fa336350 Merge pull request #42649 from frappe/version-15-hotfix
chore: release v15
2024-08-07 14:59:36 +05:30
Abhishek Chougule
8db11d03ed Merge branch 'frappe:version-15-hotfix' into version-15-hotfix 2024-08-05 17:37:11 +05:30
Abhishek Chougule
2c21df2ad9 fix: correct garbage value on Razorpay Payments Page 2024-08-03 10:54:51 +05:30
Frappe PR Bot
d8080910c6 chore(release): Bumped to Version 15.31.5
## [15.31.5](https://github.com/frappe/erpnext/compare/v15.31.4...v15.31.5) (2024-08-03)

### Bug Fixes

* use get_last_day to get the correct date (backport [#42564](https://github.com/frappe/erpnext/issues/42564)) ([#42602](https://github.com/frappe/erpnext/issues/42602)) ([02a31ca](02a31caa05))
2024-08-03 03:58:31 +00:00
mergify[bot]
02a31caa05 fix: use get_last_day to get the correct date (backport #42564) (#42602)
fix: use get_last_day to get the correct date (#42564)

(cherry picked from commit 5d58eb67a6)

Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>
2024-08-03 09:27:16 +05:30
Frappe PR Bot
703b9accb8 chore(release): Bumped to Version 15.31.4
## [15.31.4](https://github.com/frappe/erpnext/compare/v15.31.3...v15.31.4) (2024-08-01)

### Bug Fixes

* inter transfer delivery note issue with batch (backport [#42552](https://github.com/frappe/erpnext/issues/42552)) ([#42556](https://github.com/frappe/erpnext/issues/42556)) ([bf0e2b3](bf0e2b3b52))
2024-08-01 09:12:25 +00:00
rohitwaghchaure
aca0662a64 Merge pull request #42571 from frappe/mergify/bp/version-15/pr-42556
fix: inter transfer delivery note issue with batch (backport #42552) (backport #42556)
2024-08-01 14:41:10 +05:30
mergify[bot]
bf0e2b3b52 fix: inter transfer delivery note issue with batch (backport #42552) (#42556)
fix: inter transfer delivery note issue with batch (#42552)

(cherry picked from commit f620ef20ae)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 97cc3082e1)
2024-08-01 07:53:46 +00:00
Frappe PR Bot
da3eddeb26 chore(release): Bumped to Version 15.31.3
## [15.31.3](https://github.com/frappe/erpnext/compare/v15.31.2...v15.31.3) (2024-07-31)

### Bug Fixes

* Adjust initial month's depreciation to end of depreciation period ([9d2ef4d](9d2ef4d3e8))
* builtins.KeyError: ('ABC', 'Store - CP') (backport [#42505](https://github.com/frappe/erpnext/issues/42505)) ([#42509](https://github.com/frappe/erpnext/issues/42509)) ([f25b38c](f25b38caf5))
* consider payment entries for checking if tds is deducted ([183ac41](183ac41550))
* dynamic condition in the pricing rule not working (backport [#42467](https://github.com/frappe/erpnext/issues/42467)) ([#42495](https://github.com/frappe/erpnext/issues/42495)) ([ac2ef21](ac2ef21896))
* field_type is small text for v15 ([9e99eda](9e99eda3c3))
* fields alteration related to subcontracting ([80d4dc2](80d4dc2016))
* Fields Modification for Subcontracting DocTypes ([#42383](https://github.com/frappe/erpnext/issues/42383)) ([422824b](422824b9e7))
* ignore duplicates while creating default templates ([aea8271](aea8271f7e))
* incorrect cost_center on AR/AP report ([0c2e948](0c2e9480cb))
* incorrect current qty for the batch in stock reco (backport [#42434](https://github.com/frappe/erpnext/issues/42434)) ([#42459](https://github.com/frappe/erpnext/issues/42459)) ([298a569](298a5699f1))
* keyerror posting_time (backport [#42452](https://github.com/frappe/erpnext/issues/42452)) ([#42460](https://github.com/frappe/erpnext/issues/42460)) ([2d2140a](2d2140aad0))
* not able to save BOM Creator ([#42540](https://github.com/frappe/erpnext/issues/42540)) ([61280e6](61280e6072))
* parenttype in item wise purchase and sales register ([322fbe9](322fbe92ee))
* performance issue for the report Purchase Order Analysis report (backport [#42503](https://github.com/frappe/erpnext/issues/42503)) ([#42507](https://github.com/frappe/erpnext/issues/42507)) ([edf1fcb](edf1fcb742))
* price_list_currency not found error (backport [#42534](https://github.com/frappe/erpnext/issues/42534)) ([#42539](https://github.com/frappe/erpnext/issues/42539)) ([5fa185d](5fa185d480))
* purchase return from rejected warehouse (backport [#42531](https://github.com/frappe/erpnext/issues/42531)) ([#42535](https://github.com/frappe/erpnext/issues/42535)) ([b7d70ac](b7d70ac928))
* set pos data if not return doc ([25fe08e](25fe08eb74))
* **tests:** added tests for usecase ([1390c86](1390c86fc4))
* warehouse filter in Product Bundle Balance (backport [#42532](https://github.com/frappe/erpnext/issues/42532)) ([#42537](https://github.com/frappe/erpnext/issues/42537)) ([826577c](826577c88f))
* Warranty Expiry Date not set in the serial number (backport [#42513](https://github.com/frappe/erpnext/issues/42513)) ([#42515](https://github.com/frappe/erpnext/issues/42515)) ([fc0db19](fc0db1941a))

### Performance Improvements

* huge number of serial no creation (backport [#42522](https://github.com/frappe/erpnext/issues/42522)) ([#42544](https://github.com/frappe/erpnext/issues/42544)) ([6840f6c](6840f6cb26))
2024-07-31 06:03:49 +00:00
ruthra kumar
43dadc763c Merge pull request #42541 from frappe/version-15-hotfix
chore: release v15
2024-07-31 11:32:35 +05:30
Frappe PR Bot
4b66fcad64 chore(release): Bumped to Version 15.31.2
## [15.31.2](https://github.com/frappe/erpnext/compare/v15.31.1...v15.31.2) (2024-07-27)

### Bug Fixes

* dynamic condition in the pricing rule not working (backport [#42467](https://github.com/frappe/erpnext/issues/42467)) (backport [#42495](https://github.com/frappe/erpnext/issues/42495)) ([#42496](https://github.com/frappe/erpnext/issues/42496)) ([334c4d0](334c4d0676))
2024-07-27 05:38:30 +00:00
mergify[bot]
334c4d0676 fix: dynamic condition in the pricing rule not working (backport #42467) (backport #42495) (#42496)
fix: dynamic condition in the pricing rule not working (backport #42467) (#42495)

fix: dynamic condition in the pricing rule not working (#42467)

(cherry picked from commit 0e817f42ef)

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

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-07-27 11:07:20 +05:30
Frappe PR Bot
2de69e2b12 chore(release): Bumped to Version 15.31.1
## [15.31.1](https://github.com/frappe/erpnext/compare/v15.31.0...v15.31.1) (2024-07-24)

### Bug Fixes

* incorrect current qty for the batch in stock reco (backport [#42434](https://github.com/frappe/erpnext/issues/42434)) (backport [#42459](https://github.com/frappe/erpnext/issues/42459)) ([#42463](https://github.com/frappe/erpnext/issues/42463)) ([4bae419](4bae4194ab))
2024-07-24 14:00:57 +00:00
mergify[bot]
4bae4194ab fix: incorrect current qty for the batch in stock reco (backport #42434) (backport #42459) (#42463)
fix: incorrect current qty for the batch in stock reco (backport #42434) (#42459)

fix: incorrect current qty for the batch in stock reco (#42434)

(cherry picked from commit 9cd3374101)

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

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-07-24 19:29:40 +05:30
Frappe PR Bot
e28c1e9c4b chore(release): Bumped to Version 15.31.0
# [15.31.0](https://github.com/frappe/erpnext/compare/v15.30.0...v15.31.0) (2024-07-24)

### Bug Fixes

* Consider adding warranty period to serial nos (backport [#42051](https://github.com/frappe/erpnext/issues/42051)) ([#42182](https://github.com/frappe/erpnext/issues/42182)) ([8da28dc](8da28dcfb2))
* correct validation for depreciation posting date ([ffacf42](ffacf4222b))
* Don't allow negative amount on Payment Request [#41905](https://github.com/frappe/erpnext/issues/41905) ([aee2cc2](aee2cc2e03))
* missing cr/dr notes on payment reconciliation ([0a41ccd](0a41ccda99))
* not able to save QC (backport [#42371](https://github.com/frappe/erpnext/issues/42371)) ([#42373](https://github.com/frappe/erpnext/issues/42373)) ([18500b8](18500b8e3a))
* provide initial value for `.reduce()` call ([72bc539](72bc539ffd))
* Purchase Order Analysis Report Data (backport [#42387](https://github.com/frappe/erpnext/issues/42387)) ([#42394](https://github.com/frappe/erpnext/issues/42394)) ([709be13](709be13e82))
* qty in the 'Serial No Ledger' report (backport [#42429](https://github.com/frappe/erpnext/issues/42429)) ([#42433](https://github.com/frappe/erpnext/issues/42433)) ([926fd41](926fd41a2b))
* remove proprietorship and update it with individual ([527781a](527781a588))
* rounding issue causing incorrect quantity in SE (backport [#42380](https://github.com/frappe/erpnext/issues/42380)) ([#42395](https://github.com/frappe/erpnext/issues/42395)) ([54791e9](54791e938b))
* serial and batch bundle for POS Invoice (backport [#41491](https://github.com/frappe/erpnext/issues/41491)) ([#42396](https://github.com/frappe/erpnext/issues/42396)) ([555be2b](555be2be11))
* set filter to show only submitted asset ([29fc975](29fc975fb8))
* Show the rows in AR/AP report where outstanding equals to 0.01 ([886256c](886256c86b))

### Features

* add make_regional_gl_entries override for Sales Invoice ([#42399](https://github.com/frappe/erpnext/issues/42399)) ([22b17de](22b17de2b4))
2024-07-24 07:28:24 +00:00
ruthra kumar
1e16a987dd Merge pull request #42449 from frappe/version-15-hotfix
chore: release v15
2024-07-24 12:57:10 +05:30
Frappe PR Bot
4b8b3ee46a chore(release): Bumped to Version 15.30.0
# [15.30.0](https://github.com/frappe/erpnext/compare/v15.29.4...v15.30.0) (2024-07-17)

### Bug Fixes

* address and contact filters for SCO and SCR (backport [#42310](https://github.com/frappe/erpnext/issues/42310)) ([#42312](https://github.com/frappe/erpnext/issues/42312)) ([cb64c73](cb64c73c9e))
* bin deadlock issue (backport [#42342](https://github.com/frappe/erpnext/issues/42342)) ([#42357](https://github.com/frappe/erpnext/issues/42357)) ([29ee2d4](29ee2d46f0))
* cost center filter by company (backport [#42297](https://github.com/frappe/erpnext/issues/42297)) ([#42299](https://github.com/frappe/erpnext/issues/42299)) ([4c9ce1b](4c9ce1b188))
* extra qty pick in pick list (backport [#42345](https://github.com/frappe/erpnext/issues/42345)) ([#42349](https://github.com/frappe/erpnext/issues/42349)) ([1754adf](1754adfcd6))
* **gross profit:** incorrect valuation rate on different warehouses ([f161e59](f161e59cd7))
* incoming rate zero for supplied items in returned SCR (backport [#42314](https://github.com/frappe/erpnext/issues/42314)) ([#42315](https://github.com/frappe/erpnext/issues/42315)) ([076bf17](076bf17439))
* items not fetching in End Transit entry (backport [#42358](https://github.com/frappe/erpnext/issues/42358)) ([#42361](https://github.com/frappe/erpnext/issues/42361)) ([b5a2e5a](b5a2e5a375))
* keep status as In Progress for RIV for Timeout Error (backport [#42274](https://github.com/frappe/erpnext/issues/42274)) ([#42296](https://github.com/frappe/erpnext/issues/42296)) ([1de66e5](1de66e56ee))
* missing discount on POS Credit Notes ([4055ef9](4055ef92b5))
* not able to cancel the inter transfer DN (backport [#42333](https://github.com/frappe/erpnext/issues/42333)) ([#42340](https://github.com/frappe/erpnext/issues/42340)) ([cf2651d](cf2651dd85))
* not able to submit LCV entry (backport [#42303](https://github.com/frappe/erpnext/issues/42303)) ([#42304](https://github.com/frappe/erpnext/issues/42304)) ([6d098b7](6d098b7302))
* remove doctype link from serial no ledger report (backport [#42327](https://github.com/frappe/erpnext/issues/42327)) ([#42348](https://github.com/frappe/erpnext/issues/42348)) ([b741b2a](b741b2a285))
* removed patch from patches.txt ([c45d11c](c45d11cd60))
* same posting date and time causing incorrect valuation rate (backport [#42351](https://github.com/frappe/erpnext/issues/42351)) ([#42356](https://github.com/frappe/erpnext/issues/42356)) ([62fc428](62fc42803f))
* service item capitalization ([#42188](https://github.com/frappe/erpnext/issues/42188)) ([2ffe7d5](2ffe7d5838))
* show total rows credit row in balance sheet ([0d2ef0d](0d2ef0df7d))
* slowness in reposting dependent vouchers. (backport [#42282](https://github.com/frappe/erpnext/issues/42282)) ([#42292](https://github.com/frappe/erpnext/issues/42292)) ([ef16313](ef16313e0a))
* **Warehouse:** add buttons only if the user can use them ([a2b21c7](a2b21c7570))
* While submitting PCV ensure previous FY is closed (backport [#42284](https://github.com/frappe/erpnext/issues/42284)) ([#42300](https://github.com/frappe/erpnext/issues/42300)) ([e250dcc](e250dcc7c8))

### Features

* configurable depreciation calculation via accounts settings ([#42276](https://github.com/frappe/erpnext/issues/42276)) ([ddd1ca7](ddd1ca7f7c))
* create variant with/without image (backport [#41317](https://github.com/frappe/erpnext/issues/41317)) ([#42343](https://github.com/frappe/erpnext/issues/42343)) ([5f1d6ed](5f1d6ede31))
2024-07-17 05:19:44 +00:00
ruthra kumar
85aca0ef55 Merge pull request #42354 from frappe/version-15-hotfix
chore: release v15
2024-07-17 10:48:30 +05:30
Nabin Hait
ce8b423ad6 chore: release v15 (#42308)
* fix(Warehouse): add buttons only if the user can use them

(cherry picked from commit 10ae5aaf52)

* fix: missing discount on POS Credit Notes

(cherry picked from commit 1049550951)

* chore: rename test suite for payable report

(cherry picked from commit 9474f72776)

* refactor: test suite for item-wise sales register

(cherry picked from commit 3aaa22e672)

* refactor(test): use each instance UOM for assertion

(cherry picked from commit cf4fbfb601)

* fix: slowness in reposting dependent vouchers. (backport #42282) (#42292)

fix: slowness in reposting dependent vouchers. (#42282)

(cherry picked from commit b17696a8ae)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>

* refactor(test): clear old records

* fix: keep status as In Progress for RIV for Timeout Error (backport #42274) (#42296)

fix: keep status as In Progress for RIV for Timeout Error (#42274)

(cherry picked from commit 10280d6140)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>

* fix: cost center filter by company (backport #42297) (#42299)

fix: cost center filter by company (#42297)

(cherry picked from commit 9838f7e6ba)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>

* feat: configurable depreciation calculation via accounts settings (#42276)

* feat: configurable depreciation calculation via accounts settings

* refactor: code optimization

* style: changes in description and label

(cherry picked from commit b04da63aad)

* fix: not able to submit LCV entry (backport #42303) (#42304)

fix: not able to submit LCV entry (#42303)

(cherry picked from commit 9cf92eaeab)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>

* fix: While submitting PCV ensure previous FY is closed (backport #42284) (#42300)

fix: While submitting PCV ensure previous FY is closed (#42284)

(cherry picked from commit d0bbc8ca70)

Co-authored-by: Nabin Hait <nabinhait@gmail.com>

---------

Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
Co-authored-by: ruthra kumar <ruthra@erpnext.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>
2024-07-12 20:47:27 +05:30
Frappe PR Bot
f975333970 chore(release): Bumped to Version 15.29.3
## [15.29.3](https://github.com/frappe/erpnext/compare/v15.29.2...v15.29.3) (2024-07-10)

### Bug Fixes

* actual qty in sales order (backport [#42248](https://github.com/frappe/erpnext/issues/42248)) ([#42256](https://github.com/frappe/erpnext/issues/42256)) ([4866958](4866958a96))
* add missing german translations ([2f89461](2f89461ace))
* added filter to show only submitted assets ([19ed6d1](19ed6d1081))
* auto serial and batch bundle not creating for Asset Capitalization (backport [#42231](https://github.com/frappe/erpnext/issues/42231)) ([#42242](https://github.com/frappe/erpnext/issues/42242)) ([7916d64](7916d6436f))
* Billed Qty and Qty to Bill Calculation in Purchase Order Analysis (backport [#42100](https://github.com/frappe/erpnext/issues/42100)) ([#42249](https://github.com/frappe/erpnext/issues/42249)) ([43c7513](43c7513cfe))
* BOM Creator Recursion Error on duplicate save (backport [#41622](https://github.com/frappe/erpnext/issues/41622)) ([#42179](https://github.com/frappe/erpnext/issues/42179)) ([68a39df](68a39dfa33))
* changes as per review ([57896a8](57896a8f99))
* completed DC will not appear in a delivery trip ([0bab609](0bab609a6f))
* completed DC will not appear in a delivery trip ([#41655](https://github.com/frappe/erpnext/issues/41655)) ([a3444a0](a3444a07b7))
* corrected mismatch in the Purchase Receipt Status [#15620](https://github.com/frappe/erpnext/issues/15620) (backport [#42138](https://github.com/frappe/erpnext/issues/42138)) ([#42252](https://github.com/frappe/erpnext/issues/42252)) ([e1b50ef](e1b50efeea))
* correcting balance sheet calculation for zero liabilities and equity ([d48a2c9](d48a2c9f8e))
* correcting balance sheet calculation for zero liabilities and equity ([#41497](https://github.com/frappe/erpnext/issues/41497)) ([2104d90](2104d903aa))
* custom delimiters ([43ad2fe](43ad2fed63))
* download_import_log if rows are greater than 5000 ([4eb251b](4eb251b59a))
* empty item-wise sales/purchase register reports on initial load ([5ac3b34](5ac3b34a6f))
* field position ([a04938d](a04938d5ae))
* group by in item-wise purchase register ([a967d59](a967d59844))
* **Holiday List:** sort holidays on save to avoid disorienting the user (backport [#42236](https://github.com/frappe/erpnext/issues/42236)) ([#42250](https://github.com/frappe/erpnext/issues/42250)) ([b555615](b5556156c1))
* import log preview ([62aac8b](62aac8bb85))
* import status ([71311ff](71311ffd62))
* **Inventory Dimension:** reduce perms for Stock User (backport [#42226](https://github.com/frappe/erpnext/issues/42226)) ([#42243](https://github.com/frappe/erpnext/issues/42243)) ([3cc59e4](3cc59e4a7a))
* manual pick allow to pick more than available stock (backport [#42155](https://github.com/frappe/erpnext/issues/42155)) ([#42159](https://github.com/frappe/erpnext/issues/42159)) ([a7b6530](a7b6530fde))
* Multiple fixes for General Ledger Report ([ca57fd4](ca57fd4255))
* multiple free items on same Item Group ([9352863](93528631c3))
* path of automatically updates the status of asset maintenance log ([5317418](5317418a53))
* Project Status should be Open again if `percent_complete` is not 100 ([90f5c78](90f5c78607))
* provision to enable do not use batch-wise valuation (backport [#42186](https://github.com/frappe/erpnext/issues/42186)) ([#42198](https://github.com/frappe/erpnext/issues/42198)) ([ec881ac](ec881ace76))
* **Putaway Rule:** reduce perms for Stock User (backport [#42227](https://github.com/frappe/erpnext/issues/42227)) ([#42244](https://github.com/frappe/erpnext/issues/42244)) ([b78a97d](b78a97df85))
* remove deprecated field "statement_import_log" ([2f0b97d](2f0b97d91b))
* removed max discount validation for sales return ([ab987e9](ab987e9a86))
* **Stock Entry Type:** reduce perms for Stock User (backport [#42225](https://github.com/frappe/erpnext/issues/42225)) ([#42245](https://github.com/frappe/erpnext/issues/42245)) ([954d9ab](954d9ab154))
* tax on stock_rbnb on repost of Purchase Receipt ([427439c](427439c3f1))
* **tds:** use doctype reference when mapping keys across multiple doctypes ([#42258](https://github.com/frappe/erpnext/issues/42258)) ([8264e3b](8264e3bc77))
* updated logic for calculating tax_withholding_net_total in payment entry ([3fb5c7a](3fb5c7a3a6))
* use standard method to get `_doc_before_save` ([cfda5f6](cfda5f6d0b))
2024-07-10 10:44:06 +00:00
ruthra kumar
38e176160c Merge pull request #42253 from frappe/version-15-hotfix
chore: release v15
2024-07-10 16:12:52 +05:30
Frappe PR Bot
c9e3dee5b2 chore(release): Bumped to Version 15.29.2
## [15.29.2](https://github.com/frappe/erpnext/compare/v15.29.1...v15.29.2) (2024-07-05)

### Bug Fixes

* blank item-wise sales/purchase register reports on first load ([8baef24](8baef24541))
* group by in item-wise purchase register ([20d481d](20d481de5e))
2024-07-05 02:47:13 +00:00
ruthra kumar
a8cd49112d Merge pull request #42191 from frappe/mergify/bp/version-15/pr-41975
fix: group by in item-wise purchase register (backport #41975)
2024-07-05 08:15:58 +05:30
ruthra kumar
8baef24541 fix: blank item-wise sales/purchase register reports on first load 2024-07-05 07:43:13 +05:30
Nihantra C. Patel
20d481de5e fix: group by in item-wise purchase register
(cherry picked from commit 3fab00135b)
2024-07-05 02:05:29 +00:00
Frappe PR Bot
7568af67e9 chore(release): Bumped to Version 15.29.1
## [15.29.1](https://github.com/frappe/erpnext/compare/v15.29.0...v15.29.1) (2024-07-03)

### Bug Fixes

* path of automatically updates the status of asset maintenance log ([473aaf4](473aaf4e5b))
2024-07-03 14:56:03 +00:00
Raffael Meyer
5dbdcb1158 Merge pull request #42171 from frappe/mergify/bp/version-15/pr-42168
fix: path of automatically updates the status of asset maintenance log (backport #42157) (backport #42168)
2024-07-03 16:54:44 +02:00
Nihantra C. Patel
473aaf4e5b fix: path of automatically updates the status of asset maintenance log
(cherry picked from commit 909aa8f359)
(cherry picked from commit 5317418a53)
2024-07-03 14:15:05 +00:00
Frappe PR Bot
5812577854 chore(release): Bumped to Version 15.29.0
# [15.29.0](https://github.com/frappe/erpnext/compare/v15.28.2...v15.29.0) (2024-07-03)

### Bug Fixes

* add auto-update for overdue status ([#42105](https://github.com/frappe/erpnext/issues/42105)) ([317cc03](317cc0358c))
* add string for translation (backport [#41903](https://github.com/frappe/erpnext/issues/41903)) ([#41963](https://github.com/frappe/erpnext/issues/41963)) ([48dc24b](48dc24b9bf))
* always post to tax account heads if LCV is booked ([706a6c1](706a6c1ad7))
* batch picking in pick list based on Stock Settings (backport [#42021](https://github.com/frappe/erpnext/issues/42021)) ([#42134](https://github.com/frappe/erpnext/issues/42134)) ([a45f8ca](a45f8ca5fd))
* batch reset while making SABB (backport [#42076](https://github.com/frappe/erpnext/issues/42076)) ([#42123](https://github.com/frappe/erpnext/issues/42123)) ([c3f5a49](c3f5a494f3))
* decimal issue in pick list (backport [#41972](https://github.com/frappe/erpnext/issues/41972)) ([#41982](https://github.com/frappe/erpnext/issues/41982)) ([9945a90](9945a90b3f))
* **Delivery Note:** only show permitted actions ([cef6d0d](cef6d0d74d))
* do not show zero balance stock items in stock balance report (backport [#41958](https://github.com/frappe/erpnext/issues/41958)) ([#41961](https://github.com/frappe/erpnext/issues/41961)) ([c10b123](c10b123a81))
* expense account from item group not fetched (backport [#41957](https://github.com/frappe/erpnext/issues/41957)) ([#41962](https://github.com/frappe/erpnext/issues/41962)) ([760b2e2](760b2e24f2))
* fixed asset value in Fixed Asset Register (backport [#41930](https://github.com/frappe/erpnext/issues/41930)) ([#42027](https://github.com/frappe/erpnext/issues/42027)) ([f2feeaf](f2feeaf264))
* handle none type object error ([b0aef9e](b0aef9e42b))
* incorrect against_account upon reposting ([a41577a](a41577a1cd))
* incorrect Difference Amount (backport [#42008](https://github.com/frappe/erpnext/issues/42008)) ([#42013](https://github.com/frappe/erpnext/issues/42013)) ([838cc5b](838cc5b72a))
* incorrect discount on other item ([77f4199](77f4199e2a))
* incorrect dr/cr on Adv Payment against Journals ([4e74257](4e74257ba9))
* incorrect time period in asset depreciation schedule (backport [#41805](https://github.com/frappe/erpnext/issues/41805)) ([#42043](https://github.com/frappe/erpnext/issues/42043)) ([cf4d4ba](cf4d4ba3e9))
* lead status filter (backport [#41816](https://github.com/frappe/erpnext/issues/41816)) ([#42046](https://github.com/frappe/erpnext/issues/42046)) ([3536a75](3536a754ff))
* manufacturing date issue in the batch (backport [#42034](https://github.com/frappe/erpnext/issues/42034)) ([#42037](https://github.com/frappe/erpnext/issues/42037)) ([a981633](a981633d94))
* move condition for shipment ([2180239](21802396ce))
* not able to make purchase return (backport [#42053](https://github.com/frappe/erpnext/issues/42053)) ([#42055](https://github.com/frappe/erpnext/issues/42055)) ([8a91bf3](8a91bf3154))
* pricing rule with and without 'apply multiple' and priority ([f3aa885](f3aa885488))
* provisional entry for non stock items ([d61dab8](d61dab8569))
* Re-open allows SO's to be over credit limit ([7fcb0f5](7fcb0f578a))
* refactor Asset Repair and Stock Entry linkage to resolve amendme… (backport [#41919](https://github.com/frappe/erpnext/issues/41919)) ([#42058](https://github.com/frappe/erpnext/issues/42058)) ([97c49b9](97c49b93b6))
* reload asset when creating asset depreciation ([7b5d504](7b5d5043c5))
* reposting file attachment permission issue (backport [#42068](https://github.com/frappe/erpnext/issues/42068)) ([#42075](https://github.com/frappe/erpnext/issues/42075)) ([1f3374f](1f3374fcdf))
* resolve gl entries duplication in asset purchase workflow (backport [#41845](https://github.com/frappe/erpnext/issues/41845)) ([#42120](https://github.com/frappe/erpnext/issues/42120)) ([58e18e2](58e18e2b1f))
* **Sales Order:** only show permitted actions ([a0011c5](a0011c5b52))
* show zero stock items filter in the stock balance report (backport [#42147](https://github.com/frappe/erpnext/issues/42147)) ([#42152](https://github.com/frappe/erpnext/issues/42152)) ([11ebbf2](11ebbf2a9c))
* stock qty validation in SCR (backport [#42124](https://github.com/frappe/erpnext/issues/42124)) ([#42133](https://github.com/frappe/erpnext/issues/42133)) ([d9e62fe](d9e62fef21))
* Stock Reservation Entry was not getting created (backport [#42033](https://github.com/frappe/erpnext/issues/42033)) ([#42035](https://github.com/frappe/erpnext/issues/42035)) ([e278fc6](e278fc683f))
* **test:** incorrect field for customer default billing currency ([3b15708](3b15708f18))
* this.frm.events.update_cost is not a function (backport [#41960](https://github.com/frappe/erpnext/issues/41960)) ([#41965](https://github.com/frappe/erpnext/issues/41965)) ([3b4d397](3b4d39766f))
* timeout error while submitting JV (backport [#42040](https://github.com/frappe/erpnext/issues/42040)) ([#42099](https://github.com/frappe/erpnext/issues/42099)) ([a0e06a4](a0e06a4ba5))
* timeout while cancelling LCV (backport [#42030](https://github.com/frappe/erpnext/issues/42030)) (backport [#42031](https://github.com/frappe/erpnext/issues/42031)) ([#42032](https://github.com/frappe/erpnext/issues/42032)) ([068de08](068de08bbb))
* unhide serial no field (backport [#42045](https://github.com/frappe/erpnext/issues/42045)) ([#42047](https://github.com/frappe/erpnext/issues/42047)) ([482832f](482832f3c2))
* valuation rate for the legacy batches (backport [#42011](https://github.com/frappe/erpnext/issues/42011)) ([#42020](https://github.com/frappe/erpnext/issues/42020)) ([f6be19c](f6be19cb7c))
* Wrong Delete Batch on Purchase Receipt (backport [#42007](https://github.com/frappe/erpnext/issues/42007)) ([#42012](https://github.com/frappe/erpnext/issues/42012)) ([68b318a](68b318a94b))

### Features

* accounting dimension filters in gp report ([fe9dffb](fe9dffb271))
* default account head for operating cost (backport [#41985](https://github.com/frappe/erpnext/issues/41985)) ([#41987](https://github.com/frappe/erpnext/issues/41987)) ([44c1671](44c16713ba))
* **gp:** group by cost center ([068ae87](068ae87b8d))
* Turkish Chart Of Accounts (backport [#41756](https://github.com/frappe/erpnext/issues/41756)) ([#42028](https://github.com/frappe/erpnext/issues/42028)) ([63b26e6](63b26e679b))

### Performance Improvements

* code optimization to handle large asset creation (backport [#42018](https://github.com/frappe/erpnext/issues/42018)) ([#42025](https://github.com/frappe/erpnext/issues/42025)) ([c27f272](c27f272f06))
* dont run queries unnecessarily, improved filters ([#41993](https://github.com/frappe/erpnext/issues/41993)) ([b59c91a](b59c91a341))
* Performance optmization for Purchase Invoice submission (backport [#40263](https://github.com/frappe/erpnext/issues/40263)) ([#41946](https://github.com/frappe/erpnext/issues/41946)) ([d396c18](d396c18689))
2024-07-03 05:06:09 +00:00
ruthra kumar
ebb8d90b4d Merge pull request #42142 from frappe/version-15-hotfix
chore: release v15
2024-07-03 10:33:25 +05:30
Danny
b80a5f27a9 fix: set default warehouse for pos invoice
(cherry picked from commit b156937254)
2024-04-01 17:08:39 +00:00
174 changed files with 13891 additions and 1302 deletions

View File

@@ -4,21 +4,21 @@
# the repo. Unless a later match takes precedence,
erpnext/accounts/ @deepeshgarg007 @ruthra-kumar
erpnext/assets/ @anandbaburajan @deepeshgarg007
erpnext/assets/ @khushi8112 @deepeshgarg007
erpnext/regional @deepeshgarg007 @ruthra-kumar
erpnext/selling @deepeshgarg007 @ruthra-kumar
erpnext/support/ @deepeshgarg007
pos*
erpnext/buying/ @rohitwaghchaure @s-aga-r
erpnext/maintenance/ @rohitwaghchaure @s-aga-r
erpnext/manufacturing/ @rohitwaghchaure @s-aga-r
erpnext/quality_management/ @rohitwaghchaure @s-aga-r
erpnext/stock/ @rohitwaghchaure @s-aga-r
erpnext/subcontracting @rohitwaghchaure @s-aga-r
erpnext/buying/ @rohitwaghchaure
erpnext/maintenance/ @rohitwaghchaure
erpnext/manufacturing/ @rohitwaghchaure
erpnext/quality_management/ @rohitwaghchaure
erpnext/stock/ @rohitwaghchaure
erpnext/subcontracting @rohitwaghchaure
erpnext/controllers/ @deepeshgarg007 @rohitwaghchaure
erpnext/patches/ @deepeshgarg007
.github/ @deepeshgarg007
pyproject.toml @phot0n
pyproject.toml @akhilnarang

View File

@@ -4,7 +4,7 @@ import inspect
import frappe
from frappe.utils.user import is_website_user
__version__ = "15.28.2"
__version__ = "15.43.1"
def get_default_company(user=None):

View File

@@ -58,7 +58,7 @@ def build_conditions(process_type, account, company):
)
if account:
conditions += f"AND {deferred_account}='{frappe.db.escape(account)}'"
conditions += f"AND {deferred_account}={frappe.db.escape(account)}"
elif company:
conditions += f"AND p.company = {frappe.db.escape(company)}"

View File

@@ -121,7 +121,7 @@
"label": "Account Type",
"oldfieldname": "account_type",
"oldfieldtype": "Select",
"options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nCurrent Asset\nCurrent Liability\nDepreciation\nDirect Expense\nDirect Income\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nIndirect Expense\nIndirect Income\nLiability\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary",
"options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nCurrent Asset\nCurrent Liability\nDepreciation\nDirect Expense\nDirect Income\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nIndirect Expense\nIndirect Income\nLiability\nPayable\nReceivable\nRound Off\nRound Off for Opening\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary",
"search_index": 1
},
{
@@ -191,7 +191,7 @@
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2024-06-27 16:23:04.444354",
"modified": "2024-08-19 15:19:11.095045",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",

View File

@@ -60,6 +60,7 @@ class Account(NestedSet):
"Payable",
"Receivable",
"Round Off",
"Round Off for Opening",
"Stock",
"Stock Adjustment",
"Stock Received But Not Billed",

View File

@@ -113,9 +113,9 @@ def get_previous_closing_entries(company, closing_date, accounting_dimensions):
entries = []
last_period_closing_voucher = frappe.db.get_all(
"Period Closing Voucher",
filters={"docstatus": 1, "company": company, "posting_date": ("<", closing_date)},
filters={"docstatus": 1, "company": company, "period_end_date": ("<", closing_date)},
fields=["name"],
order_by="posting_date desc",
order_by="period_end_date desc",
limit=1,
)

View File

@@ -58,7 +58,7 @@ frappe.ui.form.on("Accounting Dimension", {
},
label: function (frm) {
frm.set_value("fieldname", frappe.model.scrub(frm.doc.label));
frm.set_value("fieldname", frm.doc.label.replace(/ /g, "_").replace(/-/g, "_").toLowerCase());
},
document_type: function (frm) {

View File

@@ -7,6 +7,7 @@ import json
import frappe
from frappe import _, scrub
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
from frappe.database.schema import validate_column_name
from frappe.model import core_doctypes_list
from frappe.model.document import Document
from frappe.utils import cstr
@@ -60,6 +61,7 @@ class AccountingDimension(Document):
if not self.is_new():
self.validate_document_type_change()
validate_column_name(self.fieldname)
self.validate_dimension_defaults()
def validate_document_type_change(self):

View File

@@ -74,12 +74,12 @@ def get_dimension_filter_map():
a.applicable_on_account, d.dimension_value, p.accounting_dimension,
p.allow_or_restrict, a.is_mandatory
FROM
`tabApplicable On Account` a, `tabAllowed Dimension` d,
`tabApplicable On Account` a,
`tabAccounting Dimension Filter` p
LEFT JOIN `tabAllowed Dimension` d ON d.parent = p.name
WHERE
p.name = a.parent
AND p.disabled = 0
AND p.name = d.parent
""",
as_dict=1,
)
@@ -97,7 +97,6 @@ def get_dimension_filter_map():
f.allow_or_restrict,
f.is_mandatory,
)
frappe.flags.dimension_filter_map = dimension_filter_map
return frappe.flags.dimension_filter_map

View File

@@ -101,6 +101,8 @@ def validate_accounting_period_on_doc_save(doc, method=None):
date = doc.available_for_use_date
elif doc.doctype == "Asset Repair":
date = doc.completion_date
elif doc.doctype == "Period Closing Voucher":
date = doc.period_end_date
else:
date = doc.posting_date

View File

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

View File

@@ -0,0 +1,113 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2024-10-16 16:57:12.085072",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"company",
"voucher_type",
"voucher_no",
"against_voucher_type",
"against_voucher_no",
"amount",
"currency",
"event"
],
"fields": [
{
"fieldname": "voucher_type",
"fieldtype": "Link",
"label": "Voucher Type",
"options": "DocType",
"read_only": 1
},
{
"fieldname": "voucher_no",
"fieldtype": "Dynamic Link",
"label": "Voucher No",
"options": "voucher_type",
"read_only": 1
},
{
"fieldname": "against_voucher_type",
"fieldtype": "Link",
"label": "Against Voucher Type",
"options": "DocType",
"read_only": 1
},
{
"fieldname": "against_voucher_no",
"fieldtype": "Dynamic Link",
"label": "Against Voucher No",
"options": "against_voucher_type",
"read_only": 1
},
{
"fieldname": "amount",
"fieldtype": "Currency",
"label": "Amount",
"read_only": 1
},
{
"fieldname": "currency",
"fieldtype": "Link",
"label": "Currency",
"options": "Currency",
"read_only": 1
},
{
"fieldname": "event",
"fieldtype": "Data",
"label": "Event",
"read_only": 1
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"read_only": 1
}
],
"in_create": 1,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2024-11-05 10:31:28.736671",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Advance Payment Ledger Entry",
"owner": "Administrator",
"permissions": [
{
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"share": 1
},
{
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"share": 1
},
{
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Auditor",
"share": 1
}
],
"sort_field": "creation",
"sort_order": "DESC",
"states": []
}

View File

@@ -0,0 +1,27 @@
# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class AdvancePaymentLedgerEntry(Document):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from frappe.types import DF
against_voucher_no: DF.DynamicLink | None
against_voucher_type: DF.Link | None
amount: DF.Currency
company: DF.Link | None
currency: DF.Link | None
event: DF.Data | None
voucher_no: DF.DynamicLink | None
voucher_type: DF.Link | None
# end: auto-generated types
pass

View File

@@ -0,0 +1,222 @@
# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import nowdate, today
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
class TestAdvancePaymentLedgerEntry(AccountsTestMixin, FrappeTestCase):
"""
Integration tests for AdvancePaymentLedgerEntry.
Use this class for testing interactions between multiple components.
"""
def setUp(self):
self.create_company()
self.create_usd_receivable_account()
self.create_usd_payable_account()
self.create_item()
self.clear_old_entries()
def tearDown(self):
frappe.db.rollback()
def create_sales_order(self, qty=1, rate=100, currency="INR", do_not_submit=False):
"""
Helper method
"""
so = make_sales_order(
company=self.company,
customer=self.customer,
currency=currency,
item=self.item,
qty=qty,
rate=rate,
transaction_date=today(),
do_not_submit=do_not_submit,
)
return so
def create_purchase_order(self, qty=1, rate=100, currency="INR", do_not_submit=False):
"""
Helper method
"""
po = create_purchase_order(
company=self.company,
customer=self.supplier,
currency=currency,
item=self.item,
qty=qty,
rate=rate,
transaction_date=today(),
do_not_submit=do_not_submit,
)
return po
def test_so_advance_paid_and_currency_with_payment(self):
self.create_customer("_Test USD Customer", "USD")
so = self.create_sales_order(currency="USD", do_not_submit=True)
so.conversion_rate = 80
so.submit()
pe_exchange_rate = 85
pe = get_payment_entry(so.doctype, so.name, bank_account=self.cash)
pe.reference_no = "1"
pe.reference_date = nowdate()
pe.paid_from = self.debtors_usd
pe.paid_from_account_currency = "USD"
pe.source_exchange_rate = pe_exchange_rate
pe.paid_amount = so.grand_total
pe.received_amount = pe_exchange_rate * pe.paid_amount
pe.references[0].outstanding_amount = 100
pe.references[0].total_amount = 100
pe.references[0].allocated_amount = 100
pe.save().submit()
so.reload()
self.assertEqual(so.advance_paid, 100)
self.assertEqual(so.party_account_currency, "USD")
# cancel advance payment
pe.reload()
pe.cancel()
so.reload()
self.assertEqual(so.advance_paid, 0)
self.assertEqual(so.party_account_currency, "USD")
def test_so_advance_paid_and_currency_with_journal(self):
self.create_customer("_Test USD Customer", "USD")
so = self.create_sales_order(currency="USD", do_not_submit=True)
so.conversion_rate = 80
so.submit()
je_exchange_rate = 85
je = frappe.get_doc(
{
"doctype": "Journal Entry",
"company": self.company,
"voucher_type": "Journal Entry",
"posting_date": so.transaction_date,
"multi_currency": True,
"accounts": [
{
"account": self.debtors_usd,
"party_type": "Customer",
"party": so.customer,
"credit": 8500,
"credit_in_account_currency": 100,
"is_advance": "Yes",
"reference_type": so.doctype,
"reference_name": so.name,
"exchange_rate": je_exchange_rate,
},
{
"account": self.cash,
"debit": 8500,
"debit_in_account_currency": 8500,
},
],
}
)
je.save().submit()
so.reload()
self.assertEqual(so.advance_paid, 100)
self.assertEqual(so.party_account_currency, "USD")
# cancel advance payment
je.reload()
je.cancel()
so.reload()
self.assertEqual(so.advance_paid, 0)
self.assertEqual(so.party_account_currency, "USD")
def test_po_advance_paid_and_currency_with_payment(self):
self.create_supplier("_Test USD Supplier", "USD")
po = self.create_purchase_order(currency="USD", do_not_submit=True)
po.conversion_rate = 80
po.submit()
pe_exchange_rate = 85
pe = get_payment_entry(po.doctype, po.name, bank_account=self.cash)
pe.reference_no = "1"
pe.reference_date = nowdate()
pe.paid_to = self.creditors_usd
pe.paid_to_account_currency = "USD"
pe.target_exchange_rate = pe_exchange_rate
pe.received_amount = po.grand_total
pe.paid_amount = pe_exchange_rate * pe.received_amount
pe.references[0].outstanding_amount = 100
pe.references[0].total_amount = 100
pe.references[0].allocated_amount = 100
pe.save().submit()
po.reload()
self.assertEqual(po.advance_paid, 100)
self.assertEqual(po.party_account_currency, "USD")
# cancel advance payment
pe.reload()
pe.cancel()
po.reload()
self.assertEqual(po.advance_paid, 0)
self.assertEqual(po.party_account_currency, "USD")
def test_po_advance_paid_and_currency_with_journal(self):
self.create_supplier("_Test USD Supplier", "USD")
po = self.create_purchase_order(currency="USD", do_not_submit=True)
po.conversion_rate = 80
po.submit()
je_exchange_rate = 85
je = frappe.get_doc(
{
"doctype": "Journal Entry",
"company": self.company,
"voucher_type": "Journal Entry",
"posting_date": po.transaction_date,
"multi_currency": True,
"accounts": [
{
"account": self.creditors_usd,
"party_type": "Supplier",
"party": po.supplier,
"debit": 8500,
"debit_in_account_currency": 100,
"is_advance": "Yes",
"reference_type": po.doctype,
"reference_name": po.name,
"exchange_rate": je_exchange_rate,
},
{
"account": self.cash,
"credit": 8500,
"credit_in_account_currency": 8500,
},
],
}
)
je.save().submit()
po.reload()
self.assertEqual(po.advance_paid, 100)
self.assertEqual(po.party_account_currency, "USD")
# cancel advance payment
je.reload()
je.cancel()
po.reload()
self.assertEqual(po.advance_paid, 0)
self.assertEqual(po.party_account_currency, "USD")

View File

@@ -224,11 +224,6 @@
"link_doctype": "Bank Guarantee",
"link_fieldname": "bank_account"
},
{
"group": "Transactions",
"link_doctype": "Payroll Entry",
"link_fieldname": "bank_account"
},
{
"group": "Transactions",
"link_doctype": "Bank Transaction",
@@ -255,7 +250,7 @@
"link_fieldname": "default_bank_account"
}
],
"modified": "2024-09-24 06:57:41.292970",
"modified": "2024-10-30 09:41:14.113414",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account",

View File

@@ -74,6 +74,21 @@ class ExchangeRateRevaluation(Document):
if not (self.company and self.posting_date):
frappe.throw(_("Please select Company and Posting Date to getting entries"))
def before_submit(self):
self.remove_accounts_without_gain_loss()
def remove_accounts_without_gain_loss(self):
self.accounts = [account for account in self.accounts if account.gain_loss]
if not self.accounts:
frappe.throw(_("At least one account with exchange gain or loss is required"))
frappe.msgprint(
_("Removing rows without exchange gain or loss"),
alert=True,
indicator="yellow",
)
def on_cancel(self):
self.ignore_linked_doctypes = "GL Entry"
@@ -248,23 +263,23 @@ class ExchangeRateRevaluation(Document):
new_exchange_rate = get_exchange_rate(d.account_currency, company_currency, posting_date)
new_balance_in_base_currency = flt(d.balance_in_account_currency * new_exchange_rate)
gain_loss = flt(new_balance_in_base_currency, precision) - flt(d.balance, precision)
if gain_loss:
accounts.append(
{
"account": d.account,
"party_type": d.party_type,
"party": d.party,
"account_currency": d.account_currency,
"balance_in_base_currency": d.balance,
"balance_in_account_currency": d.balance_in_account_currency,
"zero_balance": d.zero_balance,
"current_exchange_rate": current_exchange_rate,
"new_exchange_rate": new_exchange_rate,
"new_balance_in_base_currency": new_balance_in_base_currency,
"new_balance_in_account_currency": d.balance_in_account_currency,
"gain_loss": gain_loss,
}
)
accounts.append(
{
"account": d.account,
"party_type": d.party_type,
"party": d.party,
"account_currency": d.account_currency,
"balance_in_base_currency": d.balance,
"balance_in_account_currency": d.balance_in_account_currency,
"zero_balance": d.zero_balance,
"current_exchange_rate": current_exchange_rate,
"new_exchange_rate": new_exchange_rate,
"new_balance_in_base_currency": new_balance_in_base_currency,
"new_balance_in_account_currency": d.balance_in_account_currency,
"gain_loss": gain_loss,
}
)
# Handle Accounts with '0' balance in Account/Base Currency
for d in [x for x in account_details if x.zero_balance]:
@@ -288,23 +303,22 @@ class ExchangeRateRevaluation(Document):
current_exchange_rate * d.balance_in_account_currency
)
if gain_loss:
accounts.append(
{
"account": d.account,
"party_type": d.party_type,
"party": d.party,
"account_currency": d.account_currency,
"balance_in_base_currency": d.balance,
"balance_in_account_currency": d.balance_in_account_currency,
"zero_balance": d.zero_balance,
"current_exchange_rate": current_exchange_rate,
"new_exchange_rate": new_exchange_rate,
"new_balance_in_base_currency": new_balance_in_base_currency,
"new_balance_in_account_currency": new_balance_in_account_currency,
"gain_loss": gain_loss,
}
)
accounts.append(
{
"account": d.account,
"party_type": d.party_type,
"party": d.party,
"account_currency": d.account_currency,
"balance_in_base_currency": d.balance,
"balance_in_account_currency": d.balance_in_account_currency,
"zero_balance": d.zero_balance,
"current_exchange_rate": current_exchange_rate,
"new_exchange_rate": new_exchange_rate,
"new_balance_in_base_currency": new_balance_in_base_currency,
"new_balance_in_account_currency": new_balance_in_account_currency,
"gain_loss": gain_loss,
}
)
return accounts

View File

@@ -4,10 +4,7 @@
frappe.ui.form.on("Fiscal Year", {
onload: function (frm) {
if (frm.doc.__islocal) {
frm.set_value(
"year_start_date",
frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)
);
frm.set_value("year_start_date", frappe.datetime.year_start());
}
},
year_start_date: function (frm) {

View File

@@ -72,10 +72,10 @@
},
{
"default": "0",
"description": "Less than 12 months.",
"description": "More/Less than 12 months.",
"fieldname": "is_short_year",
"fieldtype": "Check",
"label": "Is Short Year",
"label": "Is Short/Long Year",
"set_only_once": 1
}
],

View File

@@ -6,38 +6,50 @@
"document_type": "Document",
"engine": "InnoDB",
"field_order": [
"dates_section",
"posting_date",
"transaction_date",
"column_break_avko",
"fiscal_year",
"due_date",
"account_details_section",
"account",
"account_currency",
"column_break_ifvf",
"against",
"party_type",
"party",
"cost_center",
"debit",
"credit",
"account_currency",
"debit_in_account_currency",
"credit_in_account_currency",
"against",
"transaction_details_section",
"voucher_type",
"voucher_no",
"voucher_subtype",
"transaction_currency",
"column_break_dpsx",
"against_voucher_type",
"against_voucher",
"voucher_type",
"voucher_subtype",
"voucher_no",
"voucher_detail_no",
"transaction_exchange_rate",
"amounts_section",
"debit_in_account_currency",
"debit",
"debit_in_transaction_currency",
"column_break_bm1w",
"credit_in_account_currency",
"credit",
"credit_in_transaction_currency",
"dimensions_section",
"cost_center",
"column_break_lmnm",
"project",
"remarks",
"more_info_section",
"finance_book",
"company",
"is_opening",
"is_advance",
"fiscal_year",
"company",
"finance_book",
"column_break_8abq",
"to_rename",
"due_date",
"is_cancelled",
"transaction_currency",
"debit_in_transaction_currency",
"credit_in_transaction_currency",
"transaction_exchange_rate"
"remarks"
],
"fields": [
{
@@ -285,13 +297,67 @@
"fieldname": "voucher_subtype",
"fieldtype": "Small Text",
"label": "Voucher Subtype"
},
{
"fieldname": "dates_section",
"fieldtype": "Section Break",
"label": "Dates"
},
{
"fieldname": "column_break_avko",
"fieldtype": "Column Break"
},
{
"fieldname": "account_details_section",
"fieldtype": "Section Break",
"label": "Account Details"
},
{
"fieldname": "column_break_ifvf",
"fieldtype": "Column Break"
},
{
"fieldname": "transaction_details_section",
"fieldtype": "Section Break",
"label": "Transaction Details"
},
{
"fieldname": "amounts_section",
"fieldtype": "Section Break",
"label": "Amounts"
},
{
"fieldname": "column_break_dpsx",
"fieldtype": "Column Break"
},
{
"fieldname": "more_info_section",
"fieldtype": "Section Break",
"label": "More Info"
},
{
"fieldname": "column_break_bm1w",
"fieldtype": "Column Break"
},
{
"fieldname": "dimensions_section",
"fieldtype": "Section Break",
"label": "Dimensions"
},
{
"fieldname": "column_break_lmnm",
"fieldtype": "Column Break"
},
{
"fieldname": "column_break_8abq",
"fieldtype": "Column Break"
}
],
"icon": "fa fa-list",
"idx": 1,
"in_create": 1,
"links": [],
"modified": "2024-07-02 14:31:51.496466",
"modified": "2024-08-22 13:03:39.997475",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",

View File

@@ -430,8 +430,9 @@ def update_against_account(voucher_type, voucher_no):
def on_doctype_update():
frappe.db.add_index("GL Entry", ["against_voucher_type", "against_voucher"])
frappe.db.add_index("GL Entry", ["voucher_type", "voucher_no"])
frappe.db.add_index("GL Entry", ["posting_date", "company"])
frappe.db.add_index("GL Entry", ["party_type", "party"])
def rename_gle_sle_docs():

View File

@@ -188,6 +188,7 @@ class JournalEntry(AccountsController):
self.validate_cheque_info()
self.check_credit_limit()
self.make_gl_entries()
self.make_advance_payment_ledger_entries()
self.update_advance_paid()
self.update_asset_value()
self.update_inter_company_jv()
@@ -218,8 +219,10 @@ class JournalEntry(AccountsController):
"Repost Accounting Ledger Items",
"Unreconcile Payment",
"Unreconcile Payment Entries",
"Advance Payment Ledger Entry",
)
self.make_gl_entries(1)
self.make_advance_payment_ledger_entries()
self.update_advance_paid()
self.unlink_advance_entry_reference()
self.unlink_asset_reference()
@@ -259,7 +262,7 @@ class JournalEntry(AccountsController):
frappe.throw(_("Journal Entry type should be set as Depreciation Entry for asset depreciation"))
def validate_stock_accounts(self):
stock_accounts = get_stock_accounts(self.company, self.doctype, self.name)
stock_accounts = get_stock_accounts(self.company, accounts=self.accounts)
for account in stock_accounts:
account_bal, stock_bal, warehouse_list = get_stock_and_account_balance(
account, self.posting_date, self.company
@@ -1668,6 +1671,8 @@ def make_reverse_journal_entry(source_name, target_doc=None):
"debit": "credit",
"credit_in_account_currency": "debit_in_account_currency",
"credit": "debit",
"reference_type": "reference_type",
"reference_name": "reference_name",
},
},
},

View File

@@ -26,6 +26,10 @@ frappe.ui.form.on("Payment Entry", {
}
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
if (frm.is_new()) {
set_default_party_type(frm);
}
},
setup: function (frm) {
@@ -403,6 +407,8 @@ frappe.ui.form.on("Payment Entry", {
},
payment_type: function (frm) {
set_default_party_type(frm);
if (frm.doc.payment_type == "Internal Transfer") {
$.each(
[
@@ -1776,3 +1782,16 @@ frappe.ui.form.on("Payment Entry Deduction", {
frm.events.set_unallocated_amount(frm);
},
});
function set_default_party_type(frm) {
if (frm.doc.party) return;
let party_type;
if (frm.doc.payment_type == "Receive") {
party_type = "Customer";
} else if (frm.doc.payment_type == "Pay") {
party_type = "Supplier";
}
if (party_type) frm.set_value("party_type", party_type);
}

View File

@@ -110,6 +110,7 @@ class PaymentEntry(AccountsController):
self.update_outstanding_amounts()
self.update_payment_schedule()
self.update_payment_requests()
self.make_advance_payment_ledger_entries()
self.update_advance_paid() # advance_paid_status depends on the payment request amount
self.set_status()
@@ -190,6 +191,7 @@ class PaymentEntry(AccountsController):
"Repost Accounting Ledger Items",
"Unreconcile Payment",
"Unreconcile Payment Entries",
"Advance Payment Ledger Entry",
)
super().on_cancel()
self.make_gl_entries(cancel=1)
@@ -197,6 +199,7 @@ class PaymentEntry(AccountsController):
self.delink_advance_entry_references()
self.update_payment_schedule(cancel=1)
self.update_payment_requests(cancel=True)
self.make_advance_payment_ledger_entries()
self.update_advance_paid() # advance_paid_status depends on the payment request amount
self.set_status()
@@ -1143,6 +1146,12 @@ class PaymentEntry(AccountsController):
if self.payment_type in ("Receive", "Pay") and not self.get("party_account_field"):
self.setup_party_account_field()
company_currency = erpnext.get_company_currency(self.company)
if self.paid_from_account_currency != company_currency:
self.currency = self.paid_from_account_currency
elif self.paid_to_account_currency != company_currency:
self.currency = self.paid_to_account_currency
gl_entries = []
self.add_party_gl_entries(gl_entries)
self.add_bank_gl_entries(gl_entries)
@@ -1245,13 +1254,22 @@ class PaymentEntry(AccountsController):
base_unallocated_amount = self.unallocated_amount * exchange_rate
gle = party_gl_dict.copy()
gle.update(
{
dr_or_cr + "_in_account_currency": self.unallocated_amount,
dr_or_cr: base_unallocated_amount,
}
)
gle.update(
self.get_gl_dict(
{
"account": self.party_account,
"party_type": self.party_type,
"party": self.party,
"against": against_account,
"account_currency": self.party_account_currency,
"cost_center": self.cost_center,
dr_or_cr + "_in_account_currency": self.unallocated_amount,
dr_or_cr: base_unallocated_amount,
},
item=self,
)
)
if self.book_advance_payments_in_separate_party_account:
gle.update(
{

View File

@@ -956,6 +956,53 @@ class TestPaymentEntry(FrappeTestCase):
self.assertEqual(flt(expected_party_balance), party_balance)
self.assertEqual(flt(expected_party_account_balance, 2), flt(party_account_balance, 2))
def test_gl_of_multi_currency_payment_transaction(self):
from erpnext.setup.doctype.currency_exchange.test_currency_exchange import (
save_new_records,
test_records,
)
save_new_records(test_records)
paid_from = create_account(
parent_account="Current Liabilities - _TC",
account_name="_Test Cash USD",
company="_Test Company",
account_type="Cash",
account_currency="USD",
)
payment_entry = create_payment_entry(
party="_Test Supplier USD",
paid_from=paid_from,
paid_to="_Test Payable USD - _TC",
paid_amount=100,
save=True,
)
payment_entry.source_exchange_rate = 84.4
payment_entry.target_exchange_rate = 84.4
payment_entry.save()
payment_entry = payment_entry.submit()
gle = qb.DocType("GL Entry")
gl_entries = (
qb.from_(gle)
.select(
gle.account,
gle.debit,
gle.credit,
gle.debit_in_account_currency,
gle.credit_in_account_currency,
gle.debit_in_transaction_currency,
gle.credit_in_transaction_currency,
)
.orderby(gle.account)
.where(gle.voucher_no == payment_entry.name)
.run()
)
expected_gl_entries = (
(paid_from, 0.0, 8440.0, 0.0, 100.0, 0.0, 100.0),
("_Test Payable USD - _TC", 8440.0, 0.0, 100.0, 0.0, 100.0, 0.0),
)
self.assertEqual(gl_entries, expected_gl_entries)
def test_multi_currency_payment_entry_with_taxes(self):
payment_entry = create_payment_entry(
party="_Test Supplier USD", paid_to="_Test Payable USD - _TC", save=True

View File

@@ -211,12 +211,14 @@ class PaymentReconciliation(Document):
if self.get("cost_center"):
conditions.append(jea.cost_center == self.cost_center)
dr_or_cr = (
"credit_in_account_currency"
if erpnext.get_party_account_type(self.party_type) == "Receivable"
else "debit_in_account_currency"
)
conditions.append(jea[dr_or_cr].gt(0))
account_type = erpnext.get_party_account_type(self.party_type)
if account_type == "Receivable":
dr_or_cr = jea.credit_in_account_currency - jea.debit_in_account_currency
elif account_type == "Payable":
dr_or_cr = jea.debit_in_account_currency - jea.credit_in_account_currency
conditions.append(dr_or_cr.gt(0))
if self.bank_cash_account:
conditions.append(jea.against_account.like(f"%%{self.bank_cash_account}%%"))
@@ -231,7 +233,7 @@ class PaymentReconciliation(Document):
je.posting_date,
je.remark.as_("remarks"),
jea.name.as_("reference_row"),
jea[dr_or_cr].as_("amount"),
dr_or_cr.as_("amount"),
jea.is_advance,
jea.exchange_rate,
jea.account_currency.as_("currency"),
@@ -323,6 +325,7 @@ class PaymentReconciliation(Document):
"posting_date": inv.posting_date,
"currency": inv.currency,
"cost_center": inv.cost_center,
"remarks": inv.remarks,
}
)
)
@@ -370,6 +373,10 @@ class PaymentReconciliation(Document):
if self.invoice_limit:
non_reconciled_invoices = non_reconciled_invoices[: self.invoice_limit]
non_reconciled_invoices = sorted(
non_reconciled_invoices, key=lambda k: k["posting_date"] or getdate(nowdate())
)
self.add_invoice_entries(non_reconciled_invoices)
def add_invoice_entries(self, non_reconciled_invoices):

View File

@@ -632,6 +632,42 @@ class TestPaymentReconciliation(FrappeTestCase):
self.assertEqual(len(pr.get("invoices")), 0)
self.assertEqual(len(pr.get("payments")), 0)
def test_negative_debit_or_credit_journal_against_invoice(self):
transaction_date = nowdate()
amount = 100
si = self.create_sales_invoice(qty=1, rate=amount, posting_date=transaction_date)
# credit debtors account to record a payment
je = self.create_journal_entry(self.bank, self.debit_to, amount, transaction_date)
je.accounts[1].party_type = "Customer"
je.accounts[1].party = self.customer
je.accounts[1].credit_in_account_currency = 0
je.accounts[1].debit_in_account_currency = -1 * amount
je.save()
je.submit()
pr = self.create_payment_reconciliation()
pr.get_unreconciled_entries()
invoices = [x.as_dict() for x in pr.get("invoices")]
payments = [x.as_dict() for x in pr.get("payments")]
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
# Difference amount should not be calculated for base currency accounts
for row in pr.allocation:
self.assertEqual(flt(row.get("difference_amount")), 0.0)
pr.reconcile()
# assert outstanding
si.reload()
self.assertEqual(si.status, "Paid")
self.assertEqual(si.outstanding_amount, 0)
# check PR tool output
self.assertEqual(len(pr.get("invoices")), 0)
self.assertEqual(len(pr.get("payments")), 0)
def test_journal_against_journal(self):
transaction_date = nowdate()
sales = "Sales - _PR"
@@ -954,6 +990,100 @@ class TestPaymentReconciliation(FrappeTestCase):
frappe.db.get_value("Journal Entry", jea_parent.parent, "voucher_type"), "Exchange Gain Or Loss"
)
def test_difference_amount_via_negative_debit_or_credit_journal_entry(self):
# Make Sale Invoice
si = self.create_sales_invoice(
qty=1, rate=100, posting_date=nowdate(), do_not_save=True, do_not_submit=True
)
si.customer = self.customer4
si.currency = "EUR"
si.conversion_rate = 85
si.debit_to = self.debtors_eur
si.save().submit()
# Make payment using Journal Entry
je1 = self.create_journal_entry("HDFC - _PR", self.debtors_eur, 100, nowdate())
je1.multi_currency = 1
je1.accounts[0].exchange_rate = 1
je1.accounts[0].credit_in_account_currency = -8000
je1.accounts[0].credit = -8000
je1.accounts[0].debit_in_account_currency = 0
je1.accounts[0].debit = 0
je1.accounts[1].party_type = "Customer"
je1.accounts[1].party = self.customer4
je1.accounts[1].exchange_rate = 80
je1.accounts[1].credit_in_account_currency = 100
je1.accounts[1].credit = 8000
je1.accounts[1].debit_in_account_currency = 0
je1.accounts[1].debit = 0
je1.save()
je1.submit()
je2 = self.create_journal_entry("HDFC - _PR", self.debtors_eur, 200, nowdate())
je2.multi_currency = 1
je2.accounts[0].exchange_rate = 1
je2.accounts[0].credit_in_account_currency = -16000
je2.accounts[0].credit = -16000
je2.accounts[0].debit_in_account_currency = 0
je2.accounts[0].debit = 0
je2.accounts[1].party_type = "Customer"
je2.accounts[1].party = self.customer4
je2.accounts[1].exchange_rate = 80
je2.accounts[1].credit_in_account_currency = 200
je1.accounts[1].credit = 16000
je1.accounts[1].debit_in_account_currency = 0
je1.accounts[1].debit = 0
je2.save()
je2.submit()
pr = self.create_payment_reconciliation()
pr.party = self.customer4
pr.receivable_payable_account = self.debtors_eur
pr.get_unreconciled_entries()
self.assertEqual(len(pr.invoices), 1)
self.assertEqual(len(pr.payments), 2)
# Test exact payment allocation
invoices = [x.as_dict() for x in pr.invoices]
payments = [pr.payments[0].as_dict()]
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
self.assertEqual(pr.allocation[0].allocated_amount, 100)
self.assertEqual(pr.allocation[0].difference_amount, -500)
# Test partial payment allocation (with excess payment entry)
pr.set("allocation", [])
pr.get_unreconciled_entries()
invoices = [x.as_dict() for x in pr.invoices]
payments = [pr.payments[1].as_dict()]
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
pr.allocation[0].difference_account = "Exchange Gain/Loss - _PR"
self.assertEqual(pr.allocation[0].allocated_amount, 100)
self.assertEqual(pr.allocation[0].difference_amount, -500)
# Check if difference journal entry gets generated for difference amount after reconciliation
pr.reconcile()
total_credit_amount = frappe.db.get_all(
"Journal Entry Account",
{"account": self.debtors_eur, "docstatus": 1, "reference_name": si.name},
"sum(credit) as amount",
group_by="reference_name",
)[0].amount
# total credit includes the exchange gain/loss amount
self.assertEqual(flt(total_credit_amount, 2), 8500)
jea_parent = frappe.db.get_all(
"Journal Entry Account",
filters={"account": self.debtors_eur, "docstatus": 1, "reference_name": si.name, "credit": 500},
fields=["parent"],
)[0]
self.assertEqual(
frappe.db.get_value("Journal Entry", jea_parent.parent, "voucher_type"), "Exchange Gain Or Loss"
)
def test_difference_amount_via_payment_entry(self):
# Make Sale Invoice
si = self.create_sales_invoice(
@@ -1986,13 +2116,15 @@ def make_period_closing_voucher(company, cost_center, posting_date=None, submit=
parent_account=parent_account,
doctype="Account",
)
fy = get_fiscal_year(posting_date, company=company)
pcv = frappe.get_doc(
{
"doctype": "Period Closing Voucher",
"transaction_date": posting_date or today(),
"posting_date": posting_date or today(),
"period_start_date": fy[1],
"period_end_date": fy[2],
"company": company,
"fiscal_year": get_fiscal_year(posting_date or today(), company=company)[0],
"fiscal_year": fy[0],
"cost_center": cost_center,
"closing_account_head": surplus_account,
"remarks": "test",

View File

@@ -14,7 +14,7 @@
"amount",
"difference_amount",
"sec_break1",
"remark",
"remarks",
"currency",
"exchange_rate",
"cost_center"
@@ -74,12 +74,6 @@
"fieldname": "sec_break1",
"fieldtype": "Section Break"
},
{
"fieldname": "remark",
"fieldtype": "Small Text",
"label": "Remark",
"read_only": 1
},
{
"fieldname": "currency",
"fieldtype": "Link",
@@ -105,12 +99,18 @@
"fieldtype": "Link",
"label": "Cost Center",
"options": "Cost Center"
},
{
"fieldname": "remarks",
"fieldtype": "Small Text",
"label": "Remarks",
"read_only": 1
}
],
"is_virtual": 1,
"istable": 1,
"links": [],
"modified": "2023-11-17 17:33:34.818530",
"modified": "2024-10-29 16:24:43.021230",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Reconciliation Payment",

View File

@@ -27,7 +27,7 @@ class PaymentReconciliationPayment(Document):
reference_name: DF.DynamicLink | None
reference_row: DF.Data | None
reference_type: DF.Link | None
remark: DF.SmallText | None
remarks: DF.SmallText | None
# end: auto-generated types
@staticmethod

View File

@@ -14,6 +14,7 @@
"party_details",
"party_type",
"party",
"party_name",
"column_break_4",
"reference_doctype",
"reference_name",
@@ -422,13 +423,19 @@
"label": "Party Account Currency",
"options": "Currency",
"read_only": 1
},
{
"fieldname": "party_name",
"fieldtype": "Data",
"label": "Party Name",
"read_only": 1
}
],
"in_create": 1,
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2024-09-16 17:50:54.440090",
"modified": "2024-10-23 12:23:40.117336",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Request",
@@ -467,4 +474,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -1,7 +1,7 @@
import json
import frappe
from frappe import _
from frappe import _, qb
from frappe.model.document import Document
from frappe.query_builder.functions import Sum
from frappe.utils import flt, nowdate
@@ -20,14 +20,6 @@ from erpnext.accounts.party import get_party_account, get_party_bank_account
from erpnext.accounts.utils import get_account_currency, get_currency_precision
from erpnext.utilities import payment_app_import_guard
def _get_payment_gateway_controller(*args, **kwargs):
with payment_app_import_guard():
from payments.utils import get_payment_gateway_controller
return get_payment_gateway_controller(*args, **kwargs)
ALLOWED_DOCTYPES_FOR_PAYMENT_REQUEST = [
"Sales Order",
"Purchase Order",
@@ -38,6 +30,13 @@ ALLOWED_DOCTYPES_FOR_PAYMENT_REQUEST = [
]
def _get_payment_gateway_controller(*args, **kwargs):
with payment_app_import_guard():
from payments.utils import get_payment_gateway_controller
return get_payment_gateway_controller(*args, **kwargs)
class PaymentRequest(Document):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
@@ -72,6 +71,7 @@ class PaymentRequest(Document):
outstanding_amount: DF.Currency
party: DF.DynamicLink | None
party_account_currency: DF.Link | None
party_name: DF.Data | None
party_type: DF.Link | None
payment_account: DF.ReadOnly | None
payment_channel: DF.Literal["", "Email", "Phone", "Other"]
@@ -304,12 +304,12 @@ class PaymentRequest(Document):
return controller.get_payment_url(
**{
"amount": flt(self.grand_total, self.precision("grand_total")),
"title": data.company.encode("utf-8"),
"description": self.subject.encode("utf-8"),
"title": data.company,
"description": self.subject,
"reference_doctype": "Payment Request",
"reference_docname": self.name,
"payer_email": self.email_to or frappe.session.user,
"payer_name": frappe.safe_encode(data.customer_name),
"payer_name": data.customer_name,
"order_id": self.name,
"currency": self.currency,
}
@@ -534,15 +534,9 @@ def make_payment_request(**args):
"""Make payment request"""
args = frappe._dict(args)
<<<<<<< HEAD
=======
ref_doc = args.ref_doc or frappe.get_doc(args.dt, args.dn)
if ref_doc.doctype not in ALLOWED_DOCTYPES_FOR_PAYMENT_REQUEST:
frappe.throw(
_("Payment Requests cannot be created against: {0}").format(frappe.bold(ref_doc.doctype))
)
>>>>>>> fc2cac62c1 (fix: only show pay button for specific doctype in portal)
if args.dt not in ALLOWED_DOCTYPES_FOR_PAYMENT_REQUEST:
frappe.throw(_("Payment Requests cannot be created against: {0}").format(frappe.bold(args.dt)))
ref_doc = frappe.get_doc(args.dt, args.dn)
gateway_account = get_gateway_details(args) or frappe._dict()
@@ -570,11 +564,24 @@ def make_payment_request(**args):
# fetches existing payment request `grand_total` amount
existing_payment_request_amount = get_existing_payment_request_amount(ref_doc.doctype, ref_doc.name)
if existing_payment_request_amount:
def validate_and_calculate_grand_total(grand_total, existing_payment_request_amount):
grand_total -= existing_payment_request_amount
if not grand_total:
frappe.throw(_("Payment Request is already created"))
return grand_total
if existing_payment_request_amount:
if args.order_type == "Shopping Cart":
# If Payment Request is in an advanced stage, then create for remaining amount.
if get_existing_payment_request_amount(
ref_doc.doctype, ref_doc.name, ["Initiated", "Partially Paid", "Payment Ordered", "Paid"]
):
grand_total = validate_and_calculate_grand_total(grand_total, existing_payment_request_amount)
else:
# If PR's are processed, cancel all of them.
cancel_old_payment_requests(ref_doc.doctype, ref_doc.name)
else:
grand_total = validate_and_calculate_grand_total(grand_total, existing_payment_request_amount)
if draft_payment_request:
frappe.db.set_value(
@@ -616,6 +623,7 @@ def make_payment_request(**args):
"party_type": party_type,
"party": args.get("party") or ref_doc.get("customer"),
"bank_account": bank_account,
"party_name": args.get("party_name") or ref_doc.get("customer_name"),
}
)
@@ -683,21 +691,65 @@ def get_amount(ref_doc, payment_account=None):
frappe.throw(_("Payment Entry is already created"))
def get_existing_payment_request_amount(ref_dt, ref_dn):
def get_irequest_status(payment_requests: None | list = None) -> list:
IR = frappe.qb.DocType("Integration Request")
res = []
if payment_requests:
res = (
frappe.qb.from_(IR)
.select(IR.name)
.where(IR.reference_doctype.eq("Payment Request"))
.where(IR.reference_docname.isin(payment_requests))
.where(IR.status.isin(["Authorized", "Completed"]))
.run(as_dict=True)
)
return res
def cancel_old_payment_requests(ref_dt, ref_dn):
PR = frappe.qb.DocType("Payment Request")
if res := (
frappe.qb.from_(PR)
.select(PR.name)
.where(PR.reference_doctype == ref_dt)
.where(PR.reference_name == ref_dn)
.where(PR.docstatus == 1)
.where(PR.status.isin(["Draft", "Requested"]))
.run(as_dict=True)
):
if get_irequest_status([x.name for x in res]):
frappe.throw(_("Another Payment Request is already processed"))
else:
for x in res:
doc = frappe.get_doc("Payment Request", x.name)
doc.flags.ignore_permissions = True
doc.cancel()
if ireqs := get_irequests_of_payment_request(doc.name):
for ireq in ireqs:
frappe.db.set_value("Integration Request", ireq.name, "status", "Cancelled")
def get_existing_payment_request_amount(ref_dt, ref_dn, statuses: list | None = None) -> list:
"""
Return the total amount of Payment Requests against a reference document.
"""
PR = frappe.qb.DocType("Payment Request")
response = (
query = (
frappe.qb.from_(PR)
.select(Sum(PR.grand_total))
.where(PR.reference_doctype == ref_dt)
.where(PR.reference_name == ref_dn)
.where(PR.docstatus == 1)
.run()
)
if statuses:
query = query.where(PR.status.isin(statuses))
response = query.run()
return response[0][0] if response[0] else 0
@@ -893,17 +945,18 @@ def validate_payment(doc, method=None):
@frappe.whitelist()
def get_open_payment_requests_query(doctype, txt, searchfield, start, page_len, filters):
# permission checks in `get_list()`
reference_doctype = filters.get("reference_doctype")
reference_name = filters.get("reference_doctype")
filters = frappe._dict(filters)
if not reference_doctype or not reference_name:
if not filters.reference_doctype or not filters.reference_name:
return []
if txt:
filters.name = ["like", f"%{txt}%"]
open_payment_requests = frappe.get_list(
"Payment Request",
filters={
"reference_doctype": filters["reference_doctype"],
"reference_name": filters["reference_name"],
**filters,
"status": ["!=", "Paid"],
"outstanding_amount": ["!=", 0], # for compatibility with old data
"docstatus": 1,
@@ -920,3 +973,17 @@ def get_open_payment_requests_query(doctype, txt, searchfield, start, page_len,
)
for pr in open_payment_requests
]
def get_irequests_of_payment_request(doc: str | None = None) -> list:
res = []
if doc:
res = frappe.db.get_all(
"Integration Request",
{
"reference_doctype": "Payment Request",
"reference_docname": doc,
"status": "Queued",
},
)
return res

View File

@@ -19,6 +19,24 @@ frappe.ui.form.on("Period Closing Voucher", {
});
},
fiscal_year: function (frm) {
if (frm.doc.fiscal_year) {
frappe.call({
method: "erpnext.accounts.doctype.period_closing_voucher.period_closing_voucher.get_period_start_end_date",
args: {
fiscal_year: frm.doc.fiscal_year,
company: frm.doc.company,
},
callback: function (r) {
if (r.message) {
frm.set_value("period_start_date", r.message[0]);
frm.set_value("period_end_date", r.message[1]);
}
},
});
}
},
refresh: function (frm) {
if (frm.doc.docstatus > 0) {
frm.add_custom_button(

View File

@@ -6,39 +6,32 @@
"engine": "InnoDB",
"field_order": [
"transaction_date",
"posting_date",
"fiscal_year",
"year_start_date",
"amended_from",
"company",
"fiscal_year",
"period_start_date",
"period_end_date",
"amended_from",
"column_break1",
"closing_account_head",
"remarks",
"gle_processing_status",
"remarks",
"error_message"
],
"fields": [
{
"default": "Today",
"fieldname": "transaction_date",
"fieldtype": "Date",
"label": "Transaction Date",
"oldfieldname": "transaction_date",
"oldfieldtype": "Date"
},
{
"fieldname": "posting_date",
"fieldtype": "Date",
"label": "Posting Date",
"oldfieldname": "posting_date",
"oldfieldtype": "Date",
"reqd": 1
},
{
"fieldname": "fiscal_year",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Closing Fiscal Year",
"label": "Fiscal Year",
"oldfieldname": "fiscal_year",
"oldfieldtype": "Select",
"options": "Fiscal Year",
@@ -103,16 +96,25 @@
"read_only": 1
},
{
"fieldname": "year_start_date",
"fieldname": "period_end_date",
"fieldtype": "Date",
"label": "Year Start Date"
"label": "Period End Date",
"reqd": 1
},
{
"fieldname": "period_start_date",
"fieldtype": "Date",
"label": "Period Start Date",
"oldfieldname": "posting_date",
"oldfieldtype": "Date",
"reqd": 1
}
],
"icon": "fa fa-file-text",
"idx": 1,
"is_submittable": 1,
"links": [],
"modified": "2023-09-11 20:19:11.810533",
"modified": "2024-09-15 17:22:45.291628",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Period Closing Voucher",
@@ -148,7 +150,7 @@
"write": 1
}
],
"search_fields": "posting_date, fiscal_year",
"search_fields": "fiscal_year, period_start_date, period_end_date",
"sort_field": "modified",
"sort_order": "DESC",
"states": [],

View File

@@ -2,15 +2,20 @@
# License: GNU General Public License v3. See license.txt
import copy
import frappe
from frappe import _
from frappe.query_builder.functions import Sum
from frappe.utils import add_days, flt
from frappe.utils import add_days, flt, formatdate, getdate
from erpnext.accounts.doctype.account_closing_balance.account_closing_balance import (
make_closing_entries,
)
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_accounting_dimensions,
)
from erpnext.accounts.utils import get_account_currency, get_fiscal_year, validate_fiscal_year
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
from erpnext.controllers.accounts_controller import AccountsController
@@ -29,36 +34,397 @@ class PeriodClosingVoucher(AccountsController):
error_message: DF.Text | None
fiscal_year: DF.Link
gle_processing_status: DF.Literal["In Progress", "Completed", "Failed"]
posting_date: DF.Date
period_end_date: DF.Date
period_start_date: DF.Date
remarks: DF.SmallText
transaction_date: DF.Date | None
year_start_date: DF.Date | None
# end: auto-generated types
def validate(self):
self.validate_account_head()
self.validate_posting_date()
self.validate_start_and_end_date()
self.check_if_previous_year_closed()
self.block_if_future_closing_voucher_exists()
self.check_closing_account_type()
self.check_closing_account_currency()
def validate_start_and_end_date(self):
self.fy_start_date, self.fy_end_date = frappe.db.get_value(
"Fiscal Year", self.fiscal_year, ["year_start_date", "year_end_date"]
)
prev_closed_period_end_date = get_previous_closed_period_in_current_year(
self.fiscal_year, self.company
)
valid_start_date = (
add_days(prev_closed_period_end_date, 1) if prev_closed_period_end_date else self.fy_start_date
)
if getdate(self.period_start_date) != getdate(valid_start_date):
frappe.throw(_("Period Start Date must be {0}").format(formatdate(valid_start_date)))
if getdate(self.period_start_date) > getdate(self.period_end_date):
frappe.throw(_("Period Start Date cannot be greater than Period End Date"))
if getdate(self.period_end_date) > getdate(self.fy_end_date):
frappe.throw(_("Period End Date cannot be greater than Fiscal Year End Date"))
def check_if_previous_year_closed(self):
last_year_closing = add_days(self.fy_start_date, -1)
previous_fiscal_year = get_fiscal_year(last_year_closing, company=self.company, boolean=True)
if not previous_fiscal_year:
return
previous_fiscal_year_start_date = previous_fiscal_year[0][1]
gle_exists_in_previous_year = frappe.db.exists(
"GL Entry",
{
"posting_date": ("between", [previous_fiscal_year_start_date, last_year_closing]),
"company": self.company,
"is_cancelled": 0,
},
)
if not gle_exists_in_previous_year:
return
previous_fiscal_year_closed = frappe.db.exists(
"Period Closing Voucher",
{
"period_end_date": ("between", [previous_fiscal_year_start_date, last_year_closing]),
"docstatus": 1,
"company": self.company,
},
)
if not previous_fiscal_year_closed:
frappe.throw(_("Previous Year is not closed, please close it first"))
def block_if_future_closing_voucher_exists(self):
future_closing_voucher = self.get_future_closing_voucher()
if future_closing_voucher and future_closing_voucher[0][0]:
action = "cancel" if self.docstatus == 2 else "create"
frappe.throw(
_(
"You cannot {0} this document because another Period Closing Entry {1} exists after {2}"
).format(action, future_closing_voucher[0][0], self.period_end_date)
)
def get_future_closing_voucher(self):
return frappe.db.get_value(
"Period Closing Voucher",
{"period_end_date": (">", self.period_end_date), "docstatus": 1, "company": self.company},
"name",
)
def check_closing_account_type(self):
closing_account_type = frappe.get_cached_value("Account", self.closing_account_head, "root_type")
if closing_account_type not in ["Liability", "Equity"]:
frappe.throw(
_("Closing Account {0} must be of type Liability / Equity").format(self.closing_account_head)
)
def check_closing_account_currency(self):
account_currency = get_account_currency(self.closing_account_head)
company_currency = frappe.get_cached_value("Company", self.company, "default_currency")
if account_currency != company_currency:
frappe.throw(_("Currency of the Closing Account must be {0}").format(company_currency))
def on_submit(self):
self.db_set("gle_processing_status", "In Progress")
get_opening_entries = False
if not frappe.db.exists(
"Period Closing Voucher", {"company": self.company, "docstatus": 1, "name": ("!=", self.name)}
):
get_opening_entries = True
self.make_gl_entries(get_opening_entries=get_opening_entries)
self.make_gl_entries()
def on_cancel(self):
self.validate_future_closing_vouchers()
self.db_set("gle_processing_status", "In Progress")
self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Payment Ledger Entry")
gle_count = frappe.db.count(
self.block_if_future_closing_voucher_exists()
self.db_set("gle_processing_status", "In Progress")
self.cancel_gl_entries()
def make_gl_entries(self):
if self.get_gle_count_in_selected_period() > 5000:
frappe.enqueue(
process_gl_and_closing_entries,
doc=self,
timeout=1800,
)
frappe.msgprint(
_(
"The GL Entries and closing balances will be processed in the background, it can take a few minutes."
),
alert=True,
)
else:
process_gl_and_closing_entries(self)
def get_gle_count_in_selected_period(self):
return frappe.db.count(
"GL Entry",
{"voucher_type": "Period Closing Voucher", "voucher_no": self.name, "is_cancelled": 0},
{
"posting_date": ["between", [self.period_start_date, self.period_end_date]],
"company": self.company,
"is_cancelled": 0,
},
)
if gle_count > 5000:
def get_pcv_gl_entries(self):
self.pl_accounts_reverse_gle = []
self.closing_account_gle = []
pl_account_balances = self.get_account_balances_based_on_dimensions(report_type="Profit and Loss")
for dimensions, account_balances in pl_account_balances.items():
for acc, balances in account_balances.items():
balance_in_company_currency = flt(balances.debit_in_account_currency) - flt(
balances.credit_in_account_currency
)
if balance_in_company_currency and acc != "balances":
self.pl_accounts_reverse_gle.append(
self.get_gle_for_pl_account(acc, balances, dimensions)
)
# closing liability account
self.closing_account_gle.append(
self.get_gle_for_closing_account(account_balances["balances"], dimensions)
)
return self.pl_accounts_reverse_gle + self.closing_account_gle
def get_gle_for_pl_account(self, acc, balances, dimensions):
balance_in_account_currency = flt(balances.debit_in_account_currency) - flt(
balances.credit_in_account_currency
)
balance_in_company_currency = flt(balances.debit) - flt(balances.credit)
gl_entry = frappe._dict(
{
"company": self.company,
"posting_date": self.period_end_date,
"account": acc,
"account_currency": balances.account_currency,
"debit_in_account_currency": abs(balance_in_account_currency)
if balance_in_account_currency < 0
else 0,
"debit": abs(balance_in_company_currency) if balance_in_company_currency < 0 else 0,
"credit_in_account_currency": abs(balance_in_account_currency)
if balance_in_account_currency > 0
else 0,
"credit": abs(balance_in_company_currency) if balance_in_company_currency > 0 else 0,
"is_period_closing_voucher_entry": 1,
"voucher_type": "Period Closing Voucher",
"voucher_no": self.name,
"fiscal_year": self.fiscal_year,
"remarks": self.remarks,
"is_opening": "No",
}
)
self.update_default_dimensions(gl_entry, dimensions)
return gl_entry
def get_gle_for_closing_account(self, dimension_balance, dimensions):
balance_in_account_currency = flt(dimension_balance.balance_in_account_currency)
balance_in_company_currency = flt(dimension_balance.balance_in_company_currency)
gl_entry = frappe._dict(
{
"company": self.company,
"posting_date": self.period_end_date,
"account": self.closing_account_head,
"account_currency": frappe.db.get_value(
"Account", self.closing_account_head, "account_currency"
),
"debit_in_account_currency": balance_in_account_currency
if balance_in_account_currency > 0
else 0,
"debit": balance_in_company_currency if balance_in_company_currency > 0 else 0,
"credit_in_account_currency": abs(balance_in_account_currency)
if balance_in_account_currency < 0
else 0,
"credit": abs(balance_in_company_currency) if balance_in_company_currency < 0 else 0,
"is_period_closing_voucher_entry": 1,
"voucher_type": "Period Closing Voucher",
"voucher_no": self.name,
"fiscal_year": self.fiscal_year,
"remarks": self.remarks,
"is_opening": "No",
}
)
self.update_default_dimensions(gl_entry, dimensions)
return gl_entry
def update_default_dimensions(self, gl_entry, dimensions):
for i, dimension in enumerate(self.accounting_dimension_fields):
gl_entry[dimension] = dimensions[i]
def get_account_balances_based_on_dimensions(self, report_type):
"""Get balance for dimension-wise pl accounts"""
self.get_accounting_dimension_fields()
acc_bal_dict = frappe._dict()
gl_entries = []
with frappe.db.unbuffered_cursor():
gl_entries = self.get_gl_entries_for_current_period(report_type, as_iterator=True)
for gle in gl_entries:
acc_bal_dict = self.set_account_balance_dict(gle, acc_bal_dict)
if report_type == "Balance Sheet" and self.is_first_period_closing_voucher():
opening_entries = self.get_gl_entries_for_current_period(report_type, only_opening_entries=True)
for gle in opening_entries:
acc_bal_dict = self.set_account_balance_dict(gle, acc_bal_dict)
return acc_bal_dict
def get_accounting_dimension_fields(self):
default_dimensions = ["cost_center", "finance_book", "project"]
self.accounting_dimension_fields = default_dimensions + get_accounting_dimensions()
def get_gl_entries_for_current_period(self, report_type, only_opening_entries=False, as_iterator=False):
date_condition = ""
if only_opening_entries:
date_condition = "is_opening = 'Yes'"
else:
date_condition = f"posting_date BETWEEN '{self.period_start_date}' AND '{self.period_end_date}' and is_opening = 'No'"
# nosemgrep
return frappe.db.sql(
"""
SELECT
name,
posting_date,
account,
account_currency,
debit_in_account_currency,
credit_in_account_currency,
debit,
credit,
{}
FROM `tabGL Entry`
WHERE
{}
AND company = %s
AND voucher_type != 'Period Closing Voucher'
AND EXISTS(SELECT name FROM `tabAccount` WHERE name = account AND report_type = %s)
AND is_cancelled = 0
""".format(
", ".join(self.accounting_dimension_fields),
date_condition,
),
(self.company, report_type),
as_dict=1,
as_iterator=as_iterator,
)
def set_account_balance_dict(self, gle, acc_bal_dict):
key = self.get_key(gle)
acc_bal_dict.setdefault(key, frappe._dict()).setdefault(
gle.account,
frappe._dict(
{
"debit_in_account_currency": 0,
"credit_in_account_currency": 0,
"debit": 0,
"credit": 0,
"account_currency": gle.account_currency,
}
),
)
acc_bal_dict[key][gle.account].debit_in_account_currency += flt(gle.debit_in_account_currency)
acc_bal_dict[key][gle.account].credit_in_account_currency += flt(gle.credit_in_account_currency)
acc_bal_dict[key][gle.account].debit += flt(gle.debit)
acc_bal_dict[key][gle.account].credit += flt(gle.credit)
# dimension-wise total balances
acc_bal_dict[key].setdefault(
"balances",
frappe._dict(
{
"balance_in_account_currency": 0,
"balance_in_company_currency": 0,
}
),
)
balance_in_account_currency = flt(gle.debit_in_account_currency) - flt(gle.credit_in_account_currency)
balance_in_company_currency = flt(gle.debit) - flt(gle.credit)
acc_bal_dict[key]["balances"].balance_in_account_currency += balance_in_account_currency
acc_bal_dict[key]["balances"].balance_in_company_currency += balance_in_company_currency
return acc_bal_dict
def get_key(self, gle):
return tuple([gle.get(dimension) for dimension in self.accounting_dimension_fields])
def get_account_closing_balances(self):
pl_closing_entries = self.get_closing_entries_for_pl_accounts()
bs_closing_entries = self.get_closing_entries_for_balance_sheet_accounts()
closing_entries_for_closing_account = self.get_closing_entries_for_closing_account()
closing_entries = pl_closing_entries + bs_closing_entries + closing_entries_for_closing_account
return closing_entries
def get_closing_entries_for_pl_accounts(self):
closing_entries = copy.deepcopy(self.pl_accounts_reverse_gle)
for d in self.pl_accounts_reverse_gle:
# reverse debit and credit
gle_copy = copy.deepcopy(d)
gle_copy.debit = d.credit
gle_copy.credit = d.debit
gle_copy.debit_in_account_currency = d.credit_in_account_currency
gle_copy.credit_in_account_currency = d.debit_in_account_currency
gle_copy.is_period_closing_voucher_entry = 0
gle_copy.period_closing_voucher = self.name
closing_entries.append(gle_copy)
return closing_entries
def get_closing_entries_for_balance_sheet_accounts(self):
closing_entries = []
balance_sheet_account_balances = self.get_account_balances_based_on_dimensions(
report_type="Balance Sheet"
)
for dimensions, account_balances in balance_sheet_account_balances.items():
for acc, balances in account_balances.items():
balance_in_company_currency = flt(balances.debit) - flt(balances.credit)
if acc != "balances" and balance_in_company_currency:
closing_entries.append(self.get_closing_entry(acc, balances, dimensions))
return closing_entries
def get_closing_entry(self, account, balances, dimensions):
closing_entry = frappe._dict(
{
"company": self.company,
"closing_date": self.period_end_date,
"period_closing_voucher": self.name,
"account": account,
"account_currency": balances.account_currency,
"debit_in_account_currency": flt(balances.debit_in_account_currency),
"debit": flt(balances.debit),
"credit_in_account_currency": flt(balances.credit_in_account_currency),
"credit": flt(balances.credit),
"is_period_closing_voucher_entry": 0,
}
)
self.update_default_dimensions(closing_entry, dimensions)
return closing_entry
def get_closing_entries_for_closing_account(self):
closing_entries = copy.deepcopy(self.closing_account_gle)
for d in closing_entries:
d.period_closing_voucher = self.name
return closing_entries
def is_first_period_closing_voucher(self):
first_pcv = frappe.db.get_value(
"Period Closing Voucher",
{"company": self.company, "docstatus": 1},
"name",
order_by="period_end_date asc",
)
if not first_pcv or first_pcv == self.name:
return True
def cancel_gl_entries(self):
if self.get_gle_count_against_current_pcv() > 5000:
frappe.enqueue(
process_cancellation,
voucher_type="Period Closing Voucher",
@@ -73,308 +439,29 @@ class PeriodClosingVoucher(AccountsController):
else:
process_cancellation(voucher_type="Period Closing Voucher", voucher_no=self.name)
def validate_future_closing_vouchers(self):
if frappe.db.exists(
"Period Closing Voucher",
{"posting_date": (">", self.posting_date), "docstatus": 1, "company": self.company},
):
frappe.throw(
_(
"You can not cancel this Period Closing Voucher, please cancel the future Period Closing Vouchers first"
)
)
def validate_account_head(self):
closing_account_type = frappe.get_cached_value("Account", self.closing_account_head, "root_type")
if closing_account_type not in ["Liability", "Equity"]:
frappe.throw(
_("Closing Account {0} must be of type Liability / Equity").format(self.closing_account_head)
)
account_currency = get_account_currency(self.closing_account_head)
company_currency = frappe.get_cached_value("Company", self.company, "default_currency")
if account_currency != company_currency:
frappe.throw(_("Currency of the Closing Account must be {0}").format(company_currency))
def validate_posting_date(self):
validate_fiscal_year(
self.posting_date, self.fiscal_year, self.company, label=_("Posting Date"), doc=self
)
self.year_start_date = get_fiscal_year(self.posting_date, self.fiscal_year, company=self.company)[1]
self.check_if_previous_year_closed()
pcv = frappe.qb.DocType("Period Closing Voucher")
existing_entry = (
frappe.qb.from_(pcv)
.select(pcv.name)
.where(
(pcv.posting_date >= self.posting_date)
& (pcv.fiscal_year == self.fiscal_year)
& (pcv.docstatus == 1)
& (pcv.company == self.company)
)
.run()
)
if existing_entry and existing_entry[0][0]:
frappe.throw(
_("Another Period Closing Entry {0} has been made after {1}").format(
existing_entry[0][0], self.posting_date
)
)
def check_if_previous_year_closed(self):
last_year_closing = add_days(self.year_start_date, -1)
previous_fiscal_year = get_fiscal_year(last_year_closing, company=self.company, boolean=True)
if not previous_fiscal_year:
return
previous_fiscal_year_start_date = previous_fiscal_year[0][1]
if not frappe.db.exists(
def get_gle_count_against_current_pcv(self):
return frappe.db.count(
"GL Entry",
{
"posting_date": ("between", [previous_fiscal_year_start_date, last_year_closing]),
"company": self.company,
"is_cancelled": 0,
},
):
return
if not frappe.db.exists(
"Period Closing Voucher",
{
"posting_date": ("between", [previous_fiscal_year_start_date, last_year_closing]),
"docstatus": 1,
"company": self.company,
},
):
frappe.throw(_("Previous Year is not closed, please close it first"))
def make_gl_entries(self, get_opening_entries=False):
gl_entries = self.get_gl_entries()
closing_entries = self.get_grouped_gl_entries(get_opening_entries=get_opening_entries)
if len(gl_entries + closing_entries) > 3000:
frappe.enqueue(
process_gl_and_closing_entries,
gl_entries=gl_entries,
closing_entries=closing_entries,
voucher_name=self.name,
company=self.company,
closing_date=self.posting_date,
timeout=3000,
)
frappe.msgprint(
_("The GL Entries will be processed in the background, it can take a few minutes."),
alert=True,
)
else:
process_gl_and_closing_entries(
gl_entries, closing_entries, self.name, self.company, self.posting_date
)
def get_grouped_gl_entries(self, get_opening_entries=False):
closing_entries = []
for acc in self.get_balances_based_on_dimensions(
group_by_account=True, for_aggregation=True, get_opening_entries=get_opening_entries
):
closing_entries.append(self.get_closing_entries(acc))
return closing_entries
def get_gl_entries(self):
gl_entries = []
# pl account
for acc in self.get_balances_based_on_dimensions(
group_by_account=True, report_type="Profit and Loss"
):
if flt(acc.bal_in_company_currency):
gl_entries.append(self.get_gle_for_pl_account(acc))
# closing liability account
for acc in self.get_balances_based_on_dimensions(
group_by_account=False, report_type="Profit and Loss"
):
if flt(acc.bal_in_company_currency):
gl_entries.append(self.get_gle_for_closing_account(acc))
return gl_entries
def get_gle_for_pl_account(self, acc):
gl_entry = self.get_gl_dict(
{
"company": self.company,
"closing_date": self.posting_date,
"account": acc.account,
"cost_center": acc.cost_center,
"finance_book": acc.finance_book,
"account_currency": acc.account_currency,
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency))
if flt(acc.bal_in_account_currency) < 0
else 0,
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0,
"credit_in_account_currency": abs(flt(acc.bal_in_account_currency))
if flt(acc.bal_in_account_currency) > 0
else 0,
"credit": abs(flt(acc.bal_in_company_currency))
if flt(acc.bal_in_company_currency) > 0
else 0,
"is_period_closing_voucher_entry": 1,
},
item=acc,
)
self.update_default_dimensions(gl_entry, acc)
return gl_entry
def get_gle_for_closing_account(self, acc):
gl_entry = self.get_gl_dict(
{
"company": self.company,
"closing_date": self.posting_date,
"account": self.closing_account_head,
"cost_center": acc.cost_center,
"finance_book": acc.finance_book,
"account_currency": acc.account_currency,
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency))
if flt(acc.bal_in_account_currency) > 0
else 0,
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0,
"credit_in_account_currency": abs(flt(acc.bal_in_account_currency))
if flt(acc.bal_in_account_currency) < 0
else 0,
"credit": abs(flt(acc.bal_in_company_currency))
if flt(acc.bal_in_company_currency) < 0
else 0,
"is_period_closing_voucher_entry": 1,
},
item=acc,
)
self.update_default_dimensions(gl_entry, acc)
return gl_entry
def get_closing_entries(self, acc):
closing_entry = self.get_gl_dict(
{
"company": self.company,
"closing_date": self.posting_date,
"period_closing_voucher": self.name,
"account": acc.account,
"cost_center": acc.cost_center,
"finance_book": acc.finance_book,
"account_currency": acc.account_currency,
"debit_in_account_currency": flt(acc.debit_in_account_currency),
"debit": flt(acc.debit),
"credit_in_account_currency": flt(acc.credit_in_account_currency),
"credit": flt(acc.credit),
},
item=acc,
{"voucher_type": "Period Closing Voucher", "voucher_no": self.name, "is_cancelled": 0},
)
for dimension in self.accounting_dimensions:
closing_entry.update({dimension: acc.get(dimension)})
return closing_entry
def update_default_dimensions(self, gl_entry, acc):
if not self.accounting_dimensions:
self.accounting_dimensions = get_accounting_dimensions()
for dimension in self.accounting_dimensions:
gl_entry.update({dimension: acc.get(dimension)})
def get_balances_based_on_dimensions(
self, group_by_account=False, report_type=None, for_aggregation=False, get_opening_entries=False
):
"""Get balance for dimension-wise pl accounts"""
qb_dimension_fields = ["cost_center", "finance_book", "project"]
self.accounting_dimensions = get_accounting_dimensions()
for dimension in self.accounting_dimensions:
qb_dimension_fields.append(dimension)
if group_by_account:
qb_dimension_fields.append("account")
account_filters = {
"company": self.company,
"is_group": 0,
}
if report_type:
account_filters.update({"report_type": report_type})
accounts = frappe.get_all("Account", filters=account_filters, pluck="name")
gl_entry = frappe.qb.DocType("GL Entry")
query = frappe.qb.from_(gl_entry).select(gl_entry.account, gl_entry.account_currency)
if not for_aggregation:
query = query.select(
(Sum(gl_entry.debit_in_account_currency) - Sum(gl_entry.credit_in_account_currency)).as_(
"bal_in_account_currency"
),
(Sum(gl_entry.debit) - Sum(gl_entry.credit)).as_("bal_in_company_currency"),
)
else:
query = query.select(
(Sum(gl_entry.debit_in_account_currency)).as_("debit_in_account_currency"),
(Sum(gl_entry.credit_in_account_currency)).as_("credit_in_account_currency"),
(Sum(gl_entry.debit)).as_("debit"),
(Sum(gl_entry.credit)).as_("credit"),
)
for dimension in qb_dimension_fields:
query = query.select(gl_entry[dimension])
query = query.where(
(gl_entry.company == self.company)
& (gl_entry.is_cancelled == 0)
& (gl_entry.account.isin(accounts))
)
if get_opening_entries:
query = query.where(
( # noqa: UP034
(gl_entry.posting_date.between(self.get("year_start_date"), self.posting_date))
| (gl_entry.is_opening == "Yes")
)
)
else:
query = query.where(
gl_entry.posting_date.between(self.get("year_start_date"), self.posting_date)
& gl_entry.is_opening
== "No"
)
if for_aggregation:
query = query.where(gl_entry.voucher_type != "Period Closing Voucher")
for dimension in qb_dimension_fields:
query = query.groupby(gl_entry[dimension])
return query.run(as_dict=1)
def process_gl_and_closing_entries(gl_entries, closing_entries, voucher_name, company, closing_date):
from erpnext.accounts.doctype.account_closing_balance.account_closing_balance import (
make_closing_entries,
)
def process_gl_and_closing_entries(doc):
from erpnext.accounts.general_ledger import make_gl_entries
try:
gl_entries = doc.get_pcv_gl_entries()
if gl_entries:
make_gl_entries(gl_entries, merge_entries=False)
make_closing_entries(gl_entries + closing_entries, voucher_name, company, closing_date)
frappe.db.set_value("Period Closing Voucher", voucher_name, "gle_processing_status", "Completed")
closing_entries = doc.get_account_closing_balances()
make_closing_entries(closing_entries, doc.name, doc.company, doc.period_end_date)
frappe.db.set_value(doc.doctype, doc.name, "gle_processing_status", "Completed")
except Exception as e:
frappe.db.rollback()
frappe.log_error(e)
frappe.db.set_value("Period Closing Voucher", voucher_name, "gle_processing_status", "Failed")
frappe.db.set_value(doc.doctype, doc.name, "gle_processing_status", "Failed")
def process_cancellation(voucher_type, voucher_no):
@@ -395,3 +482,29 @@ def delete_closing_entries(voucher_no):
frappe.qb.from_(closing_balance).delete().where(
closing_balance.period_closing_voucher == voucher_no
).run()
@frappe.whitelist()
def get_period_start_end_date(fiscal_year, company):
fy_start_date, fy_end_date = frappe.db.get_value(
"Fiscal Year", fiscal_year, ["year_start_date", "year_end_date"]
)
prev_closed_period_end_date = get_previous_closed_period_in_current_year(fiscal_year, company)
period_start_date = (
add_days(prev_closed_period_end_date, 1) if prev_closed_period_end_date else fy_start_date
)
return period_start_date, fy_end_date
def get_previous_closed_period_in_current_year(fiscal_year, company):
prev_closed_period_end_date = frappe.db.get_value(
"Period Closing Voucher",
filters={
"company": company,
"fiscal_year": fiscal_year,
"docstatus": 1,
},
fieldname=["period_end_date"],
order_by="period_end_date desc",
)
return prev_closed_period_end_date

View File

@@ -317,16 +317,18 @@ class TestPeriodClosingVoucher(unittest.TestCase):
repost_doc.posting_date = today()
repost_doc.save()
def make_period_closing_voucher(self, posting_date=None, submit=True):
def make_period_closing_voucher(self, posting_date, submit=True):
surplus_account = create_account()
cost_center = create_cost_center("Test Cost Center 1")
fy = get_fiscal_year(posting_date, company="Test PCV Company")
pcv = frappe.get_doc(
{
"doctype": "Period Closing Voucher",
"transaction_date": posting_date or today(),
"posting_date": posting_date or today(),
"period_start_date": fy[1],
"period_end_date": fy[2],
"company": "Test PCV Company",
"fiscal_year": get_fiscal_year(today(), company="Test PCV Company")[0],
"fiscal_year": fy[0],
"cost_center": cost_center,
"closing_account_head": surplus_account,
"remarks": "test",

View File

@@ -65,7 +65,7 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
super.refresh();
if (doc.docstatus == 1 && !doc.is_return) {
this.frm.add_custom_button(__("Return"), this.make_sales_return, __("Create"));
this.frm.add_custom_button(__("Return"), this.make_sales_return.bind(this), __("Create"));
this.frm.page.set_inner_btn_group_as_primary(__("Create"));
}

View File

@@ -93,7 +93,7 @@ class TestPOSInvoice(unittest.TestCase):
inv.save()
self.assertEqual(inv.net_total, 4298.25)
self.assertEqual(inv.net_total, 4298.24)
self.assertEqual(inv.grand_total, 4900.00)
def test_tax_calculation_with_multiple_items(self):

View File

@@ -438,7 +438,9 @@ def split_invoices(invoices):
if not item.serial_no and not item.serial_and_batch_bundle:
continue
return_against_is_added = any(d for d in _invoices if d.pos_invoice == pos_invoice.return_against)
return_against_is_added = any(
d for d in _invoices if d and d[0].pos_invoice == pos_invoice.return_against
)
if return_against_is_added:
break

View File

@@ -343,7 +343,7 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
inv.load_from_db()
consolidated_invoice = frappe.get_doc("Sales Invoice", inv.consolidated_invoice)
self.assertEqual(consolidated_invoice.status, "Return")
self.assertEqual(consolidated_invoice.rounding_adjustment, -0.001)
self.assertEqual(consolidated_invoice.rounding_adjustment, -0.002)
finally:
frappe.set_user("Administrator")

View File

@@ -446,7 +446,20 @@ def get_pricing_rule_for_item(args, doc=None, for_validate=False):
if isinstance(pricing_rule, str):
pricing_rule = frappe.get_cached_doc("Pricing Rule", pricing_rule)
update_pricing_rule_uom(pricing_rule, args)
pricing_rule.apply_rule_on_other_items = get_pricing_rule_items(pricing_rule) or []
fetch_other_item = True if pricing_rule.apply_rule_on_other else False
pricing_rule.apply_rule_on_other_items = (
get_pricing_rule_items(pricing_rule, other_items=fetch_other_item) or []
)
if pricing_rule.coupon_code_based == 1:
if not args.coupon_code:
return item_details
coupon_code = frappe.db.get_value(
doctype="Coupon Code", filters={"pricing_rule": pricing_rule.name}, fieldname="name"
)
if args.coupon_code != coupon_code:
continue
if pricing_rule.get("suggestion"):
continue
@@ -473,9 +486,6 @@ def get_pricing_rule_for_item(args, doc=None, for_validate=False):
pricing_rule.apply_rule_on_other_items
)
if pricing_rule.coupon_code_based == 1 and args.coupon_code is None:
return item_details
if not pricing_rule.validate_applied_rule:
if pricing_rule.price_or_product_discount == "Price":
apply_price_discount_rule(pricing_rule, item_details, args)

View File

@@ -31,6 +31,13 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
},
};
});
this.frm.set_query("expense_account", "items", function () {
return {
query: "erpnext.controllers.queries.get_expense_account",
filters: { company: doc.company },
};
});
}
onload() {
@@ -335,7 +342,9 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
party_type: "Supplier",
account: this.frm.doc.credit_to,
price_list: this.frm.doc.buying_price_list,
fetch_payment_terms_template: cint(!this.frm.doc.ignore_default_payment_terms_template),
fetch_payment_terms_template: cint(
(this.frm.doc.is_return == 0) & !this.frm.doc.ignore_default_payment_terms_template
),
},
function () {
me.apply_pricing_rule();
@@ -506,13 +515,6 @@ cur_frm.fields_dict["select_print_heading"].get_query = function (doc, cdt, cdn)
};
};
cur_frm.set_query("expense_account", "items", function (doc) {
return {
query: "erpnext.controllers.queries.get_expense_account",
filters: { company: doc.company },
};
});
cur_frm.set_query("wip_composite_asset", "items", function () {
return {
filters: { is_composite_asset: 1, docstatus: 0 },

View File

@@ -1134,12 +1134,14 @@
"label": "Payment Terms"
},
{
"depends_on": "eval:(!doc.is_paid && !doc.is_return)",
"fieldname": "payment_terms_template",
"fieldtype": "Link",
"label": "Payment Terms Template",
"options": "Payment Terms Template"
},
{
"depends_on": "eval:(!doc.is_paid && !doc.is_return)",
"fieldname": "payment_schedule",
"fieldtype": "Table",
"label": "Payment Schedule",
@@ -1631,7 +1633,7 @@
"idx": 204,
"is_submittable": 1,
"links": [],
"modified": "2024-09-11 12:59:19.130593",
"modified": "2024-10-25 18:13:01.944477",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",

View File

@@ -863,6 +863,7 @@ class PurchaseInvoice(BuyingController):
self.make_tax_gl_entries(gl_entries)
self.make_internal_transfer_gl_entries(gl_entries)
self.make_gl_entries_for_tax_withholding(gl_entries)
gl_entries = make_regional_gl_entries(gl_entries, self)
@@ -896,32 +897,37 @@ class PurchaseInvoice(BuyingController):
)
if grand_total and not self.is_internal_transfer():
against_voucher = self.name
if self.is_return and self.return_against and not self.update_outstanding_for_self:
against_voucher = self.return_against
self.add_supplier_gl_entry(gl_entries, base_grand_total, grand_total)
# Did not use base_grand_total to book rounding loss gle
gl_entries.append(
self.get_gl_dict(
{
"account": self.credit_to,
"party_type": "Supplier",
"party": self.supplier,
"due_date": self.due_date,
"against": self.against_expense_account,
"credit": base_grand_total,
"credit_in_account_currency": base_grand_total
if self.party_account_currency == self.company_currency
else grand_total,
"against_voucher": against_voucher,
"against_voucher_type": self.doctype,
"project": self.project,
"cost_center": self.cost_center,
},
self.party_account_currency,
item=self,
)
)
def add_supplier_gl_entry(
self, gl_entries, base_grand_total, grand_total, against_account=None, remarks=None, skip_merge=False
):
against_voucher = self.name
if self.is_return and self.return_against and not self.update_outstanding_for_self:
against_voucher = self.return_against
# Did not use base_grand_total to book rounding loss gle
gl = {
"account": self.credit_to,
"party_type": "Supplier",
"party": self.supplier,
"due_date": self.due_date,
"against": against_account or self.against_expense_account,
"credit": base_grand_total,
"credit_in_account_currency": base_grand_total
if self.party_account_currency == self.company_currency
else grand_total,
"against_voucher": against_voucher,
"against_voucher_type": self.doctype,
"project": self.project,
"cost_center": self.cost_center,
"_skip_merge": skip_merge,
}
if remarks:
gl["remarks"] = remarks
gl_entries.append(self.get_gl_dict(gl, self.party_account_currency, item=self))
def make_item_gl_entries(self, gl_entries):
# item gl entries
@@ -1413,6 +1419,31 @@ class PurchaseInvoice(BuyingController):
)
)
def make_gl_entries_for_tax_withholding(self, gl_entries):
"""
Tax withholding amount is not part of supplier invoice.
Separate supplier GL Entry for correct reporting.
"""
if not self.apply_tds:
return
for row in self.get("taxes"):
if not row.is_tax_withholding_account or not row.tax_amount:
continue
base_tds_amount = row.base_tax_amount_after_discount_amount
tds_amount = row.tax_amount_after_discount_amount
self.add_supplier_gl_entry(gl_entries, base_tds_amount, tds_amount)
self.add_supplier_gl_entry(
gl_entries,
-base_tds_amount,
-tds_amount,
against_account=row.account_head,
remarks=_("TDS Deducted"),
skip_merge=True,
)
def make_payment_gl_entries(self, gl_entries):
# Make Cash GL Entries
if cint(self.is_paid) and self.cash_bank_account and self.paid_amount:
@@ -1506,10 +1537,29 @@ class PurchaseInvoice(BuyingController):
# eg: rounding_adjustment = 0.01 and exchange rate = 0.05 and precision of base_rounding_adjustment is 2
# then base_rounding_adjustment becomes zero and error is thrown in GL Entry
if not self.is_internal_transfer() and self.rounding_adjustment and self.base_rounding_adjustment:
round_off_account, round_off_cost_center = get_round_off_account_and_cost_center(
(
round_off_account,
round_off_cost_center,
round_off_for_opening,
) = get_round_off_account_and_cost_center(
self.company, "Purchase Invoice", self.name, self.use_company_roundoff_cost_center
)
if self.is_opening == "Yes" and self.rounding_adjustment:
if not round_off_for_opening:
frappe.throw(
_(
"Opening Invoice has rounding adjustment of {0}.<br><br> '{1}' account is required to post these values. Please set it in Company: {2}.<br><br> Or, '{3}' can be enabled to not post any rounding adjustment."
).format(
frappe.bold(self.rounding_adjustment),
frappe.bold("Round Off for Opening"),
get_link_to_form("Company", self.company),
frappe.bold("Disable Rounded Total"),
)
)
else:
round_off_account = round_off_for_opening
gl_entries.append(
self.get_gl_dict(
{
@@ -1593,7 +1643,11 @@ class PurchaseInvoice(BuyingController):
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)
# frappe.db.set_value("Project", proj, "total_purchase_cost", current_purchase_cost + value)
project_doc = frappe.get_doc("Project", proj)
project_doc.total_purchase_cost = current_purchase_cost + value
project_doc.calculate_gross_margin()
project_doc.db_update()
def validate_supplier_invoice(self):
if self.bill_date:

View File

@@ -1544,6 +1544,61 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
payment_entry.load_from_db()
self.assertEqual(payment_entry.taxes[0].allocated_amount, 0)
def test_purchase_gl_with_tax_withholding_tax(self):
company = "_Test Company"
tds_account_args = {
"doctype": "Account",
"account_name": "TDS Payable",
"account_type": "Tax",
"parent_account": frappe.db.get_value(
"Account", {"account_name": "Duties and Taxes", "company": company}
),
"company": company,
}
tds_account = create_account(**tds_account_args)
tax_withholding_category = "Test TDS - 194 - Dividends - Individual"
# Update tax withholding category with current fiscal year and rate details
create_tax_witholding_category(tax_withholding_category, company, tds_account)
# create a new supplier to test
supplier = create_supplier(
supplier_name="_Test TDS Advance Supplier",
tax_withholding_category=tax_withholding_category,
)
pi = make_purchase_invoice(
supplier=supplier.name,
rate=3000,
qty=1,
item="_Test Non Stock Item",
do_not_submit=1,
)
pi.apply_tds = 1
pi.tax_withholding_category = tax_withholding_category
pi.save()
pi.submit()
self.assertEqual(pi.taxes[0].tax_amount, 300)
self.assertEqual(pi.taxes[0].account_head, tds_account)
gl_entries = frappe.get_all(
"GL Entry",
filters={"voucher_no": pi.name, "voucher_type": "Purchase Invoice", "account": "Creditors - _TC"},
fields=["account", "against", "debit", "credit"],
)
for gle in gl_entries:
if gle.debit:
# GL Entry with TDS Amount
self.assertEqual(gle.against, tds_account)
self.assertEqual(gle.debit, 300)
else:
# GL Entry with Purchase Invoice Amount
self.assertEqual(gle.credit, 3000)
def test_provisional_accounting_entry(self):
setup_provisional_accounting()
@@ -2310,6 +2365,65 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
item.reload()
self.assertEqual(item.last_purchase_rate, 0)
def test_opening_invoice_rounding_adjustment_validation(self):
pi = make_purchase_invoice(do_not_save=1)
pi.items[0].rate = 99.98
pi.items[0].qty = 1
pi.items[0].expense_account = "Temporary Opening - _TC"
pi.is_opening = "Yes"
pi.save()
self.assertRaises(frappe.ValidationError, pi.submit)
def _create_opening_roundoff_account(self, company_name):
liability_root = frappe.db.get_all(
"Account",
filters={"company": company_name, "root_type": "Liability", "disabled": 0},
order_by="lft",
limit=1,
)[0]
# setup round off account
if acc := frappe.db.exists(
"Account",
{
"account_name": "Round Off for Opening",
"account_type": "Round Off for Opening",
"company": company_name,
},
):
frappe.db.set_value("Company", company_name, "round_off_for_opening", acc)
else:
acc = frappe.new_doc("Account")
acc.company = company_name
acc.parent_account = liability_root.name
acc.account_name = "Round Off for Opening"
acc.account_type = "Round Off for Opening"
acc.save()
frappe.db.set_value("Company", company_name, "round_off_for_opening", acc.name)
def test_ledger_entries_of_opening_invoice_with_rounding_adjustment(self):
pi = make_purchase_invoice(do_not_save=1)
pi.items[0].rate = 99.98
pi.items[0].qty = 1
pi.items[0].expense_account = "Temporary Opening - _TC"
pi.is_opening = "Yes"
pi.save()
self._create_opening_roundoff_account(pi.company)
pi.submit()
actual = frappe.db.get_all(
"GL Entry",
filters={"voucher_no": pi.name, "is_opening": "Yes", "is_cancelled": False},
fields=["account", "debit", "credit", "is_opening"],
order_by="account,debit",
)
expected = [
{"account": "Creditors - _TC", "debit": 0.0, "credit": 100.0, "is_opening": "Yes"},
{"account": "Round Off for Opening - _TC", "debit": 0.02, "credit": 0.0, "is_opening": "Yes"},
{"account": "Temporary Opening - _TC", "debit": 99.98, "credit": 0.0, "is_opening": "Yes"},
]
self.assertEqual(len(actual), 3)
self.assertEqual(expected, actual)
def set_advance_flag(company, flag, default_account):
frappe.db.set_value(

View File

@@ -505,7 +505,8 @@
"fieldtype": "Link",
"label": "Project",
"options": "Project",
"print_hide": 1
"print_hide": 1,
"search_index": 1
},
{
"allow_on_submit": 1,
@@ -974,7 +975,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-07-19 12:12:42.449298",
"modified": "2024-10-28 15:06:19.246141",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@@ -46,8 +46,8 @@ class RepostAccountingLedger(Document):
frappe.db.get_all(
"Period Closing Voucher",
filters={"company": self.company},
order_by="posting_date desc",
pluck="posting_date",
order_by="period_end_date desc",
pluck="period_end_date",
limit=1,
)
or None

View File

@@ -129,13 +129,15 @@ class TestRepostAccountingLedger(AccountsTestMixin, FrappeTestCase):
cost_center=self.cost_center,
rate=100,
)
fy = get_fiscal_year(today(), company=self.company)
pcv = frappe.get_doc(
{
"doctype": "Period Closing Voucher",
"transaction_date": today(),
"posting_date": today(),
"period_start_date": fy[1],
"period_end_date": today(),
"company": self.company,
"fiscal_year": get_fiscal_year(today(), company=self.company)[0],
"fiscal_year": fy[0],
"cost_center": self.cost_center,
"closing_account_head": self.retained_earnings,
"remarks": "test",

View File

@@ -339,6 +339,9 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends (
account: this.frm.doc.debit_to,
price_list: this.frm.doc.selling_price_list,
pos_profile: pos_profile,
fetch_payment_terms_template: cint(
(this.frm.doc.is_return == 0) & !this.frm.doc.ignore_default_payment_terms_template
),
},
function () {
me.apply_pricing_rule();

View File

@@ -297,8 +297,11 @@ class SalesInvoice(SellingController):
self.update_current_stock()
self.validate_delivery_note()
is_deferred_invoice = any(d.get("enable_deferred_revenue") for d in self.get("items"))
# validate service stop date to lie in between start and end date
validate_service_stop_date(self)
if is_deferred_invoice:
validate_service_stop_date(self)
if not self.is_opening:
self.is_opening = "No"
@@ -1630,10 +1633,29 @@ class SalesInvoice(SellingController):
and self.base_rounding_adjustment
and not self.is_internal_transfer()
):
round_off_account, round_off_cost_center = get_round_off_account_and_cost_center(
(
round_off_account,
round_off_cost_center,
round_off_for_opening,
) = get_round_off_account_and_cost_center(
self.company, "Sales Invoice", self.name, self.use_company_roundoff_cost_center
)
if self.is_opening == "Yes" and self.rounding_adjustment:
if not round_off_for_opening:
frappe.throw(
_(
"Opening Invoice has rounding adjustment of {0}.<br><br> '{1}' account is required to post these values. Please set it in Company: {2}.<br><br> Or, '{3}' can be enabled to not post any rounding adjustment."
).format(
frappe.bold(self.rounding_adjustment),
frappe.bold("Round Off for Opening"),
get_link_to_form("Company", self.company),
frappe.bold("Disable Rounded Total"),
)
)
else:
round_off_account = round_off_for_opening
gl_entries.append(
self.get_gl_dict(
{
@@ -1731,9 +1753,11 @@ class SalesInvoice(SellingController):
)
def update_project(self):
if self.project:
project = frappe.get_doc("Project", self.project)
unique_projects = list(set([d.project for d in self.get("items") if d.project]))
for p in unique_projects:
project = frappe.get_doc("Project", p)
project.update_billed_amount()
project.calculate_gross_margin()
project.db_update()
def verify_payment_amount_is_positive(self):

View File

@@ -314,7 +314,8 @@ class TestSalesInvoice(FrappeTestCase):
si.insert()
# with inclusive tax
self.assertEqual(si.items[0].net_amount, 3947.368421052631)
self.assertEqual(si.items[0].net_amount, 3947.37)
self.assertEqual(si.net_total, si.base_net_total)
self.assertEqual(si.net_total, 3947.37)
self.assertEqual(si.grand_total, 5000)
@@ -658,7 +659,7 @@ class TestSalesInvoice(FrappeTestCase):
62.5,
625.0,
50,
499.97600115194473,
499.98,
],
"_Test Item Home Desktop 200": [
190.66,
@@ -669,7 +670,7 @@ class TestSalesInvoice(FrappeTestCase):
190.66,
953.3,
150,
749.9968530500239,
750,
],
}
@@ -682,20 +683,21 @@ class TestSalesInvoice(FrappeTestCase):
self.assertEqual(d.get(k), expected_values[d.item_code][i])
# check net total
self.assertEqual(si.net_total, 1249.97)
self.assertEqual(si.base_net_total, si.net_total)
self.assertEqual(si.net_total, 1249.98)
self.assertEqual(si.total, 1578.3)
# check tax calculation
expected_values = {
"keys": ["tax_amount", "total"],
"_Test Account Excise Duty - _TC": [140, 1389.97],
"_Test Account Education Cess - _TC": [2.8, 1392.77],
"_Test Account S&H Education Cess - _TC": [1.4, 1394.17],
"_Test Account CST - _TC": [27.88, 1422.05],
"_Test Account VAT - _TC": [156.25, 1578.30],
"_Test Account Customs Duty - _TC": [125, 1703.30],
"_Test Account Shipping Charges - _TC": [100, 1803.30],
"_Test Account Discount - _TC": [-180.33, 1622.97],
"_Test Account Excise Duty - _TC": [140, 1389.98],
"_Test Account Education Cess - _TC": [2.8, 1392.78],
"_Test Account S&H Education Cess - _TC": [1.4, 1394.18],
"_Test Account CST - _TC": [27.88, 1422.06],
"_Test Account VAT - _TC": [156.25, 1578.31],
"_Test Account Customs Duty - _TC": [125, 1703.31],
"_Test Account Shipping Charges - _TC": [100, 1803.31],
"_Test Account Discount - _TC": [-180.33, 1622.98],
}
for d in si.get("taxes"):
@@ -731,7 +733,7 @@ class TestSalesInvoice(FrappeTestCase):
"base_rate": 2500,
"base_amount": 25000,
"net_rate": 40,
"net_amount": 399.9808009215558,
"net_amount": 399.98,
"base_net_rate": 2000,
"base_net_amount": 19999,
},
@@ -745,7 +747,7 @@ class TestSalesInvoice(FrappeTestCase):
"base_rate": 7500,
"base_amount": 37500,
"net_rate": 118.01,
"net_amount": 590.0531205155963,
"net_amount": 590.05,
"base_net_rate": 5900.5,
"base_net_amount": 29502.5,
},
@@ -783,8 +785,13 @@ class TestSalesInvoice(FrappeTestCase):
self.assertEqual(si.base_grand_total, 60795)
self.assertEqual(si.grand_total, 1215.90)
self.assertEqual(si.rounding_adjustment, 0.01)
self.assertEqual(si.base_rounding_adjustment, 0.50)
# no rounding adjustment as the Smallest Currency Fraction Value of USD is 0.01
if frappe.db.get_value("Currency", "USD", "smallest_currency_fraction_value") < 0.01:
self.assertEqual(si.rounding_adjustment, 0.10)
self.assertEqual(si.base_rounding_adjustment, 5.0)
else:
self.assertEqual(si.rounding_adjustment, 0.0)
self.assertEqual(si.base_rounding_adjustment, 0.0)
def test_outstanding(self):
w = self.make()
@@ -1995,7 +2002,7 @@ class TestSalesInvoice(FrappeTestCase):
# Check if SO is unlinked/replaced by SI in PE & if SO advance paid is 0
self.assertEqual(pe.references[0].reference_name, si.name)
self.assertEqual(sales_order.advance_paid, 0.0)
self.assertEqual(sales_order.advance_paid, 300.0)
# check outstanding after advance allocation
self.assertEqual(
@@ -2172,7 +2179,7 @@ class TestSalesInvoice(FrappeTestCase):
def test_rounding_adjustment_2(self):
si = create_sales_invoice(rate=400, do_not_save=True)
for rate in [400, 600, 100]:
for rate in [400.25, 600.30, 100.65]:
si.append(
"items",
{
@@ -2198,18 +2205,19 @@ class TestSalesInvoice(FrappeTestCase):
)
si.save()
si.submit()
self.assertEqual(si.net_total, 1271.19)
self.assertEqual(si.grand_total, 1500)
self.assertEqual(si.total_taxes_and_charges, 228.82)
self.assertEqual(si.rounding_adjustment, -0.01)
self.assertEqual(si.net_total, si.base_net_total)
self.assertEqual(si.net_total, 1272.20)
self.assertEqual(si.grand_total, 1501.20)
self.assertEqual(si.total_taxes_and_charges, 229)
self.assertEqual(si.rounding_adjustment, -0.20)
round_off_account = frappe.get_cached_value("Company", "_Test Company", "round_off_account")
expected_values = {
"_Test Account Service Tax - _TC": [0.0, 114.41],
"_Test Account VAT - _TC": [0.0, 114.41],
si.debit_to: [1500, 0.0],
round_off_account: [0.01, 0.01],
"Sales - _TC": [0.0, 1271.18],
"_Test Account Service Tax - _TC": [0.0, 114.50],
"_Test Account VAT - _TC": [0.0, 114.50],
si.debit_to: [1501, 0.0],
round_off_account: [0.20, 0.0],
"Sales - _TC": [0.0, 1272.20],
}
gl_entries = frappe.db.sql(
@@ -2267,7 +2275,8 @@ class TestSalesInvoice(FrappeTestCase):
si.save()
si.submit()
self.assertEqual(si.net_total, 4007.16)
self.assertEqual(si.net_total, si.base_net_total)
self.assertEqual(si.net_total, 4007.15)
self.assertEqual(si.grand_total, 4488.02)
self.assertEqual(si.total_taxes_and_charges, 480.86)
self.assertEqual(si.rounding_adjustment, -0.02)
@@ -2280,7 +2289,7 @@ class TestSalesInvoice(FrappeTestCase):
["_Test Account Service Tax - _TC", 0.0, 240.43],
["_Test Account VAT - _TC", 0.0, 240.43],
["Sales - _TC", 0.0, 4007.15],
[round_off_account, 0.02, 0.01],
[round_off_account, 0.01, 0.0],
]
)
@@ -4005,6 +4014,127 @@ class TestSalesInvoice(FrappeTestCase):
si.submit()
self.assertEqual(si.remarks, f"Against Customer Order Test PO dated {format_date(nowdate())}")
def test_gl_voucher_subtype(self):
si = create_sales_invoice()
gl_entries = frappe.get_all(
"GL Entry",
filters={"voucher_type": "Sales Invoice", "voucher_no": si.name},
pluck="voucher_subtype",
)
self.assertTrue(all([x == "Sales Invoice" for x in gl_entries]))
si = create_sales_invoice(is_return=1, qty=-1)
gl_entries = frappe.get_all(
"GL Entry",
filters={"voucher_type": "Sales Invoice", "voucher_no": si.name},
pluck="voucher_subtype",
)
self.assertTrue(all([x == "Credit Note" for x in gl_entries]))
def test_validation_on_opening_invoice_with_rounding(self):
si = create_sales_invoice(qty=1, rate=99.98, do_not_submit=True)
si.is_opening = "Yes"
si.items[0].income_account = "Temporary Opening - _TC"
si.save()
self.assertRaises(frappe.ValidationError, si.submit)
def _create_opening_roundoff_account(self, company_name):
liability_root = frappe.db.get_all(
"Account",
filters={"company": company_name, "root_type": "Liability", "disabled": 0},
order_by="lft",
limit=1,
)[0]
# setup round off account
if acc := frappe.db.exists(
"Account",
{
"account_name": "Round Off for Opening",
"account_type": "Round Off for Opening",
"company": company_name,
},
):
frappe.db.set_value("Company", company_name, "round_off_for_opening", acc)
else:
acc = frappe.new_doc("Account")
acc.company = company_name
acc.parent_account = liability_root.name
acc.account_name = "Round Off for Opening"
acc.account_type = "Round Off for Opening"
acc.save()
frappe.db.set_value("Company", company_name, "round_off_for_opening", acc.name)
def test_opening_invoice_with_rounding_adjustment(self):
si = create_sales_invoice(qty=1, rate=99.98, do_not_submit=True)
si.is_opening = "Yes"
si.items[0].income_account = "Temporary Opening - _TC"
si.save()
self._create_opening_roundoff_account(si.company)
si.reload()
si.submit()
res = frappe.db.get_all(
"GL Entry",
filters={"voucher_no": si.name, "is_opening": "Yes"},
fields=["account", "debit", "credit", "is_opening"],
)
self.assertEqual(len(res), 3)
def _create_opening_invoice_with_inclusive_tax(self):
si = create_sales_invoice(qty=1, rate=90, do_not_submit=True)
si.is_opening = "Yes"
si.items[0].income_account = "Temporary Opening - _TC"
item_template = si.items[0].as_dict()
item_template.name = None
item_template.rate = 55
si.append("items", item_template)
si.append(
"taxes",
{
"charge_type": "On Net Total",
"account_head": "_Test Account Service Tax - _TC",
"cost_center": "_Test Cost Center - _TC",
"description": "Testing...",
"rate": 5,
"included_in_print_rate": True,
},
)
# there will be 0.01 precision loss between Dr and Cr
# caused by 'included_in_print_tax' option
si.save()
return si
def test_rounding_validation_for_opening_with_inclusive_tax(self):
si = self._create_opening_invoice_with_inclusive_tax()
# 'Round Off for Opening' not set in Company master
# Ledger level validation must be thrown
self.assertRaises(frappe.ValidationError, si.submit)
def test_ledger_entries_on_opening_invoice_with_rounding_loss_by_inclusive_tax(self):
si = self._create_opening_invoice_with_inclusive_tax()
# 'Round Off for Opening' is set in Company master
self._create_opening_roundoff_account(si.company)
si.submit()
actual = frappe.db.get_all(
"GL Entry",
filters={"voucher_no": si.name, "is_opening": "Yes", "is_cancelled": False},
fields=["account", "debit", "credit", "is_opening"],
order_by="account,debit",
)
expected = [
{"account": "_Test Account Service Tax - _TC", "debit": 0.0, "credit": 6.9, "is_opening": "Yes"},
{"account": "Debtors - _TC", "debit": 145.0, "credit": 0.0, "is_opening": "Yes"},
{"account": "Round Off for Opening - _TC", "debit": 0.0, "credit": 0.01, "is_opening": "Yes"},
{"account": "Temporary Opening - _TC", "debit": 0.0, "credit": 138.09, "is_opening": "Yes"},
]
self.assertEqual(len(actual), 4)
self.assertEqual(expected, actual)
def set_advance_flag(company, flag, default_account):
frappe.db.set_value(

View File

@@ -812,7 +812,8 @@
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project"
"options": "Project",
"search_index": 1
},
{
"depends_on": "eval:parent.update_stock == 1",
@@ -927,7 +928,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-05-23 16:36:18.970862",
"modified": "2024-10-28 15:06:40.980995",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",

View File

@@ -514,7 +514,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
payment_entry_filters.pop("apply_tax_withholding_amount", None)
payment_entry_filters.pop("tax_withholding_category", None)
supp_credit_amt = frappe.db.get_value("Purchase Invoice", invoice_filters, field) or 0.0
supp_inv_credit_amt = frappe.db.get_value("Purchase Invoice", invoice_filters, field) or 0.0
supp_jv_credit_amt = (
frappe.db.get_value(
@@ -538,7 +538,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
group_by="payment_type",
)
supp_credit_amt += supp_jv_credit_amt
supp_credit_amt = supp_jv_credit_amt
supp_credit_amt += inv.tax_withholding_net_total
for type in payment_entry_amounts:
@@ -556,18 +556,18 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
tax_withholding_net_total = inv.tax_withholding_net_total
if (threshold and tax_withholding_net_total >= threshold) or (
cumulative_threshold and supp_credit_amt >= cumulative_threshold
cumulative_threshold and (supp_credit_amt + supp_inv_credit_amt) >= cumulative_threshold
):
# Get net total again as TDS is calculated on net total
# Grand is used to just check for threshold breach
net_total = (
frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(tax_withholding_net_total)") or 0.0
)
supp_credit_amt += net_total
if (cumulative_threshold and supp_credit_amt >= cumulative_threshold) and cint(
tax_details.tax_on_excess_amount
):
# Get net total again as TDS is calculated on net total
# Grand is used to just check for threshold breach
net_total = (
frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(tax_withholding_net_total)")
or 0.0
)
net_total += inv.tax_withholding_net_total
supp_credit_amt = net_total - cumulative_threshold
if ldc and is_valid_certificate(ldc, inv.get("posting_date") or inv.get("transaction_date"), 0):

View File

@@ -74,11 +74,17 @@ class TestTaxWithholdingCategory(FrappeTestCase):
self.assertEqual(pi.grand_total, 18000)
# check gl entry for the purchase invoice
gl_entries = frappe.db.get_all("GL Entry", filters={"voucher_no": pi.name}, fields=["*"])
gl_entries = frappe.db.get_all(
"GL Entry",
filters={"voucher_no": pi.name},
fields=["account", "sum(debit) as debit", "sum(credit) as credit"],
group_by="account",
)
self.assertEqual(len(gl_entries), 3)
for d in gl_entries:
if d.account == pi.credit_to:
self.assertEqual(d.credit, 18000)
self.assertEqual(d.credit, 20000)
self.assertEqual(d.debit, 2000)
elif d.account == pi.items[0].get("expense_account"):
self.assertEqual(d.debit, 20000)
elif d.account == pi.taxes[0].get("account_head"):
@@ -121,6 +127,46 @@ class TestTaxWithholdingCategory(FrappeTestCase):
for d in reversed(invoices):
d.cancel()
def test_cumulative_threshold_with_party_ledger_amount_on_net_total(self):
invoices = []
frappe.db.set_value(
"Supplier", "Test TDS Supplier3", "tax_withholding_category", "Advance TDS Category"
)
# Invoice with tax and without exceeding single and cumulative thresholds
for _ in range(2):
pi = create_purchase_invoice(supplier="Test TDS Supplier3", rate=1000, do_not_save=True)
pi.apply_tds = 1
pi.append(
"taxes",
{
"category": "Total",
"charge_type": "Actual",
"account_head": "_Test Account VAT - _TC",
"cost_center": "Main - _TC",
"tax_amount": 500,
"description": "Test",
"add_deduct_tax": "Add",
},
)
pi.save()
pi.submit()
invoices.append(pi)
# Third Invoice exceeds single threshold and not exceeding cumulative threshold
pi1 = create_purchase_invoice(supplier="Test TDS Supplier3", rate=6000)
pi1.apply_tds = 1
pi1.save()
pi1.submit()
invoices.append(pi1)
# Cumulative threshold is 10,000
# Threshold calculation should be only on the third invoice
self.assertEqual(pi1.taxes[0].tax_amount, 800)
for d in reversed(invoices):
d.cancel()
def test_cumulative_threshold_tcs(self):
frappe.db.set_value(
"Customer", "Test TCS Customer", "tax_withholding_category", "Cumulative Threshold TCS"

View File

@@ -362,10 +362,14 @@ class TestUnreconcilePayment(AccountsTestMixin, FrappeTestCase):
# Assert 'Advance Paid'
so.reload()
pe.reload()
self.assertEqual(so.advance_paid, 0)
self.assertEqual(so.advance_paid, 100)
self.assertEqual(len(pe.references), 0)
self.assertEqual(pe.unallocated_amount, 100)
pe.cancel()
so.reload()
self.assertEqual(so.advance_paid, 100)
def test_06_unreconcile_advance_from_payment_entry(self):
self.enable_advance_as_liability()
so1 = self.create_sales_order()
@@ -411,7 +415,7 @@ class TestUnreconcilePayment(AccountsTestMixin, FrappeTestCase):
so2.reload()
pe.reload()
self.assertEqual(so1.advance_paid, 150)
self.assertEqual(so2.advance_paid, 0)
self.assertEqual(so2.advance_paid, 110)
self.assertEqual(len(pe.references), 1)
self.assertEqual(pe.unallocated_amount, 110)
@@ -459,6 +463,6 @@ class TestUnreconcilePayment(AccountsTestMixin, FrappeTestCase):
# Assert 'Advance Paid'
so.reload()
self.assertEqual(so.advance_paid, 0)
self.assertEqual(so.advance_paid, 1000)
self.disable_advance_as_liability()

View File

@@ -7,7 +7,7 @@ import copy
import frappe
from frappe import _
from frappe.model.meta import get_field_precision
from frappe.utils import cint, flt, formatdate, getdate, now
from frappe.utils import cint, flt, formatdate, get_link_to_form, getdate, now
import erpnext
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
@@ -37,13 +37,14 @@ def make_gl_entries(
validate_disabled_accounts(gl_map)
gl_map = process_gl_map(gl_map, merge_entries)
if gl_map and len(gl_map) > 1:
create_payment_ledger_entry(
gl_map,
cancel=0,
adv_adj=adv_adj,
update_outstanding=update_outstanding,
from_repost=from_repost,
)
if gl_map[0].voucher_type != "Period Closing Voucher":
create_payment_ledger_entry(
gl_map,
cancel=0,
adv_adj=adv_adj,
update_outstanding=update_outstanding,
from_repost=from_repost,
)
save_entries(gl_map, adv_adj, update_outstanding, from_repost)
# Post GL Map proccess there may no be any GL Entries
elif gl_map:
@@ -116,17 +117,16 @@ def get_accounting_dimensions_for_offsetting_entry(gl_map, company):
def validate_disabled_accounts(gl_map):
accounts = [d.account for d in gl_map if d.account]
Account = frappe.qb.DocType("Account")
disabled_accounts = frappe.get_all(
"Account",
filters={"disabled": 1, "is_group": 0, "company": gl_map[0].company},
fields=["name"],
)
disabled_accounts = (
frappe.qb.from_(Account)
.where(Account.name.isin(accounts) & Account.disabled == 1)
.select(Account.name, Account.disabled)
).run(as_dict=True)
if disabled_accounts:
used_disabled_accounts = set(accounts).intersection(set([d.name for d in disabled_accounts]))
if used_disabled_accounts:
account_list = "<br>"
account_list += ", ".join([frappe.bold(d.name) for d in disabled_accounts])
account_list += ", ".join([frappe.bold(d) for d in used_disabled_accounts])
frappe.throw(
_("Cannot create accounting entries against disabled accounts: {0}").format(account_list),
title=_("Disabled Account Selected"),
@@ -234,6 +234,10 @@ def merge_similar_entries(gl_map, precision=None):
merge_properties = get_merge_properties(accounting_dimensions)
for entry in gl_map:
if entry._skip_merge:
merged_gl_map.append(entry)
continue
entry.merge_key = get_merge_key(entry, merge_properties)
# if there is already an entry in this account then just add it
# to that entry
@@ -492,16 +496,36 @@ def raise_debit_credit_not_equal_error(debit_credit_diff, voucher_type, voucher_
)
def has_opening_entries(gl_map: list) -> bool:
for x in gl_map:
if x.is_opening == "Yes":
return True
return False
def make_round_off_gle(gl_map, debit_credit_diff, precision):
round_off_account, round_off_cost_center = get_round_off_account_and_cost_center(
round_off_account, round_off_cost_center, round_off_for_opening = get_round_off_account_and_cost_center(
gl_map[0].company, gl_map[0].voucher_type, gl_map[0].voucher_no
)
round_off_gle = frappe._dict()
round_off_account_exists = False
has_opening_entry = has_opening_entries(gl_map)
if has_opening_entry:
if not round_off_for_opening:
frappe.throw(
_("Please set '{0}' in Company: {1}").format(
frappe.bold("Round Off for Opening"), get_link_to_form("Company", gl_map[0].company)
)
)
account = round_off_for_opening
else:
account = round_off_account
if gl_map[0].voucher_type != "Period Closing Voucher":
for d in gl_map:
if d.account == round_off_account:
if d.account == account:
round_off_gle = d
if d.debit:
debit_credit_diff -= flt(d.debit) - flt(d.credit)
@@ -519,7 +543,7 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
round_off_gle.update(
{
"account": round_off_account,
"account": account,
"debit_in_account_currency": abs(debit_credit_diff) if debit_credit_diff < 0 else 0,
"credit_in_account_currency": debit_credit_diff if debit_credit_diff > 0 else 0,
"debit": abs(debit_credit_diff) if debit_credit_diff < 0 else 0,
@@ -533,6 +557,9 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
}
)
if has_opening_entry:
round_off_gle.update({"is_opening": "Yes"})
update_accounting_dimensions(round_off_gle)
if not round_off_account_exists:
gl_map.append(round_off_gle)
@@ -557,9 +584,9 @@ def update_accounting_dimensions(round_off_gle):
def get_round_off_account_and_cost_center(company, voucher_type, voucher_no, use_company_default=False):
round_off_account, round_off_cost_center = frappe.get_cached_value(
"Company", company, ["round_off_account", "round_off_cost_center"]
) or [None, None]
round_off_account, round_off_cost_center, round_off_for_opening = frappe.get_cached_value(
"Company", company, ["round_off_account", "round_off_cost_center", "round_off_for_opening"]
) or [None, None, None]
# Use expense account as fallback
if not round_off_account:
@@ -574,12 +601,20 @@ def get_round_off_account_and_cost_center(company, voucher_type, voucher_no, use
round_off_cost_center = parent_cost_center
if not round_off_account:
frappe.throw(_("Please mention Round Off Account in Company"))
frappe.throw(
_("Please mention '{0}' in Company: {1}").format(
frappe.bold("Round Off Account"), get_link_to_form("Company", company)
)
)
if not round_off_cost_center:
frappe.throw(_("Please mention Round Off Cost Center in Company"))
frappe.throw(
_("Please mention '{0}' in Company: {1}").format(
frappe.bold("Round Off Cost Center"), get_link_to_form("Company", company)
)
)
return round_off_account, round_off_cost_center
return round_off_account, round_off_cost_center, round_off_for_opening
def make_reverse_gl_entries(
@@ -708,7 +743,7 @@ def validate_against_pcv(is_opening, posting_date, company):
)
last_pcv_date = frappe.db.get_value(
"Period Closing Voucher", {"docstatus": 1, "company": company}, "max(posting_date)"
"Period Closing Voucher", {"docstatus": 1, "company": company}, "max(period_end_date)"
)
if last_pcv_date and getdate(posting_date) <= getdate(last_pcv_date):

View File

@@ -385,6 +385,7 @@ class ReceivablePayableReport:
self.delivery_notes = frappe._dict()
# delivery note link inside sales invoice
# nosemgrep
si_against_dn = frappe.db.sql(
"""
select parent, delivery_note
@@ -400,6 +401,7 @@ class ReceivablePayableReport:
if d.delivery_note:
self.delivery_notes.setdefault(d.parent, set()).add(d.delivery_note)
# nosemgrep
dn_against_si = frappe.db.sql(
"""
select distinct parent, against_sales_invoice
@@ -417,13 +419,16 @@ class ReceivablePayableReport:
def get_invoice_details(self):
self.invoice_details = frappe._dict()
if self.account_type == "Receivable":
# nosemgrep
si_list = frappe.db.sql(
"""
select name, due_date, po_no
from `tabSales Invoice`
where posting_date <= %s
and company = %s
and docstatus = 1
""",
self.filters.report_date,
(self.filters.report_date, self.filters.company),
as_dict=1,
)
for d in si_list:
@@ -431,6 +436,7 @@ class ReceivablePayableReport:
# Get Sales Team
if self.filters.show_sales_person:
# nosemgrep
sales_team = frappe.db.sql(
"""
select parent, sales_person
@@ -445,25 +451,33 @@ class ReceivablePayableReport:
)
if self.account_type == "Payable":
# nosemgrep
for pi in frappe.db.sql(
"""
select name, due_date, bill_no, bill_date
from `tabPurchase Invoice`
where posting_date <= %s
where
posting_date <= %s
and company = %s
and docstatus = 1
""",
self.filters.report_date,
(self.filters.report_date, self.filters.company),
as_dict=1,
):
self.invoice_details.setdefault(pi.name, pi)
# Invoices booked via Journal Entries
# nosemgrep
journal_entries = frappe.db.sql(
"""
select name, due_date, bill_no, bill_date
from `tabJournal Entry`
where posting_date <= %s
where
posting_date <= %s
and company = %s
and docstatus = 1
""",
self.filters.report_date,
(self.filters.report_date, self.filters.company),
as_dict=1,
)
@@ -472,6 +486,8 @@ class ReceivablePayableReport:
self.invoice_details.setdefault(je.name, je)
def set_party_details(self, row):
if not row.party:
return
# customer / supplier name
party_details = self.get_party_details(row.party) or {}
row.update(party_details)
@@ -496,6 +512,7 @@ class ReceivablePayableReport:
def get_payment_terms(self, row):
# build payment_terms for row
# nosemgrep
payment_terms_details = frappe.db.sql(
f"""
select
@@ -505,7 +522,8 @@ class ReceivablePayableReport:
from `tab{row.voucher_type}` si, `tabPayment Schedule` ps
where
si.name = ps.parent and
si.name = %s
si.name = %s and
si.is_return = 0
order by ps.paid_amount desc, due_date
""",
row.voucher_no,
@@ -708,6 +726,7 @@ class ReceivablePayableReport:
def get_return_entries(self):
doctype = "Sales Invoice" if self.account_type == "Receivable" else "Purchase Invoice"
filters = {
"posting_date": ("<=", self.filters.report_date),
"is_return": 1,
"docstatus": 1,
"company": self.filters.company,
@@ -815,6 +834,7 @@ class ReceivablePayableReport:
if self.filters.get("sales_person"):
lft, rgt = frappe.db.get_value("Sales Person", self.filters.get("sales_person"), ["lft", "rgt"])
# nosemgrep
records = frappe.db.sql(
"""
select distinct parent, parenttype

View File

@@ -9,6 +9,7 @@ import re
import frappe
from frappe import _
from frappe.utils import add_days, add_months, cint, cstr, flt, formatdate, get_first_day, getdate
from pypika.terms import ExistsCriterion
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_accounting_dimensions,
@@ -181,12 +182,12 @@ def get_data(
company,
period_list[0]["year_start_date"] if only_current_fiscal_year else None,
period_list[-1]["to_date"],
root.lft,
root.rgt,
filters,
gl_entries_by_account,
ignore_closing_entries=ignore_closing_entries,
root.lft,
root.rgt,
root_type=root_type,
ignore_closing_entries=ignore_closing_entries,
)
calculate_values(
@@ -419,93 +420,78 @@ def set_gl_entries_by_account(
company,
from_date,
to_date,
root_lft,
root_rgt,
filters,
gl_entries_by_account,
root_lft=None,
root_rgt=None,
root_type=None,
ignore_closing_entries=False,
ignore_opening_entries=False,
root_type=None,
):
"""Returns a dict like { "account": [gl entries], ... }"""
gl_entries = []
account_filters = {
"company": company,
"is_group": 0,
"lft": (">=", root_lft),
"rgt": ("<=", root_rgt),
}
if root_type:
account_filters.update(
{
"root_type": root_type,
}
# For balance sheet
ignore_closing_balances = frappe.db.get_single_value(
"Accounts Settings", "ignore_account_closing_balance"
)
if not from_date and not ignore_closing_balances:
last_period_closing_voucher = frappe.db.get_all(
"Period Closing Voucher",
filters={
"docstatus": 1,
"company": filters.company,
"period_end_date": ("<", filters["period_start_date"]),
},
fields=["period_end_date", "name"],
order_by="period_end_date desc",
limit=1,
)
if last_period_closing_voucher:
gl_entries += get_accounting_entries(
"Account Closing Balance",
from_date,
to_date,
filters,
root_lft,
root_rgt,
root_type,
ignore_closing_entries,
last_period_closing_voucher[0].name,
)
from_date = add_days(last_period_closing_voucher[0].period_end_date, 1)
ignore_opening_entries = True
accounts_list = frappe.db.get_all(
"Account",
filters=account_filters,
pluck="name",
gl_entries += get_accounting_entries(
"GL Entry",
from_date,
to_date,
filters,
root_lft,
root_rgt,
root_type,
ignore_closing_entries,
ignore_opening_entries=ignore_opening_entries,
)
if accounts_list:
# For balance sheet
ignore_closing_balances = frappe.db.get_single_value(
"Accounts Settings", "ignore_account_closing_balance"
)
if not from_date and not ignore_closing_balances:
last_period_closing_voucher = frappe.db.get_all(
"Period Closing Voucher",
filters={
"docstatus": 1,
"company": filters.company,
"posting_date": ("<", filters["period_start_date"]),
},
fields=["posting_date", "name"],
order_by="posting_date desc",
limit=1,
)
if last_period_closing_voucher:
gl_entries += get_accounting_entries(
"Account Closing Balance",
from_date,
to_date,
accounts_list,
filters,
ignore_closing_entries,
last_period_closing_voucher[0].name,
)
from_date = add_days(last_period_closing_voucher[0].posting_date, 1)
ignore_opening_entries = True
if filters and filters.get("presentation_currency"):
convert_to_presentation_currency(gl_entries, get_currency(filters))
gl_entries += get_accounting_entries(
"GL Entry",
from_date,
to_date,
accounts_list,
filters,
ignore_closing_entries,
ignore_opening_entries=ignore_opening_entries,
)
for entry in gl_entries:
gl_entries_by_account.setdefault(entry.account, []).append(entry)
if filters and filters.get("presentation_currency"):
convert_to_presentation_currency(gl_entries, get_currency(filters))
for entry in gl_entries:
gl_entries_by_account.setdefault(entry.account, []).append(entry)
return gl_entries_by_account
return gl_entries_by_account
def get_accounting_entries(
doctype,
from_date,
to_date,
accounts,
filters,
ignore_closing_entries,
root_lft=None,
root_rgt=None,
root_type=None,
ignore_closing_entries=None,
period_closing_voucher=None,
ignore_opening_entries=False,
):
@@ -535,13 +521,30 @@ def get_accounting_entries(
query = query.where(gl_entry.period_closing_voucher == period_closing_voucher)
query = apply_additional_conditions(doctype, query, from_date, ignore_closing_entries, filters)
query = query.where(gl_entry.account.isin(accounts))
if (root_lft and root_rgt) or root_type:
account_filter_query = get_account_filter_query(root_lft, root_rgt, root_type, gl_entry)
query = query.where(ExistsCriterion(account_filter_query))
entries = query.run(as_dict=True)
return entries
def get_account_filter_query(root_lft, root_rgt, root_type, gl_entry):
acc = frappe.qb.DocType("Account")
exists_query = (
frappe.qb.from_(acc).select(acc.name).where(acc.name == gl_entry.account).where(acc.is_group == 0)
)
if root_lft and root_rgt:
exists_query = exists_query.where(acc.lft >= root_lft).where(acc.rgt <= root_rgt)
if root_type:
exists_query = exists_query.where(acc.root_type == root_type)
return exists_query
def apply_additional_conditions(doctype, query, from_date, ignore_closing_entries, filters):
gl_entry = frappe.qb.DocType(doctype)
accounting_dimensions = get_accounting_dimensions(as_list=False)

View File

@@ -348,10 +348,18 @@ def get_accounts_with_children(accounts):
return frappe.qb.from_(doctype).select(doctype.name).where(Criterion.any(conditions)).run(pluck=True)
def set_bill_no(gl_entries):
inv_details = get_supplier_invoice_details()
for gl in gl_entries:
gl["bill_no"] = inv_details.get(gl.get("against_voucher"), "")
def get_data_with_opening_closing(filters, account_details, accounting_dimensions, gl_entries):
data = []
totals_dict = get_totals_dict()
set_bill_no(gl_entries)
gle_map = initialize_gle_map(gl_entries, filters, totals_dict)
totals, entries = get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map, totals_dict)
@@ -539,7 +547,6 @@ def get_account_type_map(company):
def get_result_as_list(data, filters):
balance, _balance_in_account_currency = 0, 0
inv_details = get_supplier_invoice_details()
for d in data:
if not d.get("posting_date"):
@@ -549,7 +556,6 @@ def get_result_as_list(data, filters):
d["balance"] = balance
d["account_currency"] = filters.account_currency
d["bill_no"] = inv_details.get(d.get("against_voucher"), "")
return data

View File

@@ -130,6 +130,7 @@ class PaymentLedger:
)
def get_columns(self):
company_currency = frappe.get_cached_value("Company", self.filters.get("company"), "default_currency")
options = None
self.columns.append(
dict(
@@ -194,7 +195,7 @@ class PaymentLedger:
label=_("Amount"),
fieldname="amount",
fieldtype="Currency",
options="Company:company:default_currency",
options=company_currency,
width="100",
)
)

View File

@@ -526,7 +526,8 @@ def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts, inclu
tax_details = frappe.db.sql(
"""select parent, account_head,
sum(base_tax_amount_after_discount_amount) as tax_amount
from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head"""
from `tabSales Taxes and Charges` where parent in (%s) and parenttype = 'Sales Invoice'
group by parent, account_head"""
% ", ".join(["%s"] * len(invoice_list)),
tuple(inv.name for inv in invoice_list),
as_dict=1,

View File

@@ -0,0 +1,179 @@
import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import getdate, today
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.report.sales_register.sales_register import execute
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
class TestItemWiseSalesRegister(AccountsTestMixin, FrappeTestCase):
def setUp(self):
self.create_company()
self.create_customer()
self.create_item()
self.create_child_cost_center()
def tearDown(self):
frappe.db.rollback()
def create_child_cost_center(self):
cc_name = "South Wing"
if frappe.db.exists("Cost Center", cc_name):
cc = frappe.get_doc("Cost Center", cc_name)
else:
parent = frappe.db.get_value("Cost Center", self.cost_center, "parent_cost_center")
cc = frappe.get_doc(
{
"doctype": "Cost Center",
"company": self.company,
"is_group": False,
"parent_cost_center": parent,
"cost_center_name": cc_name,
}
)
cc = cc.save()
self.south_cc = cc.name
def create_sales_invoice(self, rate=100, do_not_submit=False):
si = create_sales_invoice(
item=self.item,
company=self.company,
customer=self.customer,
debit_to=self.debit_to,
posting_date=today(),
parent_cost_center=self.cost_center,
cost_center=self.cost_center,
rate=rate,
price_list_rate=rate,
do_not_save=1,
)
si = si.save()
if not do_not_submit:
si = si.submit()
return si
def test_basic_report_output(self):
si = self.create_sales_invoice(rate=98)
filters = frappe._dict({"from_date": today(), "to_date": today(), "company": self.company})
report = execute(filters)
res = [x for x in report[1] if x.get("voucher_no") == si.name]
expected_result = {
"voucher_type": si.doctype,
"voucher_no": si.name,
"posting_date": getdate(),
"customer": self.customer,
"receivable_account": self.debit_to,
"net_total": 98.0,
"grand_total": 98.0,
"debit": 98.0,
}
report_output = {k: v for k, v in res[0].items() if k in expected_result}
self.assertDictEqual(report_output, expected_result)
def test_journal_with_cost_center_filter(self):
je1 = frappe.get_doc(
{
"doctype": "Journal Entry",
"voucher_type": "Journal Entry",
"company": self.company,
"posting_date": getdate(),
"accounts": [
{
"account": self.debit_to,
"party_type": "Customer",
"party": self.customer,
"credit_in_account_currency": 77,
"credit": 77,
"is_advance": "Yes",
"cost_center": self.cost_center,
},
{
"account": self.cash,
"debit_in_account_currency": 77,
"debit": 77,
},
],
}
)
je1.submit()
je2 = frappe.get_doc(
{
"doctype": "Journal Entry",
"voucher_type": "Journal Entry",
"company": self.company,
"posting_date": getdate(),
"accounts": [
{
"account": self.debit_to,
"party_type": "Customer",
"party": self.customer,
"credit_in_account_currency": 98,
"credit": 98,
"is_advance": "Yes",
"cost_center": self.south_cc,
},
{
"account": self.cash,
"debit_in_account_currency": 98,
"debit": 98,
},
],
}
)
je2.submit()
filters = frappe._dict(
{
"from_date": today(),
"to_date": today(),
"company": self.company,
"include_payments": True,
"customer": self.customer,
"cost_center": self.cost_center,
}
)
report_output = execute(filters)[1]
filtered_output = [x for x in report_output if x.get("voucher_no") == je1.name]
self.assertEqual(len(filtered_output), 1)
expected_result = {
"voucher_type": je1.doctype,
"voucher_no": je1.name,
"posting_date": je1.posting_date,
"customer": self.customer,
"receivable_account": self.debit_to,
"net_total": 77.0,
"credit": 77.0,
}
result_fields = {k: v for k, v in filtered_output[0].items() if k in expected_result}
self.assertDictEqual(result_fields, expected_result)
filters = frappe._dict(
{
"from_date": today(),
"to_date": today(),
"company": self.company,
"include_payments": True,
"customer": self.customer,
"cost_center": self.south_cc,
}
)
report_output = execute(filters)[1]
filtered_output = [x for x in report_output if x.get("voucher_no") == je2.name]
self.assertEqual(len(filtered_output), 1)
expected_result = {
"voucher_type": je2.doctype,
"voucher_no": je2.name,
"posting_date": je2.posting_date,
"customer": self.customer,
"receivable_account": self.debit_to,
"net_total": 98.0,
"credit": 98.0,
}
result_output = {k: v for k, v in filtered_output[0].items() if k in expected_result}
self.assertDictEqual(result_output, expected_result)

View File

@@ -94,12 +94,6 @@ def get_data(filters):
accounts, accounts_by_name, parent_children_map = filter_accounts(accounts)
min_lft, max_rgt = frappe.db.sql(
"""select min(lft), max(rgt) from `tabAccount`
where company=%s""",
(filters.company,),
)[0]
gl_entries_by_account = {}
opening_balances = get_opening_balances(filters)
@@ -112,10 +106,10 @@ def get_data(filters):
filters.company,
filters.from_date,
filters.to_date,
min_lft,
max_rgt,
filters,
gl_entries_by_account,
root_lft=None,
root_rgt=None,
ignore_closing_entries=not flt(filters.with_period_closing_entry_for_current_period),
ignore_opening_entries=True,
)
@@ -150,9 +144,9 @@ def get_rootwise_opening_balances(filters, report_type):
if not ignore_closing_balances:
last_period_closing_voucher = frappe.db.get_all(
"Period Closing Voucher",
filters={"docstatus": 1, "company": filters.company, "posting_date": ("<", filters.from_date)},
fields=["posting_date", "name"],
order_by="posting_date desc",
filters={"docstatus": 1, "company": filters.company, "period_end_date": ("<", filters.from_date)},
fields=["period_end_date", "name"],
order_by="period_end_date desc",
limit=1,
)
@@ -168,8 +162,8 @@ def get_rootwise_opening_balances(filters, report_type):
)
# Report getting generate from the mid of a fiscal year
if getdate(last_period_closing_voucher[0].posting_date) < getdate(add_days(filters.from_date, -1)):
start_date = add_days(last_period_closing_voucher[0].posting_date, 1)
if getdate(last_period_closing_voucher[0].period_end_date) < getdate(add_days(filters.from_date, -1)):
start_date = add_days(last_period_closing_voucher[0].period_end_date, 1)
gle += get_opening_balance(
"GL Entry", filters, report_type, accounting_dimensions, start_date=start_date
)

View File

@@ -255,7 +255,9 @@ def get_journal_entries(filters, args):
)
.orderby(je.posting_date, je.name, order=Order.desc)
)
query = apply_common_conditions(filters, query, doctype="Journal Entry", payments=True)
query = apply_common_conditions(
filters, query, doctype="Journal Entry", child_doctype="Journal Entry Account", payments=True
)
journal_entries = query.run(as_dict=True)
return journal_entries
@@ -306,7 +308,9 @@ def apply_common_conditions(filters, query, doctype, child_doctype=None, payment
query = query.where(parent_doc.posting_date <= filters.to_date)
if payments:
if filters.get("cost_center"):
if doctype == "Journal Entry" and filters.get("cost_center"):
query = query.where(child_doc.cost_center == filters.cost_center)
elif filters.get("cost_center"):
query = query.where(parent_doc.cost_center == filters.cost_center)
else:
if filters.get("cost_center"):

View File

@@ -630,6 +630,16 @@ def update_reference_in_journal_entry(d, journal_entry, do_not_save=False):
if jv_detail.get("reference_type") in ["Sales Order", "Purchase Order"]:
update_advance_paid.append((jv_detail.reference_type, jv_detail.reference_name))
rev_dr_or_cr = (
"debit_in_account_currency"
if d["dr_or_cr"] == "credit_in_account_currency"
else "credit_in_account_currency"
)
if jv_detail.get(rev_dr_or_cr):
d["dr_or_cr"] = rev_dr_or_cr
d["allocated_amount"] = d["allocated_amount"] * -1
d["unadjusted_amount"] = d["unadjusted_amount"] * -1
if flt(d["unadjusted_amount"]) - flt(d["allocated_amount"]) != 0:
# adjust the unreconciled balance
amount_in_account_currency = flt(d["unadjusted_amount"]) - flt(d["allocated_amount"])
@@ -1547,12 +1557,16 @@ def compare_existing_and_expected_gle(existing_gle, expected_gle, precision):
return matched
def get_stock_accounts(company, voucher_type=None, voucher_no=None):
def get_stock_accounts(company, voucher_type=None, voucher_no=None, accounts=None):
stock_accounts = [
d.name
for d in frappe.db.get_all("Account", {"account_type": "Stock", "company": company, "is_group": 0})
]
if voucher_type and voucher_no:
if accounts:
stock_accounts = [row.account for row in accounts if row.account in stock_accounts]
elif voucher_type and voucher_no:
if voucher_type == "Journal Entry":
stock_accounts = [
d.account
@@ -1965,6 +1979,7 @@ class QueryPaymentLedger:
ple.cost_center.as_("cost_center"),
Sum(ple.amount).as_("amount"),
Sum(ple.amount_in_account_currency).as_("amount_in_account_currency"),
ple.remarks,
)
.where(ple.delinked == 0)
.where(Criterion.all(filter_on_voucher_no))
@@ -2027,6 +2042,7 @@ class QueryPaymentLedger:
Table("vouchers").due_date,
Table("vouchers").currency,
Table("vouchers").cost_center.as_("cost_center"),
Table("vouchers").remarks,
)
.where(Criterion.all(filter_on_outstanding_amount))
)

View File

@@ -119,6 +119,7 @@ class Asset(AccountsController):
# end: auto-generated types
def validate(self):
self.validate_precision()
self.validate_asset_values()
self.validate_asset_and_reference()
self.validate_item()
@@ -306,6 +307,15 @@ class Asset(AccountsController):
title=_("Missing Finance Book"),
)
def validate_precision(self):
float_precision = cint(frappe.db.get_default("float_precision")) or 2
if self.gross_purchase_amount:
self.gross_purchase_amount = flt(self.gross_purchase_amount, float_precision)
if self.opening_accumulated_depreciation:
self.opening_accumulated_depreciation = flt(
self.opening_accumulated_depreciation, float_precision
)
def validate_asset_values(self):
if not self.asset_category:
self.asset_category = frappe.get_cached_value("Item", self.item_code, "asset_category")
@@ -471,6 +481,9 @@ class Asset(AccountsController):
def validate_expected_value_after_useful_life(self):
for row in self.get("finance_books"):
row.expected_value_after_useful_life = flt(
row.expected_value_after_useful_life, self.precision("gross_purchase_amount")
)
depr_schedule = get_depr_schedule(self.name, "Draft", row.finance_book)
if not depr_schedule:
@@ -790,14 +803,19 @@ class Asset(AccountsController):
args.get("value_after_depreciation")
)
else:
value = flt(args.get("expected_value_after_useful_life")) / flt(self.gross_purchase_amount)
value = flt(args.get("expected_value_after_useful_life")) / (
flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation)
)
depreciation_rate = math.pow(
value,
1.0
/ (
(
flt(args.get("total_number_of_depreciations"), 2)
(
flt(args.get("total_number_of_depreciations"), 2)
- flt(self.opening_number_of_booked_depreciations)
)
* flt(args.get("frequency_of_depreciation"))
)
/ 12

View File

@@ -581,7 +581,7 @@ class PurchaseOrder(BuyingController):
def update_receiving_percentage(self):
total_qty, received_qty = 0.0, 0.0
for item in self.items:
received_qty += item.received_qty
received_qty += min(item.received_qty, item.qty)
total_qty += item.qty
if total_qty:
self.db_set("per_received", flt(received_qty / total_qty) * 100, update_modified=False)
@@ -625,9 +625,11 @@ class PurchaseOrder(BuyingController):
if not self.is_against_so():
return
for item in removed_items:
prev_ordered_qty = frappe.get_cached_value(
"Sales Order Item", item.get("sales_order_item"), "ordered_qty"
prev_ordered_qty = (
frappe.get_cached_value("Sales Order Item", item.get("sales_order_item"), "ordered_qty")
or 0.0
)
frappe.db.set_value(
"Sales Order Item", item.get("sales_order_item"), "ordered_qty", prev_ordered_qty - item.qty
)

View File

@@ -14,18 +14,25 @@ def get_data():
"Material Request": ["items", "material_request"],
"Supplier Quotation": ["items", "supplier_quotation"],
"Project": ["items", "project"],
"Sales Order": ["items", "sales_order"],
"BOM": ["items", "bom"],
"Production Plan": ["items", "production_plan"],
"Blanket Order": ["items", "blanket_order"],
},
"transactions": [
{"label": _("Related"), "items": ["Purchase Receipt", "Purchase Invoice"]},
{"label": _("Related"), "items": ["Purchase Receipt", "Purchase Invoice", "Sales Order"]},
{"label": _("Payment"), "items": ["Payment Entry", "Journal Entry", "Payment Request"]},
{
"label": _("Reference"),
"items": ["Material Request", "Supplier Quotation", "Project", "Auto Repeat"],
"items": ["Supplier Quotation", "Project", "Auto Repeat"],
},
{
"label": _("Manufacturing"),
"items": ["Material Request", "BOM", "Production Plan", "Blanket Order"],
},
{
"label": _("Sub-contracting"),
"items": ["Subcontracting Order", "Subcontracting Receipt", "Stock Entry"],
},
{"label": _("Internal"), "items": ["Sales Order"]},
],
}

View File

@@ -146,8 +146,8 @@ frappe.ui.form.on("Request for Quotation", {
return;
}
},
"Download PDF for Supplier",
"Download"
__("Download PDF for Supplier"),
__("Download")
);
},
__("Tools")
@@ -272,9 +272,10 @@ frappe.ui.form.on("Request for Quotation", {
});
};
dialog.fields_dict.note.$wrapper
.append(`<p class="small text-muted">This is a preview of the email to be sent. A PDF of the document will
automatically be attached with the email.</p>`);
const msg = __(
"This is a preview of the email to be sent. A PDF of the document will automatically be attached with the email."
);
dialog.fields_dict.note.$wrapper.append(`<p class="small text-muted">${msg}</p>`);
dialog.show();
},

View File

@@ -345,9 +345,21 @@ class AccountsController(TransactionBase):
repost_doc.flags.ignore_links = True
repost_doc.save(ignore_permissions=True)
def _remove_advance_payment_ledger_entries(self):
adv = qb.DocType("Advance Payment Ledger Entry")
qb.from_(adv).delete().where(adv.voucher_type.eq(self.doctype) & adv.voucher_no.eq(self.name)).run()
advance_payment_doctypes = frappe.get_hooks("advance_payment_doctypes")
if self.doctype in advance_payment_doctypes:
qb.from_(adv).delete().where(
adv.against_voucher_type.eq(self.doctype) & adv.against_voucher_no.eq(self.name)
).run()
def on_trash(self):
from erpnext.accounts.utils import delete_exchange_gain_loss_journal
self._remove_advance_payment_ledger_entries()
self._remove_references_in_repost_doctypes()
self._remove_references_in_unreconcile()
self.remove_serial_and_batch_bundle()
@@ -393,16 +405,14 @@ class AccountsController(TransactionBase):
def validate_return_against_account(self):
if self.doctype in ["Sales Invoice", "Purchase Invoice"] and self.is_return and self.return_against:
cr_dr_account_field = "debit_to" if self.doctype == "Sales Invoice" else "credit_to"
cr_dr_account_label = self.meta.get_label(cr_dr_account_field)
cr_dr_account = self.get(cr_dr_account_field)
original_account = frappe.get_value(self.doctype, self.return_against, cr_dr_account_field)
if original_account != cr_dr_account:
if original_account != self.get(cr_dr_account_field):
frappe.throw(
_(
"Please set {0} to {1}, the same account that was used in the original invoice {2}."
).format(
frappe.bold(_(cr_dr_account_label, context=self.doctype)),
frappe.bold(cr_dr_account),
frappe.bold(_(self.meta.get_label(cr_dr_account_field), context=self.doctype)),
frappe.bold(original_account),
frappe.bold(self.return_against),
)
)
@@ -453,6 +463,11 @@ class AccountsController(TransactionBase):
)
def validate_invoice_documents_schedule(self):
if self.is_return:
self.payment_terms_template = ""
self.payment_schedule = []
return
self.validate_payment_schedule_dates()
self.set_due_date()
self.set_payment_schedule()
@@ -467,7 +482,7 @@ class AccountsController(TransactionBase):
self.validate_payment_schedule_amount()
def validate_all_documents_schedule(self):
if self.doctype in ("Sales Invoice", "Purchase Invoice") and not self.is_return:
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
self.validate_invoice_documents_schedule()
elif self.doctype in ("Quotation", "Purchase Order", "Sales Order"):
self.validate_non_invoice_documents_schedule()
@@ -1081,9 +1096,11 @@ class AccountsController(TransactionBase):
return "Purchase Return"
elif self.doctype == "Delivery Note" and self.is_return:
return "Sales Return"
elif (self.doctype == "Sales Invoice" and self.is_return) or self.doctype == "Purchase Invoice":
elif self.doctype == "Sales Invoice" and self.is_return:
return "Credit Note"
elif (self.doctype == "Purchase Invoice" and self.is_return) or self.doctype == "Sales Invoice":
elif self.doctype == "Sales Invoice" and self.is_debit_note:
return "Debit Note"
elif self.doctype == "Purchase Invoice" and self.is_return:
return "Debit Note"
return self.doctype
@@ -1281,7 +1298,11 @@ class AccountsController(TransactionBase):
d.exchange_gain_loss = difference
def make_precision_loss_gl_entry(self, gl_entries):
round_off_account, round_off_cost_center = get_round_off_account_and_cost_center(
(
round_off_account,
round_off_cost_center,
round_off_for_opening,
) = get_round_off_account_and_cost_center(
self.company, "Purchase Invoice", self.name, self.use_company_roundoff_cost_center
)
@@ -1932,21 +1953,23 @@ class AccountsController(TransactionBase):
return stock_items
def set_total_advance_paid(self):
ple = frappe.qb.DocType("Payment Ledger Entry")
party = self.customer if self.doctype == "Sales Order" else self.supplier
def calculate_total_advance_from_ledger(self):
adv = frappe.qb.DocType("Advance Payment Ledger Entry")
advance = (
frappe.qb.from_(ple)
.select(ple.account_currency, Abs(Sum(ple.amount_in_account_currency)).as_("amount"))
frappe.qb.from_(adv)
.select(adv.currency.as_("account_currency"), Abs(Sum(adv.amount)).as_("amount"))
.where(
(ple.against_voucher_type == self.doctype)
& (ple.against_voucher_no == self.name)
& (ple.party == party)
& (ple.delinked == 0)
& (ple.company == self.company)
(adv.against_voucher_type == self.doctype)
& (adv.against_voucher_no == self.name)
& (adv.company == self.company)
)
.run(as_dict=True)
)
return advance
def set_total_advance_paid(self):
advance = self.calculate_total_advance_from_ledger()
advance_paid, order_total = None, None
if advance:
advance = advance[0]
@@ -2543,6 +2566,67 @@ class AccountsController(TransactionBase):
repost_ledger.insert()
repost_ledger.submit()
def get_advance_payment_doctypes(self) -> list:
return frappe.get_hooks("advance_payment_doctypes")
def make_advance_payment_ledger_for_journal(self):
advance_payment_doctypes = self.get_advance_payment_doctypes()
advance_doctype_references = [
x for x in self.accounts if x.reference_type in advance_payment_doctypes
]
for x in advance_doctype_references:
# Looking for payments
dr_or_cr = (
"credit_in_account_currency"
if x.account_type == "Receivable"
else "debit_in_account_currency"
)
amount = x.get(dr_or_cr)
if amount > 0:
doc = frappe.new_doc("Advance Payment Ledger Entry")
doc.company = self.company
doc.voucher_type = self.doctype
doc.voucher_no = self.name
doc.against_voucher_type = x.reference_type
doc.against_voucher_no = x.reference_name
doc.amount = amount if self.docstatus == 1 else -1 * amount
doc.event = "Submit" if self.docstatus == 1 else "Cancel"
doc.currency = x.account_currency
doc.flags.ignore_permissions = 1
doc.save()
def make_advance_payment_ledger_for_payment(self):
advance_payment_doctypes = self.get_advance_payment_doctypes()
advance_doctype_references = [
x for x in self.references if x.reference_doctype in advance_payment_doctypes
]
currency = (
self.paid_from_account_currency
if self.payment_type == "Receive"
else self.paid_to_account_currency
)
for x in advance_doctype_references:
doc = frappe.new_doc("Advance Payment Ledger Entry")
doc.company = self.company
doc.voucher_type = self.doctype
doc.voucher_no = self.name
doc.against_voucher_type = x.reference_doctype
doc.against_voucher_no = x.reference_name
doc.amount = x.allocated_amount if self.docstatus == 1 else -1 * x.allocated_amount
doc.currency = currency
doc.event = "Submit" if self.docstatus == 1 else "Cancel"
doc.flags.ignore_permissions = 1
doc.save()
def make_advance_payment_ledger_entries(self):
if self.docstatus != 0:
if self.doctype == "Journal Entry":
self.make_advance_payment_ledger_for_journal()
elif self.doctype == "Payment Entry":
self.make_advance_payment_ledger_for_payment()
@frappe.whitelist()
def get_tax_rate(account_head):

View File

@@ -415,7 +415,6 @@ def get_batches_from_stock_ledger_entries(searchfields, txt, filters, start=0, p
stock_ledger_entry.batch_no,
Sum(stock_ledger_entry.actual_qty).as_("qty"),
)
.where((batch_table.expiry_date >= expiry_date) | (batch_table.expiry_date.isnull()))
.where(stock_ledger_entry.is_cancelled == 0)
.where(
(stock_ledger_entry.item_code == filters.get("item_code"))
@@ -428,6 +427,9 @@ def get_batches_from_stock_ledger_entries(searchfields, txt, filters, start=0, p
.limit(page_len)
)
if not filters.get("include_expired_batches"):
query = query.where((batch_table.expiry_date >= expiry_date) | (batch_table.expiry_date.isnull()))
query = query.select(
Concat("MFG-", batch_table.manufacturing_date).as_("manufacturing_date"),
Concat("EXP-", batch_table.expiry_date).as_("expiry_date"),
@@ -466,7 +468,6 @@ def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters, start=0
bundle.batch_no,
Sum(bundle.qty).as_("qty"),
)
.where((batch_table.expiry_date >= expiry_date) | (batch_table.expiry_date.isnull()))
.where(stock_ledger_entry.is_cancelled == 0)
.where(
(stock_ledger_entry.item_code == filters.get("item_code"))
@@ -479,6 +480,11 @@ def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters, start=0
.limit(page_len)
)
if not filters.get("include_expired_batches"):
bundle_query = bundle_query.where(
(batch_table.expiry_date >= expiry_date) | (batch_table.expiry_date.isnull())
)
bundle_query = bundle_query.select(
Concat("MFG-", batch_table.manufacturing_date),
Concat("EXP-", batch_table.expiry_date),

View File

@@ -79,6 +79,9 @@ def validate_returned_items(doc):
if doc.doctype in ["Purchase Invoice", "Purchase Receipt", "Subcontracting Receipt"]:
select_fields += ",rejected_qty, received_qty"
if doc.doctype in ["Purchase Receipt", "Purchase Invoice"]:
select_fields += ",name"
for d in frappe.db.sql(
f"""select {select_fields} from `tab{doc.doctype} Item` where parent = %s""",
doc.return_against,
@@ -104,15 +107,24 @@ def validate_returned_items(doc):
items_returned = False
for d in doc.get("items"):
key = d.item_code
raise_exception = False
if doc.doctype in ["Purchase Receipt", "Purchase Invoice"]:
field = frappe.scrub(doc.doctype) + "_item"
if d.get(field):
key = (d.item_code, d.get(field))
raise_exception = True
if d.item_code and (flt(d.qty) < 0 or flt(d.get("received_qty")) < 0):
if d.item_code not in valid_items:
frappe.throw(
if key not in valid_items:
frappe.msgprint(
_("Row # {0}: Returned Item {1} does not exist in {2} {3}").format(
d.idx, d.item_code, doc.doctype, doc.return_against
)
),
raise_exception=raise_exception,
)
else:
ref = valid_items.get(d.item_code, frappe._dict())
ref = valid_items.get(key, frappe._dict())
validate_quantity(doc, d, ref, valid_items, already_returned_items)
if (
@@ -193,8 +205,12 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
def get_ref_item_dict(valid_items, ref_item_row):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
key = ref_item_row.item_code
if ref_item_row.get("name"):
key = (ref_item_row.item_code, ref_item_row.name)
valid_items.setdefault(
ref_item_row.item_code,
key,
frappe._dict(
{
"qty": 0,
@@ -208,7 +224,7 @@ def get_ref_item_dict(valid_items, ref_item_row):
}
),
)
item_dict = valid_items[ref_item_row.item_code]
item_dict = valid_items[key]
item_dict["qty"] += ref_item_row.qty
item_dict["stock_qty"] += ref_item_row.get("stock_qty", 0)
if ref_item_row.get("rate", 0) > item_dict["rate"]:
@@ -335,6 +351,9 @@ def make_return_doc(doctype: str, source_name: str, target_doc=None, return_agai
doc.select_print_heading = frappe.get_cached_value("Print Heading", _("Debit Note"))
if source.tax_withholding_category:
doc.set_onload("supplier_tds", source.tax_withholding_category)
elif doctype == "Delivery Note":
# manual additions to the return should hit the return warehous, too
doc.set_warehouse = default_warehouse_for_sales_return
for tax in doc.get("taxes") or []:
if tax.charge_type == "Actual":
@@ -581,6 +600,10 @@ def make_return_doc(doctype: str, source_name: str, target_doc=None, return_agai
if default_warehouse_for_sales_return:
target_doc.warehouse = default_warehouse_for_sales_return
if not source_doc.use_serial_batch_fields and source_doc.serial_and_batch_bundle:
target_doc.serial_no = None
target_doc.batch_no = None
if (
(source_doc.serial_no or source_doc.batch_no)
and not source_doc.serial_and_batch_bundle
@@ -883,6 +906,7 @@ def get_serial_batches_based_on_bundle(field, _bundle_ids):
"`tabSerial and Batch Entry`.`serial_no`",
"`tabSerial and Batch Entry`.`batch_no`",
"`tabSerial and Batch Entry`.`qty`",
"`tabSerial and Batch Entry`.`incoming_rate`",
"`tabSerial and Batch Bundle`.`voucher_detail_no`",
"`tabSerial and Batch Bundle`.`voucher_type`",
"`tabSerial and Batch Bundle`.`voucher_no`",
@@ -904,15 +928,23 @@ def get_serial_batches_based_on_bundle(field, _bundle_ids):
if key not in available_dict:
available_dict[key] = frappe._dict(
{"qty": 0.0, "serial_nos": defaultdict(float), "batches": defaultdict(float)}
{
"qty": 0.0,
"serial_nos": defaultdict(float),
"batches": defaultdict(float),
"serial_nos_valuation": defaultdict(float),
"batches_valuation": defaultdict(float),
}
)
available_dict[key]["qty"] += row.qty
if row.serial_no:
available_dict[key]["serial_nos"][row.serial_no] += row.qty
available_dict[key]["serial_nos_valuation"][row.serial_no] = row.incoming_rate
elif row.batch_no:
available_dict[key]["batches"][row.batch_no] += row.qty
available_dict[key]["batches_valuation"][row.batch_no] = row.incoming_rate
return available_dict
@@ -948,12 +980,13 @@ def get_serial_and_batch_bundle(field, doctype, reference_ids, is_rejected=False
)
)
else:
fields = [
"serial_and_batch_bundle",
]
fields = ["serial_and_batch_bundle"]
if is_rejected:
fields.extend(["rejected_serial_and_batch_bundle", "return_qty_from_rejected_warehouse"])
fields.append("rejected_serial_and_batch_bundle")
if doctype == "Purchase Receipt Item":
fields.append("return_qty_from_rejected_warehouse")
del filters["rejected_serial_and_batch_bundle"]
data = frappe.get_all(
@@ -987,7 +1020,14 @@ def filter_serial_batches(parent_doc, data, row, warehouse_field=None, qty_field
warehouse = row.get(warehouse_field)
qty = abs(row.get(qty_field))
filterd_serial_batch = frappe._dict({"serial_nos": [], "batches": defaultdict(float)})
filterd_serial_batch = frappe._dict(
{
"serial_nos": [],
"batches": defaultdict(float),
"serial_nos_valuation": data.get("serial_nos_valuation"),
"batches_valuation": data.get("batches_valuation"),
}
)
if data.serial_nos:
available_serial_nos = []
@@ -997,7 +1037,7 @@ def filter_serial_batches(parent_doc, data, row, warehouse_field=None, qty_field
if available_serial_nos:
if parent_doc.doctype in ["Purchase Invoice", "Purchase Reecipt"]:
available_serial_nos = get_available_serial_nos(available_serial_nos)
available_serial_nos = get_available_serial_nos(available_serial_nos, warehouse)
if len(available_serial_nos) > qty:
filterd_serial_batch["serial_nos"] = sorted(available_serial_nos[0 : cint(qty)])
@@ -1082,6 +1122,8 @@ def make_serial_batch_bundle_for_return(data, child_doc, parent_doc, warehouse_f
"warehouse": warehouse,
"serial_nos": data.get("serial_nos"),
"batches": data.get("batches"),
"serial_nos_valuation": data.get("serial_nos_valuation"),
"batches_valuation": data.get("batches_valuation"),
"posting_date": parent_doc.posting_date,
"posting_time": parent_doc.posting_time,
"voucher_type": parent_doc.doctype,

View File

@@ -167,6 +167,9 @@ class SellingController(StockController):
total = 0.0
sales_team = self.get("sales_team")
self.validate_sales_team(sales_team)
for sales_person in sales_team:
self.round_floats_in(sales_person)
@@ -186,6 +189,20 @@ class SellingController(StockController):
if sales_team and total != 100.0:
throw(_("Total allocated percentage for sales team should be 100"))
def validate_sales_team(self, sales_team):
sales_persons = [d.sales_person for d in sales_team]
if not sales_persons:
return
sales_person_status = frappe.db.get_all(
"Sales Person", filters={"name": ["in", sales_persons]}, fields=["name", "enabled"]
)
for row in sales_person_status:
if not row.enabled:
frappe.throw(_("Sales Person <b>{0}</b> is disabled.").format(row.name))
def validate_max_discount(self):
for d in self.get("items"):
if d.item_code:

View File

@@ -334,6 +334,11 @@ class StockController(AccountsController):
}
)
if self.doctype in ["Sales Invoice", "Delivery Note"]:
row.db_set(
"incoming_rate", frappe.db.get_value("Serial and Batch Bundle", bundle, "avg_rate")
)
def get_reference_ids(self, table_name, qty_field=None, bundle_field=None) -> tuple[str, list[str]]:
field = {
"Sales Invoice": "sales_invoice_item",
@@ -834,6 +839,15 @@ class StockController(AccountsController):
if not dimension:
continue
if (
self.doctype in ["Purchase Invoice", "Purchase Receipt"]
and row.get("rejected_warehouse")
and sl_dict.get("warehouse") == row.get("rejected_warehouse")
):
fieldname = f"rejected_{dimension.source_fieldname}"
sl_dict[dimension.target_fieldname] = row.get(fieldname)
continue
if self.doctype in [
"Purchase Invoice",
"Purchase Receipt",

View File

@@ -561,11 +561,11 @@ class SubcontractingController(StockController):
use_serial_batch_fields = frappe.db.get_single_value("Stock Settings", "use_serial_batch_fields")
if self.doctype == self.subcontract_data.order_doctype:
rm_obj.required_qty = qty
rm_obj.amount = rm_obj.required_qty * rm_obj.rate
rm_obj.required_qty = flt(qty, rm_obj.precision("required_qty"))
rm_obj.amount = flt(rm_obj.required_qty * rm_obj.rate, rm_obj.precision("amount"))
else:
rm_obj.consumed_qty = qty
rm_obj.required_qty = bom_item.required_qty or qty
rm_obj.consumed_qty = flt(qty, rm_obj.precision("consumed_qty"))
rm_obj.required_qty = flt(bom_item.required_qty or qty, rm_obj.precision("required_qty"))
rm_obj.serial_and_batch_bundle = None
setattr(
rm_obj, self.subcontract_data.order_field, item_row.get(self.subcontract_data.order_field)
@@ -664,8 +664,8 @@ class SubcontractingController(StockController):
self.__set_serial_nos(item_row, rm_obj)
def __set_consumed_qty(self, rm_obj, consumed_qty, required_qty=0):
rm_obj.required_qty = required_qty
rm_obj.consumed_qty = consumed_qty
rm_obj.required_qty = flt(required_qty, rm_obj.precision("required_qty"))
rm_obj.consumed_qty = flt(consumed_qty, rm_obj.precision("consumed_qty"))
def __set_serial_nos(self, item_row, rm_obj):
key = (rm_obj.rm_item_code, item_row.item_code, item_row.get(self.subcontract_data.order_field))
@@ -1235,6 +1235,17 @@ def add_items_in_ste(ste_doc, row, qty, rm_details, rm_detail_field="sco_rm_deta
def make_return_stock_entry_for_subcontract(
available_materials, order_doc, rm_details, order_doctype="Subcontracting Order"
):
def post_process(source_doc, target_doc):
target_doc.purpose = "Material Transfer"
if source_doc.doctype == "Purchase Order":
target_doc.purchase_order = source_doc.name
else:
target_doc.subcontracting_order = source_doc.name
target_doc.company = source_doc.company
target_doc.is_return = 1
ste_doc = get_mapped_doc(
order_doctype,
order_doc.name,
@@ -1245,18 +1256,13 @@ def make_return_stock_entry_for_subcontract(
},
},
ignore_child_tables=True,
postprocess=post_process,
)
ste_doc.purpose = "Material Transfer"
if order_doctype == "Purchase Order":
ste_doc.purchase_order = order_doc.name
rm_detail_field = "po_detail"
else:
ste_doc.subcontracting_order = order_doc.name
rm_detail_field = "sco_rm_detail"
ste_doc.company = order_doc.company
ste_doc.is_return = 1
for _key, value in available_materials.items():
if not value.qty:

View File

@@ -8,6 +8,7 @@ import frappe
from frappe import _, scrub
from frappe.model.document import Document
from frappe.utils import cint, flt, round_based_on_smallest_currency_fraction
from frappe.utils.deprecations import deprecated
import erpnext
from erpnext.accounts.doctype.journal_entry.journal_entry import get_exchange_rate
@@ -74,7 +75,7 @@ class calculate_taxes_and_totals:
self.calculate_net_total()
self.calculate_tax_withholding_net_total()
self.calculate_taxes()
self.manipulate_grand_total_for_inclusive_tax()
self.adjust_grand_total_for_inclusive_tax()
self.calculate_totals()
self._cleanup()
self.calculate_total_net_weight()
@@ -286,7 +287,7 @@ class calculate_taxes_and_totals:
):
amount = flt(item.amount) - total_inclusive_tax_amount_per_qty
item.net_amount = flt(amount / (1 + cumulated_tax_fraction))
item.net_amount = flt(amount / (1 + cumulated_tax_fraction), item.precision("net_amount"))
item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate"))
item.discount_percentage = flt(
item.discount_percentage, item.precision("discount_percentage")
@@ -531,7 +532,12 @@ class calculate_taxes_and_totals:
tax.base_tax_amount = round(tax.base_tax_amount, 0)
tax.base_tax_amount_after_discount_amount = round(tax.base_tax_amount_after_discount_amount, 0)
@deprecated
def manipulate_grand_total_for_inclusive_tax(self):
# for backward compatablility - if in case used by an external application
return self.adjust_grand_total_for_inclusive_tax()
def adjust_grand_total_for_inclusive_tax(self):
# if fully inclusive taxes and diff
if self.doc.get("taxes") and any(cint(t.included_in_print_rate) for t in self.doc.get("taxes")):
last_tax = self.doc.get("taxes")[-1]
@@ -553,17 +559,21 @@ class calculate_taxes_and_totals:
diff = flt(diff, self.doc.precision("rounding_adjustment"))
if diff and abs(diff) <= (5.0 / 10 ** last_tax.precision("tax_amount")):
self.doc.rounding_adjustment = diff
self.doc.grand_total_diff = diff
else:
self.doc.grand_total_diff = 0
def calculate_totals(self):
if self.doc.get("taxes"):
self.doc.grand_total = flt(self.doc.get("taxes")[-1].total) + flt(self.doc.rounding_adjustment)
self.doc.grand_total = flt(self.doc.get("taxes")[-1].total) + flt(
self.doc.get("grand_total_diff")
)
else:
self.doc.grand_total = flt(self.doc.net_total)
if self.doc.get("taxes"):
self.doc.total_taxes_and_charges = flt(
self.doc.grand_total - self.doc.net_total - flt(self.doc.rounding_adjustment),
self.doc.grand_total - self.doc.net_total - flt(self.doc.get("grand_total_diff")),
self.doc.precision("total_taxes_and_charges"),
)
else:
@@ -626,8 +636,8 @@ class calculate_taxes_and_totals:
self.doc.grand_total, self.doc.currency, self.doc.precision("rounded_total")
)
# if print_in_rate is set, we would have already calculated rounding adjustment
self.doc.rounding_adjustment += flt(
# rounding adjustment should always be the difference vetween grand and rounded total
self.doc.rounding_adjustment = flt(
self.doc.rounded_total - self.doc.grand_total, self.doc.precision("rounding_adjustment")
)

View File

@@ -1234,6 +1234,7 @@ def make_subcontracted_items():
"Subcontracted Item SA6": {},
"Subcontracted Item SA7": {},
"Subcontracted Item SA8": {},
"Subcontracted Item SA9": {"stock_uom": "Litre"},
}
for item, properties in sub_contracted_items.items():
@@ -1254,6 +1255,7 @@ def make_raw_materials():
"Subcontracted SRM Item 4": {"has_serial_no": 1, "serial_no_series": "SRII.####"},
"Subcontracted SRM Item 5": {"has_serial_no": 1, "serial_no_series": "SRIID.####"},
"Subcontracted SRM Item 8": {},
"Subcontracted SRM Item 9": {"stock_uom": "Litre"},
}
for item, properties in raw_materials.items():
@@ -1280,6 +1282,7 @@ def make_service_items():
"Subcontracted Service Item 6": {},
"Subcontracted Service Item 7": {},
"Subcontracted Service Item 8": {},
"Subcontracted Service Item 9": {},
}
for item, properties in service_items.items():

View File

@@ -127,8 +127,8 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller
fieldname: "prospect_name",
fieldtype: "Data",
default: frm.doc.company_name,
reqd: 1,
depends_on: "create_prospect",
mandatory_depends_on: "create_prospect",
}
);
}

0
erpnext/edi/__init__.py Normal file
View File

View File

View File

@@ -0,0 +1,51 @@
// Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Code List", {
refresh: (frm) => {
if (!frm.doc.__islocal) {
frm.add_custom_button(__("Import Genericode File"), function () {
erpnext.edi.import_genericode(frm);
});
}
},
setup: (frm) => {
frm.savetrash = () => {
frm.validate_form_action("Delete");
frappe.confirm(
__(
"Are you sure you want to delete {0}?<p>This action will also delete all associated Common Code documents.</p>",
[frm.docname.bold()]
),
function () {
return frappe.call({
method: "frappe.client.delete",
args: {
doctype: frm.doctype,
name: frm.docname,
},
freeze: true,
freeze_message: __("Deleting {0} and all associated Common Code documents...", [
frm.docname,
]),
callback: function (r) {
if (!r.exc) {
frappe.utils.play_sound("delete");
frappe.model.clear_doc(frm.doctype, frm.docname);
window.history.back();
}
},
});
}
);
};
frm.set_query("default_common_code", function (doc) {
return {
filters: {
code_list: doc.name,
},
};
});
},
});

View File

@@ -0,0 +1,112 @@
{
"actions": [],
"allow_copy": 1,
"allow_rename": 1,
"autoname": "prompt",
"creation": "2024-09-29 06:55:03.920375",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"title",
"canonical_uri",
"url",
"default_common_code",
"column_break_nkls",
"version",
"publisher",
"publisher_id",
"section_break_npxp",
"description"
],
"fields": [
{
"fieldname": "title",
"fieldtype": "Data",
"label": "Title"
},
{
"fieldname": "publisher",
"fieldtype": "Data",
"in_standard_filter": 1,
"label": "Publisher"
},
{
"columns": 1,
"fieldname": "version",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Version"
},
{
"fieldname": "description",
"fieldtype": "Small Text",
"label": "Description"
},
{
"fieldname": "canonical_uri",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Canonical URI"
},
{
"fieldname": "column_break_nkls",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_npxp",
"fieldtype": "Section Break"
},
{
"fieldname": "publisher_id",
"fieldtype": "Data",
"in_standard_filter": 1,
"label": "Publisher ID"
},
{
"fieldname": "url",
"fieldtype": "Data",
"label": "URL",
"options": "URL"
},
{
"description": "This value shall be used when no matching Common Code for a record is found.",
"fieldname": "default_common_code",
"fieldtype": "Link",
"label": "Default Common Code",
"options": "Common Code"
}
],
"index_web_pages_for_search": 1,
"links": [
{
"link_doctype": "Common Code",
"link_fieldname": "code_list"
}
],
"modified": "2024-11-16 17:01:40.260293",
"modified_by": "Administrator",
"module": "EDI",
"name": "Code List",
"naming_rule": "Set by user",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"search_fields": "description",
"show_title_field_in_link": 1,
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"title_field": "title"
}

View File

@@ -0,0 +1,125 @@
# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from typing import TYPE_CHECKING
import frappe
from frappe.model.document import Document
if TYPE_CHECKING:
from lxml.etree import Element
class CodeList(Document):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from frappe.types import DF
canonical_uri: DF.Data | None
default_common_code: DF.Link | None
description: DF.SmallText | None
publisher: DF.Data | None
publisher_id: DF.Data | None
title: DF.Data | None
url: DF.Data | None
version: DF.Data | None
# end: auto-generated types
def on_trash(self):
if not frappe.flags.in_bulk_delete:
self.__delete_linked_docs()
def __delete_linked_docs(self):
self.db_set("default_common_code", None)
linked_docs = frappe.get_all(
"Common Code",
filters={"code_list": self.name},
fields=["name"],
)
for doc in linked_docs:
frappe.delete_doc("Common Code", doc.name)
def get_codes_for(self, doctype: str, name: str) -> tuple[str]:
"""Get the applicable codes for a doctype and name"""
return get_codes_for(self.name, doctype, name)
def get_docnames_for(self, doctype: str, code: str) -> tuple[str]:
"""Get the mapped docnames for a doctype and code"""
return get_docnames_for(self.name, doctype, code)
def get_default_code(self) -> str | None:
"""Get the default common code for this code list"""
return (
frappe.db.get_value("Common Code", self.default_common_code, "common_code")
if self.default_common_code
else None
)
def from_genericode(self, root: "Element"):
"""Extract Code List details from genericode XML"""
self.title = root.find(".//Identification/ShortName").text
self.version = root.find(".//Identification/Version").text
self.canonical_uri = root.find(".//CanonicalUri").text
# optionals
self.description = getattr(root.find(".//Identification/LongName"), "text", None)
self.publisher = getattr(root.find(".//Identification/Agency/ShortName"), "text", None)
if not self.publisher:
self.publisher = getattr(root.find(".//Identification/Agency/LongName"), "text", None)
self.publisher_id = getattr(root.find(".//Identification/Agency/Identifier"), "text", None)
self.url = getattr(root.find(".//Identification/LocationUri"), "text", None)
def get_codes_for(code_list: str, doctype: str, name: str) -> tuple[str]:
"""Return the common code for a given record"""
CommonCode = frappe.qb.DocType("Common Code")
DynamicLink = frappe.qb.DocType("Dynamic Link")
codes = (
frappe.qb.from_(CommonCode)
.join(DynamicLink)
.on((CommonCode.name == DynamicLink.parent) & (DynamicLink.parenttype == "Common Code"))
.select(CommonCode.common_code)
.where(
(DynamicLink.link_doctype == doctype)
& (DynamicLink.link_name == name)
& (CommonCode.code_list == code_list)
)
.distinct()
.orderby(CommonCode.common_code)
).run()
return tuple(c[0] for c in codes) if codes else ()
def get_docnames_for(code_list: str, doctype: str, code: str) -> tuple[str]:
"""Return the record name for a given common code"""
CommonCode = frappe.qb.DocType("Common Code")
DynamicLink = frappe.qb.DocType("Dynamic Link")
docnames = (
frappe.qb.from_(CommonCode)
.join(DynamicLink)
.on((CommonCode.name == DynamicLink.parent) & (DynamicLink.parenttype == "Common Code"))
.select(DynamicLink.link_name)
.where(
(DynamicLink.link_doctype == doctype)
& (CommonCode.common_code == code)
& (CommonCode.code_list == code_list)
)
.distinct()
.orderby(DynamicLink.idx)
).run()
return tuple(d[0] for d in docnames) if docnames else ()
def get_default_code(code_list: str) -> str | None:
"""Return the default common code for a given code list"""
code_id = frappe.db.get_value("Code List", code_list, "default_common_code")
return frappe.db.get_value("Common Code", code_id, "common_code") if code_id else None

View File

@@ -0,0 +1,218 @@
frappe.provide("erpnext.edi");
erpnext.edi.import_genericode = function (listview_or_form) {
let doctype = "Code List";
let docname = undefined;
if (listview_or_form.doc !== undefined) {
docname = listview_or_form.doc.name;
}
new frappe.ui.FileUploader({
method: "erpnext.edi.doctype.code_list.code_list_import.import_genericode",
doctype: doctype,
docname: docname,
allow_toggle_private: false,
allow_take_photo: false,
on_success: function (_file_doc, r) {
listview_or_form.refresh();
show_column_selection_dialog(r.message);
},
});
};
function show_column_selection_dialog(context) {
let title_description = __("If there is no title column, use the code column for the title.");
let default_title = get_default(context.columns, ["name", "Name", "code-name", "scheme-name"]);
let fields = [
{
fieldtype: "HTML",
fieldname: "code_list_info",
options: `<div class="text-muted">${__(
"You are importing data for the code list:"
)} ${frappe.utils.get_form_link(
"Code List",
context.code_list,
true,
context.code_list_title
)}</div>`,
},
{
fieldtype: "Section Break",
},
{
fieldname: "import_column",
label: __("Import"),
fieldtype: "Column Break",
},
{
fieldname: "title_column",
label: __("as Title"),
fieldtype: "Select",
reqd: 1,
options: context.columns,
default: default_title,
description: default_title ? null : title_description,
},
{
fieldname: "code_column",
label: __("as Code"),
fieldtype: "Select",
options: context.columns,
reqd: 1,
default: get_default(context.columns, ["code", "Code", "value"]),
},
{
fieldname: "filters_column",
label: __("Filter"),
fieldtype: "Column Break",
},
];
if (context.columns.length > 2) {
fields.splice(5, 0, {
fieldname: "description_column",
label: __("as Description"),
fieldtype: "Select",
options: [null].concat(context.columns),
default: get_default(context.columns, [
"description",
"Description",
"remark",
__("description"),
__("Description"),
]),
});
}
// Add filterable columns
for (let column in context.filterable_columns) {
fields.push({
fieldname: `filter_${column}`,
label: __("by {}", [column]),
fieldtype: "Select",
options: [null].concat(context.filterable_columns[column]),
});
}
fields.push(
{
fieldname: "preview_section",
label: __("Preview"),
fieldtype: "Section Break",
},
{
fieldname: "preview_html",
fieldtype: "HTML",
}
);
let d = new frappe.ui.Dialog({
title: __("Select Columns and Filters"),
fields: fields,
primary_action_label: __("Import"),
size: "large", // This will make the modal wider
primary_action(values) {
let filters = {};
for (let field in values) {
if (field.startsWith("filter_") && values[field]) {
filters[field.replace("filter_", "")] = values[field];
}
}
frappe
.xcall("erpnext.edi.doctype.code_list.code_list_import.process_genericode_import", {
code_list_name: context.code_list,
file_name: context.file,
code_column: values.code_column,
title_column: values.title_column,
description_column: values.description_column,
filters: filters,
})
.then((count) => {
frappe.msgprint(__("Import completed. {0} common codes created.", [count]));
});
d.hide();
},
});
d.fields_dict.code_column.df.onchange = () => update_preview(d, context);
d.fields_dict.title_column.df.onchange = (e) => {
let field = d.fields_dict.title_column;
if (!e.target.value) {
field.df.description = title_description;
field.refresh();
} else {
field.df.description = null;
field.refresh();
}
update_preview(d, context);
};
// Add onchange events for filterable columns
for (let column in context.filterable_columns) {
d.fields_dict[`filter_${column}`].df.onchange = () => update_preview(d, context);
}
d.show();
update_preview(d, context);
}
/**
* Return the first key from the keys array that is found in the columns array.
*/
function get_default(columns, keys) {
return keys.find((key) => columns.includes(key));
}
function update_preview(dialog, context) {
let code_column = dialog.get_value("code_column");
let title_column = dialog.get_value("title_column");
let description_column = dialog.get_value("description_column");
let html = '<table class="table table-bordered"><thead><tr>';
if (title_column) html += `<th>${__("Title")}</th>`;
if (code_column) html += `<th>${__("Code")}</th>`;
if (description_column) html += `<th>${__("Description")}</th>`;
// Add headers for filterable columns
for (let column in context.filterable_columns) {
if (dialog.get_value(`filter_${column}`)) {
html += `<th>${__(column)}</th>`;
}
}
html += "</tr></thead><tbody>";
for (let i = 0; i < 3; i++) {
html += "<tr>";
if (title_column) {
let title = context.example_values[title_column][i] || "";
html += `<td title="${title}">${truncate(title)}</td>`;
}
if (code_column) {
let code = context.example_values[code_column][i] || "";
html += `<td title="${code}">${truncate(code)}</td>`;
}
if (description_column) {
let description = context.example_values[description_column][i] || "";
html += `<td title="${description}">${truncate(description)}</td>`;
}
// Add values for filterable columns
for (let column in context.filterable_columns) {
if (dialog.get_value(`filter_${column}`)) {
let value = context.example_values[column][i] || "";
html += `<td title="${value}">${truncate(value)}</td>`;
}
}
html += "</tr>";
}
html += "</tbody></table>";
dialog.fields_dict.preview_html.$wrapper.html(html);
}
function truncate(value, maxLength = 40) {
if (typeof value !== "string") return "";
return value.length > maxLength ? value.substring(0, maxLength - 3) + "..." : value;
}

View File

@@ -0,0 +1,140 @@
import json
import frappe
import requests
from frappe import _
from lxml import etree
URL_PREFIXES = ("http://", "https://")
@frappe.whitelist()
def import_genericode():
doctype = "Code List"
docname = frappe.form_dict.docname
content = frappe.local.uploaded_file
# recover the content, if it's a link
if (file_url := frappe.local.uploaded_file_url) and file_url.startswith(URL_PREFIXES):
try:
# If it's a URL, fetch the content and make it a local file (for durable audit)
response = requests.get(frappe.local.uploaded_file_url)
response.raise_for_status()
frappe.local.uploaded_file = content = response.content
frappe.local.uploaded_filename = frappe.local.uploaded_file_url.split("/")[-1]
frappe.local.uploaded_file_url = None
except Exception as e:
frappe.throw(f"<pre>{e!s}</pre>", title=_("Fetching Error"))
if file_url := frappe.local.uploaded_file_url:
file_path = frappe.utils.file_manager.get_file_path(file_url)
with open(file_path.encode(), mode="rb") as f:
content = f.read()
# Parse the xml content
parser = etree.XMLParser(remove_blank_text=True)
try:
root = etree.fromstring(content, parser=parser)
except Exception as e:
frappe.throw(f"<pre>{e!s}</pre>", title=_("Parsing Error"))
# Extract the name (CanonicalVersionUri) from the parsed XML
name = root.find(".//CanonicalVersionUri").text
docname = docname or name
if frappe.db.exists(doctype, docname):
code_list = frappe.get_doc(doctype, docname)
if code_list.name != name:
frappe.throw(_("The uploaded file does not match the selected Code List."))
else:
# Create a new Code List document with the extracted name
code_list = frappe.new_doc(doctype)
code_list.name = name
code_list.from_genericode(root)
code_list.save()
# Attach the file and provide a recoverable identifier
file_doc = frappe.get_doc(
{
"doctype": "File",
"attached_to_doctype": "Code List",
"attached_to_name": code_list.name,
"folder": "Home/Attachments",
"file_name": frappe.local.uploaded_filename,
"file_url": frappe.local.uploaded_file_url,
"is_private": 1,
"content": content,
}
).save()
# Get available columns and example values
columns, example_values, filterable_columns = get_genericode_columns_and_examples(root)
return {
"code_list": code_list.name,
"code_list_title": code_list.title,
"file": file_doc.name,
"columns": columns,
"example_values": example_values,
"filterable_columns": filterable_columns,
}
@frappe.whitelist()
def process_genericode_import(
code_list_name: str,
file_name: str,
code_column: str,
title_column: str | None = None,
description_column: str | None = None,
filters: str | None = None,
):
from erpnext.edi.doctype.common_code.common_code import import_genericode
column_map = {"code": code_column, "title": title_column, "description": description_column}
return import_genericode(code_list_name, file_name, column_map, json.loads(filters) if filters else None)
def get_genericode_columns_and_examples(root):
columns = []
example_values = {}
filterable_columns = {}
# Get column names
for column in root.findall(".//Column"):
column_id = column.get("Id")
columns.append(column_id)
example_values[column_id] = []
filterable_columns[column_id] = set()
# Get all values and count unique occurrences
for row in root.findall(".//SimpleCodeList/Row"):
for value in row.findall("Value"):
column_id = value.get("ColumnRef")
if column_id not in columns:
# Handle undeclared column
columns.append(column_id)
example_values[column_id] = []
filterable_columns[column_id] = set()
simple_value = value.find("./SimpleValue")
if simple_value is None:
continue
filterable_columns[column_id].add(simple_value.text)
# Get example values (up to 3) and filter columns with cardinality <= 5
for row in root.findall(".//SimpleCodeList/Row")[:3]:
for value in row.findall("Value"):
column_id = value.get("ColumnRef")
simple_value = value.find("./SimpleValue")
if simple_value is None:
continue
example_values[column_id].append(simple_value.text)
filterable_columns = {k: list(v) for k, v in filterable_columns.items() if len(v) <= 5}
return columns, example_values, filterable_columns

View File

@@ -0,0 +1,8 @@
frappe.listview_settings["Code List"] = {
onload: function (listview) {
listview.page.add_inner_button(__("Import Genericode File"), function () {
erpnext.edi.import_genericode(listview);
});
},
hide_name_column: true,
};

View File

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

View File

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

View File

@@ -0,0 +1,103 @@
{
"actions": [],
"autoname": "hash",
"creation": "2024-09-29 07:01:18.133067",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"code_list",
"title",
"common_code",
"description",
"column_break_wxsw",
"additional_data",
"section_break_rhgh",
"applies_to"
],
"fields": [
{
"fieldname": "code_list",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Code List",
"options": "Code List",
"reqd": 1,
"search_index": 1
},
{
"fieldname": "title",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Title",
"length": 300,
"reqd": 1
},
{
"fieldname": "column_break_wxsw",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_rhgh",
"fieldtype": "Section Break"
},
{
"fieldname": "applies_to",
"fieldtype": "Table",
"label": "Applies To",
"options": "Dynamic Link"
},
{
"fieldname": "common_code",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Common Code",
"length": 300,
"reqd": 1,
"search_index": 1
},
{
"fieldname": "additional_data",
"fieldtype": "Code",
"label": "Additional Data",
"max_height": "190px",
"read_only": 1
},
{
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Description",
"max_height": "60px"
}
],
"links": [],
"modified": "2024-11-06 07:46:17.175687",
"modified_by": "Administrator",
"module": "EDI",
"name": "Common Code",
"naming_rule": "Random",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"search_fields": "common_code,description",
"show_title_field_in_link": 1,
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"title_field": "title"
}

View File

@@ -0,0 +1,114 @@
# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
import hashlib
import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils.data import get_link_to_form
from lxml import etree
class CommonCode(Document):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from frappe.core.doctype.dynamic_link.dynamic_link import DynamicLink
from frappe.types import DF
additional_data: DF.Code | None
applies_to: DF.Table[DynamicLink]
code_list: DF.Link
common_code: DF.Data
description: DF.SmallText | None
title: DF.Data
# end: auto-generated types
def validate(self):
self.validate_distinct_references()
def validate_distinct_references(self):
"""Ensure no two Common Codes of the same Code List are linked to the same document."""
for link in self.applies_to:
existing_links = frappe.get_all(
"Common Code",
filters=[
["name", "!=", self.name],
["code_list", "=", self.code_list],
["Dynamic Link", "link_doctype", "=", link.link_doctype],
["Dynamic Link", "link_name", "=", link.link_name],
],
fields=["name", "common_code"],
)
if existing_links:
existing_link = existing_links[0]
frappe.throw(
_("{0} {1} is already linked to Common Code {2}.").format(
link.link_doctype,
link.link_name,
get_link_to_form("Common Code", existing_link["name"], existing_link["common_code"]),
)
)
def from_genericode(self, column_map: dict, xml_element: "etree.Element"):
"""Populate the Common Code document from a genericode XML element
Args:
column_map (dict): A mapping of column names to XML column references. Keys: code, title, description
code (etree.Element): The XML element representing a code in the genericode file
"""
title_column = column_map.get("title")
code_column = column_map["code"]
description_column = column_map.get("description")
self.common_code = xml_element.find(f"./Value[@ColumnRef='{code_column}']/SimpleValue").text
if title_column:
simple_value_title = xml_element.find(f"./Value[@ColumnRef='{title_column}']/SimpleValue")
self.title = simple_value_title.text if simple_value_title is not None else self.common_code
if description_column:
simple_value_descr = xml_element.find(f"./Value[@ColumnRef='{description_column}']/SimpleValue")
self.description = simple_value_descr.text if simple_value_descr is not None else None
self.additional_data = etree.tostring(xml_element, encoding="unicode", pretty_print=True)
def simple_hash(input_string, length=6):
return hashlib.blake2b(input_string.encode(), digest_size=length // 2).hexdigest()
def import_genericode(code_list: str, file_name: str, column_map: dict, filters: dict | None = None):
"""Import genericode file and create Common Code entries"""
file_path = frappe.utils.file_manager.get_file_path(file_name)
parser = etree.XMLParser(remove_blank_text=True)
tree = etree.parse(file_path, parser=parser)
root = tree.getroot()
# Construct the XPath expression
xpath_expr = ".//SimpleCodeList/Row"
filter_conditions = [
f"Value[@ColumnRef='{column_ref}']/SimpleValue='{value}'" for column_ref, value in filters.items()
]
if filter_conditions:
xpath_expr += "[" + " and ".join(filter_conditions) + "]"
elements = root.xpath(xpath_expr)
total_elements = len(elements)
for i, xml_element in enumerate(elements, start=1):
common_code: "CommonCode" = frappe.new_doc("Common Code")
common_code.code_list = code_list
common_code.from_genericode(column_map, xml_element)
common_code.save()
frappe.publish_progress(i / total_elements * 100, title=_("Importing Common Codes"))
return total_elements
def on_doctype_update():
frappe.db.add_index("Common Code", ["code_list", "common_code"])

View File

@@ -0,0 +1,8 @@
frappe.listview_settings["Common Code"] = {
onload: function (listview) {
listview.page.add_inner_button(__("Import Genericode File"), function () {
erpnext.edi.import_genericode(listview);
});
},
hide_name_column: true,
};

View File

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

View File

@@ -35,6 +35,14 @@ doctype_js = {
"Newsletter": "public/js/newsletter.js",
"Contact": "public/js/contact.js",
}
doctype_list_js = {
"Code List": [
"edi/doctype/code_list/code_list_import.js",
],
"Common Code": [
"edi/doctype/code_list/code_list_import.js",
],
}
override_doctype_class = {"Address": "erpnext.accounts.custom.address.ERPNextAddress"}

View File

@@ -742,11 +742,8 @@ class BOM(WebsiteGenerator):
base_total_rm_cost = 0
for d in self.get("items"):
if not d.is_stock_item and self.rm_cost_as_per == "Valuation Rate":
continue
old_rate = d.rate
if not self.bom_creator:
if not self.bom_creator and d.is_stock_item:
d.rate = self.get_rm_rate(
{
"company": self.company,
@@ -968,6 +965,13 @@ class BOM(WebsiteGenerator):
if not d.batch_size or d.batch_size <= 0:
d.batch_size = 1
if not d.workstation and not d.workstation_type:
frappe.throw(
_(
"Row {0}: Workstation or Workstation Type is mandatory for an operation {1}"
).format(d.idx, d.operation)
)
def get_tree_representation(self) -> BOMTree:
"""Get a complete tree representation preserving order of child items."""
return BOMTree(self.name)

View File

@@ -37,7 +37,7 @@ frappe.ui.form.on("Job Card", {
frappe.flags.resume_job = 0;
let has_items = frm.doc.items && frm.doc.items.length;
if (!frm.is_new() && frm.doc.__onload.work_order_closed) {
if (!frm.is_new() && frm.doc.__onload?.work_order_closed) {
frm.disable_save();
return;
}

View File

@@ -941,26 +941,19 @@ class JobCard(Document):
qty = 0
if self.work_order:
doc = frappe.get_doc("Work Order", self.work_order)
if doc.transfer_material_against == "Job Card" and not doc.skip_transfer:
completed = True
min_qty = []
for d in doc.operations:
if d.status != "Completed":
completed = False
if d.completed_qty:
min_qty.append(d.completed_qty)
else:
min_qty = []
break
if completed:
job_cards = frappe.get_all(
"Job Card",
filters={"work_order": self.work_order, "docstatus": ("!=", 2)},
fields="sum(transferred_qty) as qty",
group_by="operation_id",
)
if min_qty:
qty = min(min_qty)
if job_cards:
qty = min(d.qty for d in job_cards)
doc.db_set("material_transferred_for_manufacturing", qty)
doc.db_set("material_transferred_for_manufacturing", qty)
self.set_status(update_status)

View File

@@ -87,17 +87,17 @@ frappe.ui.form.on("Production Plan", {
if (frm.doc.docstatus === 1) {
frm.trigger("show_progress");
if (frm.doc.status !== "Completed") {
frm.add_custom_button(
__("Production Plan Summary"),
() => {
frappe.set_route("query-report", "Production Plan Summary", {
production_plan: frm.doc.name,
});
},
__("View")
);
frm.add_custom_button(
__("Production Plan Summary"),
() => {
frappe.set_route("query-report", "Production Plan Summary", {
production_plan: frm.doc.name,
});
},
__("View")
);
if (frm.doc.status !== "Completed") {
if (frm.doc.status === "Closed") {
frm.add_custom_button(
__("Re-open"),

View File

@@ -173,10 +173,16 @@ class WorkOrder(Document):
self.get_items_and_operations_from_bom()
def validate_workstation_type(self):
if not self.docstatus.is_submitted():
return
for row in self.operations:
if not row.workstation and not row.workstation_type:
msg = f"Row {row.idx}: Workstation or Workstation Type is mandatory for an operation {row.operation}"
frappe.throw(_(msg))
frappe.throw(
_("Row {0}: Workstation or Workstation Type is mandatory for an operation {1}").format(
row.idx, row.operation
)
)
def validate_sales_order(self):
if self.sales_order:

View File

@@ -27,32 +27,51 @@ def get_data(filters):
def get_production_plan_item_details(filters, data, order_details):
itemwise_indent = {}
production_plan_doc = frappe.get_cached_doc("Production Plan", filters.get("production_plan"))
for row in production_plan_doc.po_items:
work_order = frappe.get_value(
work_orders = frappe.get_all(
"Work Order",
{"production_plan_item": row.name, "bom_no": row.bom_no, "production_item": row.item_code},
"name",
filters={
"production_plan_item": row.name,
"bom_no": row.bom_no,
"production_item": row.item_code,
},
pluck="name",
)
if row.item_code not in itemwise_indent:
itemwise_indent.setdefault(row.item_code, {})
order_qty = row.planned_qty
total_produced_qty = 0.0
pending_qty = 0.0
for work_order in work_orders:
produced_qty = flt(order_details.get((work_order, row.item_code), {}).get("produced_qty", 0))
pending_qty = flt(order_qty) - produced_qty
total_produced_qty += produced_qty
data.append(
{
"indent": 0,
"item_code": row.item_code,
"sales_order": row.get("sales_order"),
"item_name": frappe.get_cached_value("Item", row.item_code, "item_name"),
"qty": order_qty,
"document_type": "Work Order",
"document_name": work_order or "",
"bom_level": 0,
"produced_qty": produced_qty,
"pending_qty": pending_qty,
}
)
order_qty = pending_qty
data.append(
{
"indent": 0,
"item_code": row.item_code,
"sales_order": row.get("sales_order"),
"item_name": frappe.get_cached_value("Item", row.item_code, "item_name"),
"indent": 0,
"qty": row.planned_qty,
"document_type": "Work Order",
"document_name": work_order or "",
"bom_level": 0,
"produced_qty": order_details.get((work_order, row.item_code), {}).get("produced_qty", 0),
"pending_qty": flt(row.planned_qty)
- flt(order_details.get((work_order, row.item_code), {}).get("produced_qty", 0)),
"produced_qty": total_produced_qty,
"pending_qty": pending_qty,
}
)

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