Compare commits

..

421 Commits

Author SHA1 Message Date
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
mergify[bot]
8c8dc241e5 fix: bom cost update is not working (backport #43155) (#43157)
fix: bom cost update is not working (#43155)

(cherry picked from commit 05f9015c0b)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-09-10 23:07:07 +05:30
mergify[bot]
c9f49caecc perf: timeout error (backport #43154) (#43158)
perf: timeout error (#43154)

(cherry picked from commit 1bf60248d9)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-09-10 23:06:38 +05:30
mergify[bot]
cd57e009dd fix: concurrency issue while picking materials (backport #43087) (#43152)
fix: concurrency issue while picking materials (#43087)

(cherry picked from commit 5c7dff0e84)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-09-10 17:01:53 +05:30
ruthra kumar
f11e298984 Merge pull request #43149 from frappe/mergify/bp/version-15-hotfix/pr-43146
fix: permission error on Payment Request creation by Guest (backport #43146)
2024-09-10 16:00:00 +05:30
Khushi Rawat
2eec0c057a Merge pull request #43140 from frappe/mergify/bp/version-15-hotfix/pr-43114
fix: primary action button not showing (backport #43114)
2024-09-10 15:45:09 +05:30
ruthra kumar
50b4257a6f Merge pull request #43148 from frappe/mergify/bp/version-15-hotfix/pr-43144
feat: utility report for identifying invalid ledger entries (backport #43144)
2024-09-10 14:55:03 +05:30
ruthra kumar
a23e8b13be fix: permission on guest PR creation
(cherry picked from commit ea02e5f15a)
2024-09-10 09:18:23 +00:00
ruthra kumar
9f09bf14cb refactor: allow all accounts
(cherry picked from commit 43198c946b)
2024-09-10 09:07:06 +00:00
ruthra kumar
5413372aeb refactor: fetch as dictionary
(cherry picked from commit 2126b10a92)
2024-09-10 09:07:06 +00:00
ruthra kumar
710d30074d refactor: barebones methods with basic logic
(cherry picked from commit b05b378ef0)
2024-09-10 09:07:06 +00:00
ruthra kumar
14e30d12b4 refactor: standard filters
(cherry picked from commit dccbc1f432)
2024-09-10 09:07:06 +00:00
ruthra kumar
5929d50c72 feat: utility report to identify invalid ledger entries
(cherry picked from commit 832c4aaf82)
2024-09-10 09:07:06 +00:00
mergify[bot]
d2923bae85 fix: return type of get_party_details (backport #43131) (#43134)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
fix: return type of `get_party_details` (#43131)
2024-09-09 19:26:38 +02:00
Khushi Rawat
9e72a844f7 fix: pass company from asset to asset capitalization
(cherry picked from commit f3445d645d)
2024-09-09 17:00:01 +00:00
Khushi Rawat
208bd2b8ff fix: unhide action button after form redirect
(cherry picked from commit 5ce5b1b6a2)
2024-09-09 17:00:01 +00:00
mergify[bot]
5110975c6d fix: incorrect actual cost in Procurement Tracker report (backport #43109) (#43138)
fix: incorrect actual cost in Procurement Tracker report (#43109)

(cherry picked from commit 80f101f92e)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-09-09 20:34:56 +05:30
ruthra kumar
82764af09e Merge pull request #43132 from frappe/mergify/bp/version-15-hotfix/pr-43056
fix(Opening Invoice Creation Tool): translatability of messages (backport #43056)
2024-09-09 16:54:08 +05:30
barredterra
3fd9df0d2e fix(Opening Invoice Creation Tool): translatability of messages
(cherry picked from commit f3c5803198)
2024-09-09 09:48:34 +00:00
ruthra kumar
cf81202d94 Merge pull request #43129 from frappe/mergify/bp/version-15-hotfix/pr-42801
fix(Delivery Note): translatability of validation errors (backport #42801)
2024-09-09 15:15:45 +05:30
barredterra
0c0f103b83 refactor: extract common validation method
(cherry picked from commit 08646b7ab7)
2024-09-09 09:14:23 +00:00
barredterra
ea4f7365ea fix(Delivery Note): translatability of validation errors
(cherry picked from commit 34df6e39dc)
2024-09-09 09:14:23 +00:00
ruthra kumar
346c06977c Merge pull request #43127 from frappe/mergify/bp/version-15-hotfix/pr-43051
fix: unreconcile allocation child table redirect url voucher no issue (backport #43051)
2024-09-09 14:38:17 +05:30
Prashant Kamble
2dddd7906b fix: unreconcile allocation child table redirect url voucher no issue
(cherry picked from commit 5d6f6a2fb9)
2024-09-09 09:00:37 +00:00
ruthra kumar
026c2d7590 Merge pull request #43122 from frappe/mergify/bp/version-15-hotfix/pr-43022
feat: added revaluation surplus and impairment acc in standard charts… (backport #43022)
2024-09-09 14:19:34 +05:30
ruthra kumar
8e5252d6f8 Merge pull request #43125 from frappe/mergify/bp/version-15-hotfix/pr-43064
fix: validate the item code when updating the other item's price rule (backport #43064)
2024-09-09 14:16:49 +05:30
ruthra kumar
ffc119a8a4 Merge pull request #43123 from frappe/mergify/bp/version-15-hotfix/pr-43121
fix: set today in 'On This Date' in Available Batch Report (backport #43121)
2024-09-09 14:14:19 +05:30
Bhavan23
8f4dc8048d fix: validate the item code when updating the other item's price rule
(cherry picked from commit 45de18069c)
2024-09-09 08:43:58 +00:00
Nihantra C. Patel
03e3374a8b fix: set today in 'On This Date' in Available Batch Report
(cherry picked from commit 9fd55e4c83)
2024-09-09 08:26:38 +00:00
rahulgupta8848
ea86bc2235 feat: added revaluation surplus and impairment acc in standard charts… (#43022)
feat: added revaluation surplus and impairment acc in standard charts of accounts

Co-authored-by: “rahulgupta8848” <“rahul.gupta@8848digital.com”>
(cherry picked from commit 8202f505cc)
2024-09-09 06:43:00 +00:00
ruthra kumar
60b81a2a59 Merge pull request #43120 from frappe/mergify/bp/version-15-hotfix/pr-43095
fix: check multi-currency on jv for common party accounting with foreign currency (backport #43095)
2024-09-09 11:17:43 +05:30
ruthra kumar
354c34e4d8 chore: resolve conflict 2024-09-09 10:51:45 +05:30
ruthra kumar
a9bd11f59a refactor(test): use change_settings decorator
(cherry picked from commit ee94fb37c8)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
2024-09-09 05:06:38 +00:00
venkat102
33174b1ba2 fix: uncomment internal parties
(cherry picked from commit 454e18ad5f)
2024-09-09 05:06:38 +00:00
venkat102
47b216373d test: add unit test for common party with foreign currency
(cherry picked from commit 740a04a704)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
2024-09-09 05:06:38 +00:00
venkat102
d17baddb0d fix: check multi-currency on jv for common party accounting with foreign currency
(cherry picked from commit 00938bfd4d)
2024-09-09 05:06:38 +00:00
mergify[bot]
80b5c16a2e fix: Cannot read properties of null (reading 'doc') (backport #43071) (#43118)
fix: Cannot read properties of null (reading 'doc')

(cherry picked from commit 62c3389bd6)

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2024-09-09 09:56:29 +05:30
Smit Vora
a9b142eccd Merge pull request #43117 from frappe/mergify/bp/version-15-hotfix/pr-42753
fix: multiple fixes related to remarks for GL Report (backport #42753)
2024-09-09 08:00:45 +05:30
Smit Vora
a66d1c30ae Merge pull request #43116 from frappe/mergify/bp/version-15-hotfix/pr-42816
fix: ensure `SellingController.onload` gets called for SO & DN (backport #42816)
2024-09-09 08:00:33 +05:30
Smit Vora
c379b783b1 Merge pull request #43092 from frappe/mergify/bp/version-15-hotfix/pr-43013
fix: `default_advance_account` field in Process Payment Reconciliation (backport #43013)
2024-09-09 08:00:07 +05:30
Smit Vora
f45b1db1a4 fix: multiple fixes related to remarks for GL Report (#42753)
* fix: show remarks in report only if it exists

* fix: additional fixes to reduce redundancy in report print format

* fix: revert changes for supplier invoice reference

* fix: update remarks before submit to ensure all available details before submit are used

* fix: patch to update invoice remarks where it's not set

* fix: update remarks in payment ledger entry

(cherry picked from commit e5a49f738b)
2024-09-09 01:54:40 +00:00
Smit Vora
a69623c131 Merge pull request #43115 from frappe/mergify/bp/version-15-hotfix/pr-42736
refactor: age range in one field (backport #42736)
2024-09-09 07:14:18 +05:30
Sagar Vora
2c1f72e44c fix: ensure SellingController.onload gets called for SO & DN
(cherry picked from commit 8431e3c275)
2024-09-09 01:44:17 +00:00
Smit Vora
3915018400 chore: resolve conflicts with backport 2024-09-09 07:00:32 +05:30
Sanket322
b832b60b28 refactor: age range in one field (#42736)
* fix: age range in one field

* fix: patch for custom reports

* refactor: stock ageing and account payable report

* fix: fixing the test cases

* fix: common patch for reports with ageing

* refactor: rename variable and minor refactor

* fix: fixing the test case

(cherry picked from commit 05de8994b0)
2024-09-09 01:20:13 +00:00
Khushi Rawat
b70eb46222 Merge pull request #43099 from frappe/mergify/bp/version-15-hotfix/pr-43098
fix(minor): reorder expected value validation (backport #43098)
2024-09-08 23:38:07 +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
mergify[bot]
8447bf34f0 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>
2024-09-07 17:32:42 +05:30
Khushi Rawat
6fde07da0e fix(minor): reorder expected value validation
(cherry picked from commit 0a6bf1559b)
2024-09-06 18:44:41 +00:00
ruthra kumar
6bd95a6d17 Merge pull request #43097 from frappe/mergify/bp/version-15-hotfix/pr-43077
fix: cancel common party advance jv while canceling the invoice (backport #43077)
2024-09-06 20:41:20 +05:30
venkat102
6c74180e1c test: add unit test for canceling the common party advance jv created from sales invoice
(cherry picked from commit 8c6e3f3c12)
2024-09-06 14:50:08 +00:00
venkat102
9bd3d7a020 fix: cancel common party advance jv while canceling the invoice
(cherry picked from commit 6a928b92df)
2024-09-06 14:50:07 +00:00
ruthra kumar
84b0fa38d5 refactor: fetch advance account on party seleection
(cherry picked from commit c4ed04cb31)
2024-09-06 09:48:47 +00:00
ljain112
75cb29890d fix: default_advance_account field in Process Payment Reconciliation
(cherry picked from commit 143209f91a)

# Conflicts:
#	erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.json
2024-09-06 09:48:47 +00:00
ruthra kumar
c31b4e6b4b Merge pull request #43074 from frappe/mergify/bp/version-15-hotfix/pr-43070
fix: AP filter to simulate employee advance as a ledger impacting voucher (backport #43070)
2024-09-06 10:09:30 +05:30
ruthra kumar
cb64f90d7d chore: resolve conflict 2024-09-05 17:22:47 +05:30
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
efdc2173b2 refactor: filter to toggle employee advance scenario in AP
(cherry picked from commit 257e13c299)

# Conflicts:
#	erpnext/accounts/report/accounts_payable/accounts_payable.js
2024-09-05 11:44:04 +00:00
ruthra kumar
99828d945f refactor: Handle Emp Advance as separate row in AP report
(cherry picked from commit eedf22b07a)
2024-09-05 11:44:03 +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
mergify[bot]
d2b2002664 fix: auto reorder material request mail issue (backport #43066) (#43068)
fix: auto reorder material request mail issue (#43066)

fix: auto reorder matreial request mail issue
(cherry picked from commit a8055a6da9)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-09-05 16:00:47 +05:30
mergify[bot]
56dad7d365 fix: disabled batches showing in the list (backport #43024) (#43069)
fix: disabled batches showing in the list (#43024)

(cherry picked from commit c13a147df1)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-09-05 16:00:33 +05:30
Khushi Rawat
6869e5dde9 Merge pull request #43039 from khushi8112/backport-asset-value-through-landed-cost-voucher
fix: backport asset value through landed cost voucher
2024-09-05 14:53:51 +05:30
Khushi Rawat
5d5ec2ab7c chore: resolve test failing 2024-09-05 14:31:05 +05:30
Khushi Rawat
f5a4ec129b chore: patch correction 2024-09-05 14:31:05 +05:30
Khushi Rawat
e185a06a15 refactor: rename to in SLE query functions 2024-09-05 14:31:05 +05:30
Khushi Rawat
193d7981ea chore: linters/semgrep check 2024-09-05 14:31:05 +05:30
Khushi Rawat
957eabf53e chore: resolved linter warnings with #nosemgrep 2024-09-05 14:31:05 +05:30
Khushi Rawat
3bb186736d fix: improve asset item matching logic 2024-09-05 14:31:05 +05:30
Khushi Rawat
1121c6663f fix: link Purchase Invoice and Receipt Items to Asset 2024-09-05 14:31:05 +05:30
Smit Vora
944479313c Merge pull request #43046 from frappe/mergify/bp/version-15-hotfix/pr-42988
fix: adjust price insertion logic for internal suppliers/customers (backport #42988)
2024-09-04 13:19:52 +05:30
Lakshit Jain
daa75eea00 fix: adjust price insertion logic for internal suppliers/customers (#42988)
* fix: adjust price insertion logic for internal suppliers/customers

* refactor: correct indentation, specify conditions within function

* fix: typo

---------

Co-authored-by: Smit Vora <smitvora203@gmail.com>
(cherry picked from commit 38f925b376)
2024-09-04 07:27:47 +00:00
ruthra kumar
a2b7fc18ab Merge pull request #43033 from frappe/mergify/bp/version-15-hotfix/pr-43030
fix: typerror on default_currency (backport #43030)
2024-09-03 16:51:22 +05:30
ruthra kumar
7d6984c873 fix: typerror on default_currency
(cherry picked from commit 4a7cc4da87)
2024-09-03 11:11:29 +00:00
Nihantra C. Patel
64cbf446bd Merge pull request #43031 from frappe/mergify/bp/version-15-hotfix/pr-43029
fix: move setup_queries to refresh event for company (backport #43029)
2024-09-03 16:12:27 +05:30
Nihantra C. Patel
b99cdb5be7 fix: company accounts setup_queries
(cherry picked from commit 80ace72541)
2024-09-03 10:36:29 +00:00
ruthra kumar
d6de50634f Merge pull request #43028 from frappe/mergify/bp/version-15-hotfix/pr-42974
fix: retain date filter when redirecting in Profit and Loss report (backport #42974)
2024-09-03 15:51:46 +05:30
vishnu
4d7c0c004a fix: indentation
(cherry picked from commit 598e9c1390)
2024-09-03 10:14:32 +00:00
vishnu
f0e3fb466a fix: retain date filter when redirecting in Profit and Loss report
(cherry picked from commit bb29fc4c3d)
2024-09-03 10:14:31 +00:00
Khushi Rawat
8337439589 Merge pull request #43018 from frappe/mergify/bp/version-15-hotfix/pr-43015
chore: test case failing issue (backport #43015)
2024-09-03 03:55:32 +05:30
Khushi Rawat
88e5ed7998 chore: test case failing issue
(cherry picked from commit 0bdffdfa98)
2024-09-02 22:09:22 +00:00
mergify[bot]
fee2255661 fix: validate component quantity according to BOM (backport #43011) (#43014)
* fix: validate component quantity according to BOM (#43011)

(cherry picked from commit f3b91d4d62)

# Conflicts:
#	erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-09-02 16:29:30 +05:30
Nihantra C. Patel
23d91145d0 Merge pull request #43009 from frappe/mergify/bp/version-15-hotfix/pr-43008
fix: update develop_version in hooks (backport #43008)
2024-09-02 12:21:03 +05:30
Nihantra C. Patel
6c8e0fd1fb fix: update develop_version in hooks
(cherry picked from commit 01b345e046)
2024-09-02 06:13:37 +00:00
Shariq Ansari
512a171ad5 Merge pull request #42994 from frappe/mergify/bp/version-15-hotfix/pr-42993
fix: added app permission check for apps page (backport #42993)
2024-08-30 18:05:55 +05:30
Shariq Ansari
30f034555b chore: linter fix
(cherry picked from commit 1d9ed27a89)
2024-08-30 12:06:10 +00:00
Shariq Ansari
a35ce12d60 fix: added app permission check for apps page
(cherry picked from commit e8f8fb8a8f)
2024-08-30 12:06:10 +00:00
Khushi Rawat
8cf057849e Merge pull request #42986 from frappe/mergify/bp/version-15-hotfix/pr-42857
fix(capitalization): debit cwip account instead of fixed asset account (backport #42857)
2024-08-30 00:46:06 +05:30
Khushi Rawat
f3c60ea0a7 fix(capitalization): debit cwip account instead of fixed asset account (#42857)
* fix(capitalization): debit cwip account instead of fixed asset account

* fix: post entries for capitalized asset through background jobs

* chore: run pre-commit

* fix: correct GL entries posting for composite assets

* fix(minor): resolve failing check

* chore: update gl entry check logic

* chore: handle none values

(cherry picked from commit 5d99f17583)
2024-08-29 11:01:03 +00:00
ruthra kumar
c724573a18 Merge pull request #42985 from frappe/mergify/bp/version-15-hotfix/pr-42983
refactor: link utility report with bank reconciliation statement (backport #42983)
2024-08-29 16:19:47 +05:30
ruthra kumar
53e1b57354 refactor: link utility report with bank reconciliation statement
(cherry picked from commit 00eac65712)
2024-08-29 10:42:57 +00:00
mergify[bot]
42e7725442 fix: add the company in payment request bcz delete company transactions (backport #42664) (#42982)
* fix: add the company in payment request bcz delete company transactions

(cherry picked from commit 12834ccf9a)

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

* fix: link company when make payment request

(cherry picked from commit e3008843d1)

* fix: add the company in payment request bcz delete company transactions --conflicts

---------

Co-authored-by: Nihantra Patel <nihantra@frappe.io>
Co-authored-by: Nihantra C. Patel <141945075+Nihantra-Patel@users.noreply.github.com>
2024-08-29 15:41:08 +05:30
ruthra kumar
18b7af977c Merge pull request #42981 from frappe/mergify/bp/version-15-hotfix/pr-42979
refactor: better UX on Bank Clearance tool (backport #42979)
2024-08-29 14:07:49 +05:30
ruthra kumar
db746a4def refactor: better UX on Bank Clearance tool
(cherry picked from commit 6a06e26d04)
2024-08-29 08:25:12 +00:00
Khushi Rawat
3d5fb5fc90 Merge pull request #42977 from frappe/mergify/bp/version-15-hotfix/pr-42976
fix: don't allow capitalizing only service item for new composite asset (backport #42976)
2024-08-29 11:47:28 +05:30
Khushi Rawat
a833010d2b fix: don't allow capitalizing only service item for new composite asset
(cherry picked from commit f1d2138258)
2024-08-28 20:43:15 +00:00
ruthra kumar
0d6148f218 Merge pull request #42968 from frappe/mergify/bp/version-15-hotfix/pr-42966
fix: typeerror on Payment Entry (backport #42966)
2024-08-28 13:21:32 +05:30
ruthra kumar
6d51d14dfd fix: typeerror on Payment Entry
(cherry picked from commit e9cf8937cd)
2024-08-28 06:58:04 +00:00
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
ruthra kumar
2a820a85ed Merge pull request #42952 from frappe/mergify/bp/version-15-hotfix/pr-41925
fix: spec mobile and email fields for notifications (backport #41925)
2024-08-28 10:13:26 +05:30
mergify[bot]
8d8dd0cd2b feat: Disassembly Order (backport #42655) (#42957)
* feat: Disassembly Order (#42655)

(cherry picked from commit 663a08e4cd)

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

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-27 23:07:37 +05:30
ruthra kumar
3a5f19853a Merge pull request #42947 from frappe/mergify/bp/version-15-hotfix/pr-42923
fix: get amount with taxes and charges from payment entry (backport #42923)
2024-08-27 17:39:30 +05:30
Khushi Rawat
c0dd794e15 Merge pull request #42944 from frappe/mergify/bp/version-15-hotfix/pr-42939
feat: added finance book filter in depreciation and balances report (backport #42939)
2024-08-27 17:18:10 +05:30
David
f56ee58e81 fix: spec mobile and email fields for notifications
(cherry picked from commit 18993a97ce)
2024-08-27 11:45:40 +00:00
mergify[bot]
2c99075899 fix: Cannot read properties of null (reading 'doctype') (backport #42941) (#42943)
fix: Cannot read properties of null (reading 'doctype') (#42941)

(cherry picked from commit 86d3a9ab03)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-27 17:15:23 +05:30
ruthra kumar
01cd509113 Merge pull request #42950 from frappe/mergify/bp/version-15-hotfix/pr-41949
refactor: item-wise purchase history (query to script report) (backport #41949)
2024-08-27 17:11:46 +05:30
ruthra kumar
5563bea789 Merge pull request #42949 from frappe/mergify/bp/version-15-hotfix/pr-42936
fix: remove unnecessary condition on 'voucher_no' (backport #42936)
2024-08-27 17:08:56 +05:30
Nihantra Patel
a0a932a235 refactor: item-wise purchase history (query to script report) --upd
(cherry picked from commit 2851764ed6)
2024-08-27 11:19:03 +00:00
Nihantra Patel
6f75a3c617 refactor: item-wise purchase history (query to script report) --prettier
(cherry picked from commit 7bae18aba8)
2024-08-27 11:19:03 +00:00
Nihantra Patel
a4d3934f75 refactor: item-wise purchase history (query to script report) --prettier
(cherry picked from commit f740c94363)
2024-08-27 11:19:03 +00:00
Nihantra Patel
b4171e4bd9 refactor: item-wise purchase history (query to script report) -- formatter
(cherry picked from commit 003a9608dc)
2024-08-27 11:19:03 +00:00
Nihantra Patel
76d32ab07a refactor: item-wise purchase history (query to script report)
(cherry picked from commit 49331e6109)
2024-08-27 11:19:03 +00:00
Nihantra Patel
3d469db47b refactor: item-wise purchase history (query to script report)
(cherry picked from commit 5de91cf55e)
2024-08-27 11:19:02 +00:00
ruthra kumar
80244bafa4 fix: use of incorrect attribute
(cherry picked from commit fb32d2cafb)
2024-08-27 11:06:38 +00:00
venkat102
c54e97b89a fix: get amount with taxes and charges from payment entry
(cherry picked from commit b3a901b631)
2024-08-27 11:01:36 +00:00
ruthra kumar
14202fae06 Merge pull request #42453 from mujeerhashmi/patch-2
fix: Update get_amount to return currency precision grand total
2024-08-27 16:29:08 +05:30
Khushi Rawat
9fc0ac1a92 chore: resolved linter warnings with #nosemgrep
(cherry picked from commit adf1e487e1)
2024-08-27 10:54:11 +00:00
Khushi Rawat
5bdd2989c6 feat: added finance book filter in depreciation and balances report
(cherry picked from commit 45804c68f0)
2024-08-27 10:54:10 +00:00
ruthra kumar
42dccadff1 Merge pull request #42940 from frappe/mergify/bp/version-15-hotfix/pr-42921
fix: make party naming sequential when naming_by set as auto name (backport #42921)
2024-08-27 16:13:00 +05:30
venkat102
0650c22b53 fix: make party naming sequential when naming_by set as auto name
(cherry picked from commit c9015f7c04)
2024-08-27 10:07:50 +00:00
mergify[bot]
ec26c92263 fix: timeout while submitting stock entry (backport #42929) (#42931)
fix: timeout while submitting stock entry (#42929)

(cherry picked from commit ca2fde891e)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-27 11:03:45 +05:30
mergify[bot]
26248924b6 fix: same posting date and time, creation causing incorrect balance qty (backport #42904) (#42920)
fix: same posting date and time, creation causing incorrect balance qty (#42904)

fix: same posting date and time, creation causing incorrect balance quantity
(cherry picked from commit 27364b7e6b)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-27 09:30:47 +05:30
mergify[bot]
8d29dc6a81 fix: unsupported operand type(s) for *: 'float' and 'NoneType' (backport #42916) (#42918)
fix: unsupported operand type(s) for *: 'float' and 'NoneType' (#42916)

(cherry picked from commit 10434742e9)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-26 18:18:31 +05:30
ruthra kumar
6eb50fa300 Merge pull request #42915 from frappe/mergify/bp/version-15-hotfix/pr-42887
fix: update dimesions in exchange_gain_loss jv based on base document (backport #42887)
2024-08-26 17:56:21 +05:30
mergify[bot]
8c350d43b2 fix: Column 'valuation_rate' cannot be null (backport #42909) (#42913)
fix: Column 'valuation_rate' cannot be null (#42909)

(cherry picked from commit 92bde71ab1)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-26 17:35:20 +05:30
ljain112
caa6ca1d0b fix: update dimesions in exchange_gain_loss jv based on base document
(cherry picked from commit 96df19149d)
2024-08-26 12:01:28 +00:00
ruthra kumar
47f1714be4 Merge pull request #42912 from frappe/mergify/bp/version-15-hotfix/pr-42910
feat: utility report to better diagnose incorrectly cleared Cheques and Deposits (backport #42910)
2024-08-26 16:32:29 +05:30
ruthra kumar
ecb0506dba refactor: build dictionary for Journal
remove redundant filter

(cherry picked from commit 2144e0337d)
2024-08-26 10:11:24 +00:00
ruthra kumar
42382b3945 chore: remove redundant column
(cherry picked from commit 74b36db24e)
2024-08-26 10:11:23 +00:00
ruthra kumar
993114942e refactor: build dict for payment entry
(cherry picked from commit 784dec24c8)
2024-08-26 10:11:23 +00:00
ruthra kumar
5a28a1728e refactor: working state with minimum functions
(cherry picked from commit 4cd023444a)
2024-08-26 10:11:23 +00:00
ruthra kumar
80a5df0e96 refactor: barebones functions
(cherry picked from commit ceaa1be729)
2024-08-26 10:11:23 +00:00
ruthra kumar
25193c5e92 feat: report to identify incorrectly cleared cheques
(cherry picked from commit 28890fa833)
2024-08-26 10:11:23 +00:00
ruthra kumar
1ee14ac135 Merge pull request #42907 from frappe/mergify/bp/version-15-hotfix/pr-42905
refactor: better err msg on clearance tool (backport #42905)
2024-08-26 15:29:48 +05:30
ruthra kumar
a3e5ffe915 refactor: better err msg on clearance tool
(cherry picked from commit 092411b54f)
2024-08-26 08:55:01 +00:00
mergify[bot]
ff868a9290 fix: LCV based on purchase invoice amount with multi-currency (backport #42890) (#42894)
fix: LCV based on purchase invoice amount with multi-currency (#42890)

(cherry picked from commit 6721ae76de)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-26 13:25:18 +05:30
Smit Vora
247ae7a965 Merge pull request #42892 from frappe/mergify/bp/version-15-hotfix/pr-42848
fix: do not copy date fields in opportunity doctype (backport #42848)
2024-08-24 13:12:13 +05:30
Smit Vora
3a149b3c9b chore: resolve conflicts 2024-08-24 12:38:49 +05:30
mergify[bot]
08bed618f6 fix: not able to make stock entry against MR (backport #42874) (#42875)
fix: not able to make stock entry against MR (#42874)

(cherry picked from commit 63ca1025bc)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-23 15:22:39 +05:30
mergify[bot]
d9ca680a29 fix: incorrect in and out qty in the Batch-Wise Balance History (backport #42866) (#42876)
fix: incorrect in and out qty in the Batch-Wise Balance History (#42866)

(cherry picked from commit ce7f6ee71c)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-23 15:22:23 +05:30
ljain112
7401dc4015 fix: do not copy date fields in opportunity doctype
(cherry picked from commit 74afa57a9f)

# Conflicts:
#	erpnext/crm/doctype/opportunity/opportunity.json
2024-08-23 08:48:33 +00:00
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
ruthra kumar
85089d3d64 Merge pull request #42871 from frappe/mergify/bp/version-15-hotfix/pr-42867
fix: call 'process' directly instead of creating 'process_subscription' (backport #42867)
2024-08-22 17:51:37 +05:30
ruthra kumar
eed6d2b81c Merge pull request #42869 from frappe/mergify/bp/version-15-hotfix/pr-42851
refactor: Allow equity type Account in Payment Entry for shareholders (backport #42851)
2024-08-22 17:30:50 +05:30
Shariq Ansari
edf53f1ab7 Merge pull request #42863 from frappe/mergify/bp/version-15-hotfix/pr-42727
fix: include erpnext in apps page (backport #42727)
2024-08-22 17:24:33 +05:30
ruthra kumar
758282739e fix: call 'process' directly instead of creating 'process_subscripti
reason: 'process' follows simple DB transaction model.
(cherry picked from commit b4d22c2936)
2024-08-22 11:53:32 +00:00
ruthra kumar
49d995c3ac refactor: filter shareholder on company
(cherry picked from commit 63ad9f4f86)
2024-08-22 11:40:39 +00:00
ruthra kumar
72ca2ec9a5 refactor: allow equity types on Payment Entry
(cherry picked from commit 6cbf98294a)
2024-08-22 11:40:39 +00:00
Shariq Ansari
4297895bd9 chore: renamed include_as_app to include_in_apps_screen
(cherry picked from commit 5280132423)
2024-08-22 06:57:25 +00:00
Shariq Ansari
7428df8778 fix: include erpnext in apps page
(cherry picked from commit 1d52ef7afe)
2024-08-22 06:57:25 +00:00
Khushi Rawat
767c79663c Merge pull request #42862 from frappe/mergify/bp/version-15-hotfix/pr-42861
fix(minor): calculation correction for annual depreciation (backport #42861)
2024-08-22 11:56:08 +05:30
Khushi Rawat
fa85482662 fix: calculation correction for annual depreciation
(cherry picked from commit f440243b75)
2024-08-22 05:48:09 +00:00
mergify[bot]
831e2aaf18 fix: custom stock entry type issue (backport #42835) (#42846)
* fix: custom stock entry type issue (#42835)

(cherry picked from commit 9c82c2b5d3)

# Conflicts:
#	erpnext/stock/doctype/stock_entry_type/stock_entry_type.py

* chore: fix conflicts

* chore: fix linters issue

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-21 16:46:05 +05:30
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
mergify[bot]
72c16097d6 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>
2024-08-21 16:12:33 +05:30
mergify[bot]
2203ea9301 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>
2024-08-21 15:20:50 +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
Khushi Rawat
21e5c01f11 Merge pull request #42828 from frappe/mergify/bp/version-15-hotfix/pr-42824
perf: asset creation from purchase receipt (backport #42824)
2024-08-20 15:17:51 +05:30
mergify[bot]
ae6c1a30ac refactor: brand js and allow quick entry (backport #42829) (#42830)
* refactor: brand js and allow quick entry (#42829)

* refactor: brand js and allow quick entry

* refactor: brand js and allow quick entry --prettier

* refactor: brand js and allow quick entry --prettier

(cherry picked from commit a1183f0165)

# Conflicts:
#	erpnext/setup/doctype/brand/brand.json

* refactor: brand js and allow quick entry --refactor

---------

Co-authored-by: Nihantra C. Patel <141945075+Nihantra-Patel@users.noreply.github.com>
2024-08-20 15:03:23 +05:30
Khushi Rawat
1040198ce1 perf: asset creation from purchase receipt
(cherry picked from commit 6e84fc5143)
2024-08-20 08:12:48 +00:00
Nihantra C. Patel
69878b7847 Merge pull request #42826 from frappe/mergify/bp/version-15-hotfix/pr-42379
fix: Create Sales Order from Quotation for Prospect (backport #42379)
2024-08-20 11:57:29 +05:30
Nihantra C. Patel
ec0201cb85 fix: create SO from Quot for Prospect --conflicts 2024-08-20 11:34:27 +05:30
Nihantra C. Patel
5d7fb1d945 fix: create SO from Quot for Prospect --conflicts 2024-08-20 11:31:49 +05:30
Nihantra Patel
33542cb909 fix: update the testcase format
(cherry picked from commit ee44022249)
2024-08-20 05:11:02 +00:00
Nihantra Patel
549dc286d0 fix: update the testcase format
(cherry picked from commit 29d50b770e)
2024-08-20 05:11:02 +00:00
Nihantra Patel
f547befeb9 fix: Create Sales Order from Quotation for Prospect
(cherry picked from commit 2f63fae31d)

# Conflicts:
#	erpnext/selling/doctype/quotation/quotation.py
2024-08-20 05:11:02 +00:00
ruthra kumar
a144059c7c Merge pull request #42825 from frappe/mergify/bp/version-15-hotfix/pr-42731
fix: bank reconcilation tool cost center company filter adding (backport #42731)
2024-08-20 10:35:21 +05:30
Parameshwari Palanisamy
b96361e837 refactor: update dialog_manager.js
(cherry picked from commit 6d19aae423)
2024-08-20 04:44:47 +00:00
creative-paramu
cd5994017c fix: bank reconcilation tool cost center company filter adding
(cherry picked from commit 6e2ac09821)
2024-08-20 04:44:47 +00:00
Raffael Meyer
431fb62803 Merge pull request #42823 from barredterra/backport-german-translations 2024-08-19 19:25:16 +02:00
barredterra
9e9de4c99e fix: backport german translations from develop 2024-08-19 16:43:22 +02:00
Raffael Meyer
d3369368db Merge pull request #42804 from frappe/mergify/bp/version-15-hotfix/pr-42800
fix: translatability of boldened text (backport #42800)
2024-08-19 16:03:11 +02:00
mergify[bot]
b24de3e35b fix: dropping index to improve performance (backport #42820) (#42821)
fix: dropping index to improve performance (#42820)

fix: droping index to improve peformance
(cherry picked from commit 5404b21c7d)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-19 17:34:24 +05:30
mergify[bot]
0344442d42 perf: data import for stock entries (backport #42711) (#42819)
perf: data import for stock entries (#42711)

(cherry picked from commit 1511280464)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-19 14:55:41 +05:30
Raffael Meyer
0decd0955b Merge pull request #42805 from barredterra/de-hr-transl 2024-08-17 02:49:22 +02:00
barredterra
6f7fdbefac fix: german translations of "HR" 2024-08-17 02:48:39 +02:00
barredterra
dbd466b6b2 chore: resolve conflicts 2024-08-17 02:24:58 +02:00
barredterra
4914481105 fix: translatability of boldened text
(cherry picked from commit af0ae930ca)

# Conflicts:
#	erpnext/controllers/accounts_controller.py
2024-08-17 00:21:05 +00:00
Raffael Meyer
8514c01a91 Merge pull request #42798 from barredterra/20240816-de-translations 2024-08-16 19:11:37 +02:00
barredterra
751c20984f fix: german translations 2024-08-16 18:54:06 +02:00
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
ruthra kumar
528f42c713 Merge pull request #42794 from frappe/mergify/bp/version-15-hotfix/pr-42791
fix(patch): Use sql to update 'against_voucher' rather than reposting (backport #42791)
2024-08-16 15:55:14 +05:30
mergify[bot]
7cc7179b05 fix: Auto Create Serial and Batch Bundle For Outward (backport #42778) (#42792)
fix: Auto Create Serial and Batch Bundle For Outward (#42778)

(cherry picked from commit 48c3b0d094)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-16 15:54:14 +05:30
ruthra kumar
cfaad685a4 chore: update patches.txt
(cherry picked from commit 1721175a20)
2024-08-16 10:02:44 +00:00
ruthra kumar
e420fa9779 fix(patch): replace repost with direct sql to update 'against_voucher
(cherry picked from commit 13bb48434f)
2024-08-16 10:02:44 +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
mergify[bot]
0f9849e672 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>
2024-08-16 11:39:15 +05:30
ruthra kumar
3be037221a Merge pull request #42783 from frappe/mergify/bp/version-15-hotfix/pr-42774
refactor: Loosen account currency validation on groups (backport #42774)
2024-08-16 10:41:56 +05:30
ruthra kumar
b2e108afcc refactor: allow foreign currency accounts in Supplier Group
(cherry picked from commit 164498bafb)
2024-08-16 04:30:12 +00:00
ruthra kumar
114a5f8cca refactor: allow foreign currency accounts in customer group
(cherry picked from commit 066e935892)
2024-08-16 04:30:12 +00:00
mergify[bot]
aba54ba18f fix: ignore pricing rule while making DN from Pick List (backport #42763) (#42768)
fix: ignore pricing rule while making DN from Pick List (#42763)

(cherry picked from commit 0db82ec93a)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-14 23:03:01 +05:30
Nihantra C. Patel
6a7768367e Merge pull request #42771 from frappe/mergify/bp/version-15-hotfix/pr-42769
fix: disable rename from warehouse (backport #42769)
2024-08-14 17:15:26 +05:30
Nihantra C. Patel
3a1ad6e844 fix: disable rename from warehouse 2024-08-14 16:37:36 +05:30
Nihantra C. Patel
40abd82e2d fix: disable rename from warehouse
(cherry picked from commit c1812f74e8)

# Conflicts:
#	erpnext/stock/doctype/warehouse/warehouse.json
2024-08-14 11:03:49 +00:00
Khushi Rawat
2933a86458 Merge pull request #42767 from frappe/mergify/bp/version-15-hotfix/pr-42765
fix: set up filters for dimensions (backport #42765)
2024-08-14 14:45:14 +05:30
Khushi Rawat
ecf0d0b388 chore: linters check
(cherry picked from commit 0d42793397)
2024-08-14 09:07:38 +00:00
Khushi Rawat
b84ca04975 fix: removed extra filter condition
(cherry picked from commit 6fa29376a0)
2024-08-14 09:07:38 +00:00
Khushi Rawat
abb88662c1 fix: set up filters for dimensions
(cherry picked from commit 2fd8de2f76)
2024-08-14 09:07:37 +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
ruthra kumar
3dafa98eef Merge pull request #42761 from frappe/mergify/bp/version-15-hotfix/pr-42720
fix: incorrect 'against_voucher' for Pos return with 'Update Outstanding for Self' disabled. (backport #42720)
2024-08-14 12:27:24 +05:30
ruthra kumar
3699b96adf refactor: move patch to v14 and update patches.txt
(cherry picked from commit da2286802a)
2024-08-14 06:26:48 +00:00
ruthra kumar
f782af8ab3 test: against_voucher for pos_returns without updating for self
(cherry picked from commit 3fb0858321)
2024-08-14 06:26:48 +00:00
ruthra kumar
2af48e40a1 refactor: update patches.txt
(cherry picked from commit 4dc0d3a003)
2024-08-14 06:26:48 +00:00
ruthra kumar
389227bce8 fix: patch to fix incorrect against_voucher references in ledger
(cherry picked from commit 487d0a55f5)
2024-08-14 06:26:48 +00:00
ruthra kumar
8cd1952da3 fix: ledger entries for pos return with update outstanding for self
(cherry picked from commit 2cd9b28e5b)
2024-08-14 06:26:48 +00:00
Khushi Rawat
f128fcd86c Merge pull request #42759 from frappe/mergify/bp/version-15-hotfix/pr-42719
fix: linkage between asset repair and asset value adjustment (backport #42719)
2024-08-14 11:23:33 +05:30
Khushi Rawat
d890d02b5c test: new depreciation after cancelling asset repair
(cherry picked from commit 88a5824e31)
2024-08-13 19:01:02 +00:00
Khushi Rawat
defd5541b0 fix: resolved conflict
(cherry picked from commit c085b6159b)
2024-08-13 19:01:01 +00:00
mergify[bot]
8624a0abce fix: duplicate labels in stock entry (backport #42756) (#42758)
fix: duplicate labels in stock entry (#42756)

(cherry picked from commit 8aadc18ee8)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-13 20:31:05 +05:30
ruthra kumar
13b79c6781 Merge pull request #42750 from frappe/mergify/bp/version-15-hotfix/pr-40964
fix: price list when invoice created from timesheet (backport #40964)
2024-08-13 17:35:50 +05:30
Nihantra C. Patel
2926915a06 fix: price list when invoice created from timesheet
(cherry picked from commit 882227a460)
2024-08-13 11:41:40 +00:00
Nihantra C. Patel
536dc47eb0 fix: price list when invoice created from timesheet
(cherry picked from commit 39d6df7c7d)
2024-08-13 11:41:39 +00:00
ruthra kumar
225843265e Merge pull request #42749 from frappe/mergify/bp/version-15-hotfix/pr-42221
fix: Force Fetching updates on Subscriptions (backport #42221)
2024-08-13 16:47:35 +05:30
ruthra kumar
a1f98603a6 refactor: test for force-fetch on future subscription
(cherry picked from commit fd680380bb)
2024-08-13 10:53:24 +00:00
ruthra kumar
ab59b33606 chore: minor naming change
(cherry picked from commit d8b6767697)
2024-08-13 10:53:24 +00:00
ruthra kumar
1f1e934675 refactor: don't process future subscriptions
(cherry picked from commit 3a11577411)
2024-08-13 10:53:24 +00:00
ruthra kumar
582fffca93 fix: force fetch updates for subcription
(cherry picked from commit 1ef890db73)
2024-08-13 10:53:23 +00:00
Khushi Rawat
e9b3a24221 Merge pull request #42742 from frappe/mergify/bp/version-15-hotfix/pr-42689
fix: fetch month's last date to avoid miscalculation (backport #42689)
2024-08-13 15:32:04 +05:30
ruthra kumar
0d5ac078f6 Merge pull request #42741 from frappe/mergify/bp/version-15-hotfix/pr-42726
fix: text color in sales funnel report based on theme (backport #42726)
2024-08-13 14:36:13 +05:30
ruthra kumar
f109164f88 Merge pull request #42739 from frappe/mergify/bp/version-15-hotfix/pr-42590
fix: error message in coa importer (backport #42590)
2024-08-13 14:35:53 +05:30
Khushi Rawat
765c1104c4 fix: fetch months last date to avoid miscalculation
(cherry picked from commit 70ff4e7644)
2024-08-13 08:42:33 +00:00
ljain112
a8de8aecf5 fix: text color in sales funnel report based on theme
(cherry picked from commit 61bc0925d5)
2024-08-13 08:36:31 +00:00
ljain112
20c1bcd654 fix: error message in coa importer
(cherry picked from commit 5d0a38dfc7)
2024-08-13 08:33:21 +00:00
ruthra kumar
6eaad90535 Merge pull request #42735 from frappe/mergify/bp/version-15-hotfix/pr-42733
refactor: add a new filter flag in Process Statement of Accounts (backport #42733)
2024-08-13 11:49:29 +05:30
Smit Vora
91a5c562d8 Merge pull request #42489 from frappe/mergify/bp/version-15-hotfix/pr-42050
fix: Update Rate as per Valuation Rate for Internal Transfers only if Setting is Enabled (backport #42050)
2024-08-13 11:25:09 +05:30
ruthra kumar
70d5593ace chore: resolve conflict 2024-08-13 11:21:09 +05:30
ruthra kumar
f3401243be refactor: pass filter to General Ledger
(cherry picked from commit 90880c8c01)
2024-08-13 05:41:35 +00:00
ruthra kumar
19dfeca96d refactor: cr and dr note filter in Statement of Accounts
(cherry picked from commit 0cf478c4c2)

# Conflicts:
#	erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json
2024-08-13 05:41:35 +00:00
ruthra kumar
774db56762 refactor: combine vouchers from both ignore
(cherry picked from commit 4cc5cd5a71)
2024-08-13 05:41:35 +00:00
Khushi Rawat
d15c535f86 Merge pull request #42730 from frappe/mergify/bp/version-15-hotfix/pr-42729
fix: cancel Journal Entry on cancellation of asset value adjustment (backport #42729)
2024-08-13 02:31:24 +05:30
Khushi Rawat
a429f2f626 fix: cancel Journal Entry on cancellation of asset value adjustment
(cherry picked from commit 4b7f1f2d67)
2024-08-12 20:43:30 +00:00
ruthra kumar
dfbc7e8b33 Merge pull request #42725 from frappe/mergify/bp/version-15-hotfix/pr-42672
fix: update 'Paid Amount' on forex payment request (backport #42672)
2024-08-12 16:31:35 +05:30
ruthra kumar
b41f10c1b9 chore: resolve conflict 2024-08-12 16:13:59 +05:30
ruthra kumar
44745a757d test: currency conversion on foreign currency account
(cherry picked from commit f913c0fde1)
2024-08-12 10:38:35 +00:00
ruthra kumar
47bf2d408b test: make use of test fixture
(cherry picked from commit d6d0a1b38d)

# Conflicts:
#	erpnext/accounts/doctype/payment_request/test_payment_request.py
2024-08-12 10:38:35 +00:00
ruthra kumar
c71f06be9e fix: update 'Paid Amount' on forex payment request
(cherry picked from commit 7b0dfb2a05)
2024-08-12 10:38:34 +00:00
mergify[bot]
50b1fa5deb fix: currency changing while making PR from the PO (backport #42718) (#42721)
fix: currency changing while making PR from the PO (#42718)

(cherry picked from commit 17ba0cff44)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-12 15:20:04 +05:30
mergify[bot]
a99057754d fix: warning message for negative stock (backport #42683) (#42710)
fix: warning message for negative stock (#42683)

(cherry picked from commit deccb007c1)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-11 12:35:13 +05:30
mergify[bot]
6f16ae3e00 fix: delivery note creation issue (backport #42696) (#42697)
fix: delivery note creation issue (#42696)

(cherry picked from commit b65072cd98)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-09 15:24:34 +05:30
ruthra kumar
38d80aab99 Merge pull request #42695 from frappe/mergify/bp/version-15-hotfix/pr-42428
fix: Sort lists before calling itertools.groupby (backport #42428)
2024-08-09 12:44:38 +05:30
Corentin Forler
d8939e0bb0 fix: Sort lists before calling itertools.groupby
(cherry picked from commit 45a6ecbd38)
2024-08-09 06:23:57 +00:00
ruthra kumar
f376abf0fe Merge pull request #42693 from frappe/mergify/bp/version-15-hotfix/pr-42691
fix: typeerror on payment entry (backport #42691)
2024-08-09 11:52:18 +05:30
ruthra kumar
64e75a8e08 fix: typeerror on payment entry
(cherry picked from commit 9cdca0d662)
2024-08-09 06:11:16 +00:00
Raffael Meyer
67a210f722 Merge pull request #42684 from barredterra/exit-translation
fix: german translation of exit
2024-08-08 22:23:34 +02:00
barredterra
a2df276880 fix: german translation of exit 2024-08-08 20:20:22 +02:00
Raffael Meyer
151d293aaf Merge pull request #42680 from frappe/mergify/bp/version-15-hotfix/pr-42679
fix(Exchange Rate Revaluation): translatable strings (backport #42679)
2024-08-08 13:17:27 +02:00
barredterra
13f6f3259d refactor(Exchange Rate Revaluation): remove unused variables
(cherry picked from commit 8bd84e9d51)
2024-08-08 10:09:53 +00:00
barredterra
da6eea7743 fix(Exchange Rate Revaluation): translatable strings
(cherry picked from commit dc29fb8759)
2024-08-08 10:09:52 +00:00
ruthra kumar
b28fa8b994 Merge pull request #42678 from frappe/mergify/bp/version-15-hotfix/pr-42673
fix: Maintain same rate on qty change on Quotation to Sales Order (backport #42673)
2024-08-08 13:43:46 +05:30
ruthra kumar
7ed7c22469 fix: Maintain same rate on qty change on Quotation to Sales Order
(cherry picked from commit 91ce9fce9b)
2024-08-08 08:04:30 +00:00
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
Shariq Ansari
a81bc28afb Merge pull request #42668 from frappe/mergify/bp/version-15-hotfix/pr-42596
fix: changes in opportunity.py to show contacts and addresses created from opportunity (backport #42596)
2024-08-08 11:39:44 +05:30
Smit Vora
70e40183bb Merge pull request #42551 from frappe/mergify/bp/version-15-hotfix/pr-42392
fix: allow sale of asset for internal transfer (backport #42392)
2024-08-08 11:22:00 +05:30
Smit Vora
bdfc1ddfc3 Merge pull request #42550 from frappe/mergify/bp/version-15-hotfix/pr-42432
fix: promotional scheme doctype fields in consitency with pricing rule (backport #42432)
2024-08-08 11:21:09 +05:30
Raffael Meyer
fb770f5633 Merge pull request #42669 from barredterra/incoterms-translation 2024-08-07 20:52:32 +02:00
barredterra
9789648175 fix: german translations for incoterms 2024-08-07 20:08:54 +02:00
Dietmar Fischer
94f4c92a03 fix: pre-commit for better code formatting
(cherry picked from commit 511a0b9f37)
2024-08-07 14:29:48 +00:00
Dietmar Fischer
3cac4a598f feat: changes in opportunity.py to show contacts and addresses from referenced and opportunities
(cherry picked from commit 61576ca030)
2024-08-07 14:29:47 +00:00
ruthra kumar
654fea8a3b Merge pull request #42661 from frappe/mergify/bp/version-15-hotfix/pr-42578
fix: dimensions in common party journal entry (backport #42578)
2024-08-07 16:23:54 +05:30
ruthra kumar
838d341d91 test: dimension inheritance on Exc Gain/Loss JV on Common party
(cherry picked from commit 8040544216)
2024-08-07 10:34:09 +00:00
ljain112
fd4143e686 fix: dimensions in common party journal entry
(cherry picked from commit ac629ede79)
2024-08-07 10:34:09 +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
Khushi Rawat
0a3c0ecea2 Merge pull request #42654 from frappe/mergify/bp/version-15-hotfix/pr-42593
fix: disable primary action button only when there are no active capitalization (backport #42593)
2024-08-06 20:19:11 +05:30
Khushi Rawat
2d644ac066 fix: disable primary action button only when there are no active capitalization
(cherry picked from commit bb877f4a6b)
2024-08-06 13:43:27 +00:00
mergify[bot]
d8768c5377 feat: expiry date column in Available Batch Report (backport #42628) (#42642)
feat: expiry date column in Available Batch Report (#42628)

(cherry picked from commit faff84c6e5)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-06 14:45:12 +05:30
ruthra kumar
65c1387a04 Merge pull request #42646 from frappe/mergify/bp/version-15-hotfix/pr-42592
fix: company filter for filtring tax withheld vouchers (backport #42592)
2024-08-06 13:38:47 +05:30
ljain112
3ad1f2d0d0 fix: company filter for filtring tax withheld vouchers
(cherry picked from commit cfe2ae604b)
2024-08-06 07:47:21 +00:00
ruthra kumar
af31f3b291 Merge pull request #42644 from frappe/mergify/bp/version-15-hotfix/pr-42545
fix: min height for rows in sales funnel (backport #42545)
2024-08-06 13:09:29 +05:30
ljain112
2f81c99143 fix: min height for rows in sales funnel
(cherry picked from commit fd71d8af52)
2024-08-06 07:33:19 +00:00
ruthra kumar
e679b336ef Merge pull request #42638 from frappe/mergify/bp/version-15-hotfix/pr-42636
refactor: posting date should not be considered for ignore filters in GL (backport #42636)
2024-08-06 11:43:46 +05:30
ruthra kumar
82c17632f7 refactor: posting date is not considered for ignore filters in GL
(cherry picked from commit c930f8ba9d)
2024-08-06 05:26:25 +00:00
mergify[bot]
59b9b7dc91 fix: do not update item price and last purchase rate for inter transf… (backport #42616) (#42633)
fix: do not update item price and last purchase rate for inter transf… (#42616)

fix: do not update item price and last purchase rate for inter transfer transaction
(cherry picked from commit c8af544ef3)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-08-06 08:19:59 +05:30
ruthra kumar
d242d5330c Merge pull request #42626 from frappe/mergify/bp/version-15-hotfix/pr-42555
refactor: date filters should be mandatory in Sales Pipeline Analytics report (backport #42555)
2024-08-05 15:32:17 +05:30
ruthra kumar
05c606b65d refactor(test): use test fixture and supply from and to dates
(cherry picked from commit 4253caf910)
2024-08-05 09:39:30 +00:00
ruthra kumar
52578b03b4 refactor: consider empty-string as Not Assigned
(cherry picked from commit 213b2ba942)
2024-08-05 09:39:30 +00:00
ruthra kumar
8978a54479 refactor: report columns should be based on from and to dates
(cherry picked from commit 751a25c4b7)
2024-08-05 09:39:30 +00:00
ruthra kumar
b44598cb7a refactor: make 'from_date' and 'to_date' mandatory
(cherry picked from commit 3617b41b95)
2024-08-05 09:39:30 +00:00
ruthra kumar
48e05b6110 refactor: date filters should be explicit
(cherry picked from commit 40c166a0a0)
2024-08-05 09:39:30 +00:00
ruthra kumar
3640bc7f88 Merge pull request #42623 from frappe/mergify/bp/version-15-hotfix/pr-42621
refactor(test): clear data before GL report tests (backport #42621)
2024-08-05 14:02:19 +05:30
ruthra kumar
531410820f refactor(test): clear old records on GL report tests
(cherry picked from commit 56620785a0)
2024-08-05 08:15:31 +00:00
ruthra kumar
d08eba7308 Merge pull request #42614 from frappe/mergify/bp/version-15-hotfix/pr-42597
refactor: filter to ignore system generated cr / dr reconciliation journals on general ledger (backport #42597)
2024-08-05 11:34:00 +05:30
ruthra kumar
c1bfa0a31a refactor(test): filter and reconcile concerned vouchers
(cherry picked from commit 9ade269b7a)
2024-08-05 05:44:25 +00:00
ruthra kumar
155ca14b19 test: clear old data
(cherry picked from commit 991069bfbc)
2024-08-05 05:44:25 +00:00
ruthra kumar
3ee5991896 refactor: make use of date filters on ignore filterss
(cherry picked from commit 03f3ab522f)
2024-08-05 05:44:25 +00:00
ruthra kumar
7ec7e11634 test: ignore filter for system generated cr / dr note journals
(cherry picked from commit 3ffac73598)
2024-08-05 05:44:25 +00:00
ruthra kumar
17a6224a3f refactor: ignore system generated cr / dr notes on general ledger
(cherry picked from commit bb8c9b5a58)
2024-08-05 05:44:25 +00:00
ruthra kumar
e9bcb1bbb2 refactor: ignore filter in general ledger for cr / dr notes
(cherry picked from commit 59d5beee20)
2024-08-05 05:44:25 +00:00
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
mergify[bot]
830b95bdcb fix: all warehouse filter for the stock report (backport #42584) (#42604)
fix: all warehouse filter for the stock report

(cherry picked from commit a4311e345d)

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2024-08-03 09:02:25 +05:30
mergify[bot]
2de86eb0f4 fix: use get_last_day to get the correct date (backport #42564) (#42598)
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-02 17:10:37 +05:30
Raffael Meyer
9616c59ed8 Merge pull request #42581 from barredterra/german-translations-01082024 2024-08-01 16:56:24 +02:00
barredterra
f27e9f3089 fix: german translations 2024-08-01 16:33:19 +02:00
mergify[bot]
9321408154 fix: Discount and taxes in return document should follow the reference document (backport #41911) (#42574)
fix: Discount and taxes in return document should follow the reference document (#41911)

* fix: Discount and taxes in return document should follow the reference document

* fix: Ignore Pricing rule on debit/credit note if created against PI/SI with test cases

* fix: linter issue

(cherry picked from commit 281198456d)

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2024-08-01 15:45:18 +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
mergify[bot]
97cc3082e1 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>
2024-08-01 13:22:33 +05:30
ruthra kumar
b7b4de7c8d Merge pull request #42566 from frappe/mergify/bp/version-15-hotfix/pr-42563
fix: set query filters for sales / purchase tax template on PE (backport #42563)
2024-07-31 17:28:56 +05:30
ruthra kumar
dc9cf74be8 fix: set query filters for sales / purchase tax template on PE
(cherry picked from commit 9fe47ac101)
2024-07-31 11:39:12 +00:00
ruthra kumar
4e826fb3e9 Merge pull request #42560 from frappe/mergify/bp/version-15-hotfix/pr-42558
fix: 'undefined' in PL and BS report summary on Consolidated report (backport #42558)
2024-07-31 16:19:29 +05:30
Raffael Meyer
553513c4c6 Merge pull request #42561 from barredterra/backport-translations 2024-07-31 12:48:52 +02:00
barredterra
5cfa2d0692 chore: backport german translations from develop 2024-07-31 12:19:13 +02:00
ruthra kumar
3da7071327 fix: 'undefined' in PL and BS report summary on Consolidated report
(cherry picked from commit dd5a5e4919)
2024-07-31 10:04:00 +00:00
Nabin Hait
c3293d110c fix: resolved conflict (#42557) 2024-07-31 14:54:52 +05:30
Lakshit Jain
78eb443614 chore: resolve conflicts (#42553) 2024-07-31 13:38:38 +05:30
ljain112
97cadfe5d3 fix: allow sale of asset for internal transfer
(cherry picked from commit 972329cc16)
2024-07-31 07:54:58 +00:00
Lakshit Jain
87d8603d1d 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
2024-07-31 07:51:57 +00:00
Smit Vora
7dc68cabcc Merge pull request #42548 from frappe/mergify/bp/version-15-hotfix/pr-42367
fix: reverse debit credit for party gl entry in payment entry based on negative amount (backport #42367)
2024-07-31 13:17:08 +05:30
mergify[bot]
7c8d13c51a fix: set currency on change of company considering customer default currency (backport #42405) (#42547)
fix: set currency on change of company considering customer default currency (#42405)

(cherry picked from commit 4986f28a89)

# Conflicts:
#	erpnext/public/js/controllers/transaction.js

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2024-07-31 13:02:12 +05:30
Lakshit Jain
14f9aef55c fix: reverse debit credit for party gl entry in payment entry based on negative amount (#42367)
* fix: do not absolute the amount for party gl entries

* fix: reverse debit credit for party gl entry based on negative amount

* refactor: reduce nesting of if condition

---------

(cherry picked from commit a694390a12)
2024-07-31 07:16:57 +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
Khushi Rawat
64c185f097 Merge pull request #42546 from frappe/mergify/bp/version-15-hotfix/pr-42525
fix: Adjust initial month's depreciation to end of depreciation period (backport #42525)
2024-07-30 19:24:32 +05:30
Khushi Rawat
1390c86fc4 fix(tests): added tests for usecase
(cherry picked from commit f0768010d9)
2024-07-30 13:35:18 +00:00
Khushi Rawat
9d2ef4d3e8 fix: Adjust initial month's depreciation to end of depreciation period
(cherry picked from commit cbb749a3a5)
2024-07-30 13:35:17 +00:00
mergify[bot]
6840f6cb26 perf: huge number of serial no creation (backport #42522) (#42544)
perf: huge number of serial no creation (#42522)

(cherry picked from commit 1c7f7c8d1a)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-07-30 17:01:43 +05:30
rohitwaghchaure
61280e6072 fix: not able to save BOM Creator (#42540) 2024-07-30 15:13:19 +05:30
mergify[bot]
b7d70ac928 fix: purchase return from rejected warehouse (backport #42531) (#42535)
fix: purchase return from rejected warehouse (#42531)

(cherry picked from commit c5d68333c9)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-07-30 14:53:42 +05:30
mergify[bot]
826577c88f fix: warehouse filter in Product Bundle Balance (backport #42532) (#42537)
fix: warehouse filter in Product Bundle Balance (#42532)

(cherry picked from commit 0ecfa709d8)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-07-30 14:53:03 +05:30
mergify[bot]
5fa185d480 fix: price_list_currency not found error (backport #42534) (#42539)
fix: price_list_currency not found error (#42534)

(cherry picked from commit 23fed831a0)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-07-30 14:52:23 +05:30
ruthra kumar
75271ca1a0 Merge pull request #42533 from frappe/mergify/bp/version-15-hotfix/pr-42476
refactor: checkbox to control Payment Request creation (backport #42476)
2024-07-30 14:04:48 +05:30
ruthra kumar
f03e58f5f6 chore: resolve conflict 2024-07-30 13:39:14 +05:30
ruthra kumar
596110dd65 refactor: checkbox to control Payment Request creation
(cherry picked from commit ce81fd9ba6)

# Conflicts:
#	erpnext/accounts/doctype/payment_request/payment_request.py
2024-07-30 08:07:04 +00:00
ruthra kumar
76018f5b9c Merge pull request #42530 from frappe/mergify/bp/version-15-hotfix/pr-42528
chore: button name should reflect what it creates (backport #42528)
2024-07-30 12:12:28 +05:30
ruthra kumar
1019f6d158 chore: button name should reflect what it creates
(cherry picked from commit 0b6e7f83cd)
2024-07-30 06:31:20 +00:00
mergify[bot]
fc0db1941a fix: Warranty Expiry Date not set in the serial number (backport #42513) (#42515)
fix: Warranty Expiry Date not set in the serial number (#42513)

* fix: Warranty Expiry Date not set in the serial number

* chore: fix linters issue

(cherry picked from commit 8eff168d76)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-07-29 15:44:01 +05:30
mergify[bot]
f25b38caf5 fix: builtins.KeyError: ('ABC', 'Store - CP') (backport #42505) (#42509)
fix: builtins.KeyError: ('ABC', 'Store - CP') (#42505)

(cherry picked from commit 25dac1f18e)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-07-29 10:21:11 +05:30
mergify[bot]
edf1fcb742 fix: performance issue for the report Purchase Order Analysis report (backport #42503) (#42507)
fix: performance issue for the report Purchase Order Analysis report (#42503)

(cherry picked from commit cb522f8f22)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-07-29 09:50:02 +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
mergify[bot]
ac2ef21896 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>
2024-07-27 10:41:07 +05:30
ruthra kumar
b529dc7dd1 Merge pull request #42492 from frappe/mergify/bp/version-15-hotfix/pr-42477
fix: incorrect cost_center on AR/AP report (backport #42477)
2024-07-26 20:10:30 +05:30
ruthra kumar
4b24f8bc04 test: invoice cost center reported in AR/AP report
(cherry picked from commit 9a0894fd65)
2024-07-26 14:14:32 +00:00
ruthra kumar
0c2e9480cb fix: incorrect cost_center on AR/AP report
(cherry picked from commit 3e19041fa3)
2024-07-26 14:14:31 +00:00
Ninad Parikh
6e833cce6a fix: Update Rate as per Valuation Rate for Internal Transfers only if Setting is Enabled (#42050)
* fix: update rate for internal transfers only if settings enabled

* fix: better naming

* fix: create field for storing incoming rate in purchase doctypes

* fix: use qty instead of qty_in_stock_uom

* fix: add description, refactor for readablility

* test: test case to validate internal transfers at arm's length price

* fix: minor fix

* fix: deletion of code not required

---------

Co-authored-by: Smit Vora <smitvora203@gmail.com>
(cherry picked from commit 723ac0ffc4)
2024-07-26 12:58:12 +00:00
Smit Vora
901f83edd5 Merge pull request #42487 from frappe/mergify/bp/version-15-hotfix/pr-42470
fix: Fields Alteration Related to Subcontracting (backport #42470)
2024-07-26 18:23:11 +05:30
Ninad1306
80d4dc2016 fix: fields alteration related to subcontracting
(cherry picked from commit 77590e6077)
2024-07-26 10:56:15 +00:00
Smit Vora
3a279db06b Merge pull request #42468 from frappe/mergify/bp/version-15-hotfix/pr-42383
fix: Fields Modification for Subcontracting DocTypes (backport #42383)
2024-07-26 16:24:10 +05:30
Smit Vora
3053254db7 Merge pull request #42484 from frappe/mergify/bp/version-15-hotfix/pr-42305
fix: consider payment entries for checking if tds is deducted (backport #42305)
2024-07-26 15:17:18 +05:30
Smit Vora
d135193f6c Merge pull request #42482 from frappe/mergify/bp/version-15-hotfix/pr-42444
fix: parenttype in purchase and sales item query (backport #42444)
2024-07-26 15:16:54 +05:30
ljain112
183ac41550 fix: consider payment entries for checking if tds is deducted
(cherry picked from commit 40b59de4cd)
2024-07-26 09:11:50 +00:00
ljain112
322fbe92ee fix: parenttype in item wise purchase and sales register
(cherry picked from commit 35981b8730)
2024-07-26 08:56:43 +00:00
Smit Vora
367b7eeeba Merge pull request #42471 from Ninad1306/backport_changes
fix: Field type is small text for v15
2024-07-26 14:04:39 +05:30
ruthra kumar
dd8fff6d43 Merge pull request #42474 from frappe/mergify/bp/version-15-hotfix/pr-42472
refactor: index on Purchase Invoice 'release_date' (backport #42472)
2024-07-25 21:51:23 +05:30
ruthra kumar
3e3bdf7491 refactor: index on Purchase Invoice 'release_date'
(cherry picked from commit 764dd12b10)
2024-07-25 15:57:59 +00:00
Ninad1306
9e99eda3c3 fix: field_type is small text for v15 2024-07-25 18:39:20 +05:30
Smit Vora
05b9432f6d Merge pull request #42402 from frappe/mergify/bp/version-15-hotfix/pr-42386
fix: set pos data if not return doc (backport #42386)
2024-07-25 11:40:49 +05:30
Ninad Parikh
422824b9e7 fix: Fields Modification for Subcontracting DocTypes (#42383)
* fix: fields renaming and reordering for enhanced user experience

* fix: dashboard data for stock entry

(cherry picked from commit 302339998f)

# Conflicts:
#	erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.json
2024-07-25 04:49:14 +00:00
mergify[bot]
2d2140aad0 fix: keyerror posting_time (backport #42452) (#42460)
fix: keyerror posting_time (#42452)

fix: keyerror: posting_time
(cherry picked from commit 06e2d7265c)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-07-25 06:48:10 +05:30
ruthra kumar
a24fe951ed Merge pull request #42465 from frappe/mergify/bp/version-15-hotfix/pr-42462
refactor: provision for re-evaluating Exchange Rates in monthly frequency (backport #42462)
2024-07-24 22:11:29 +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
ruthra kumar
7b3a78e04e refactor: hooks for monthly re-evaluation jobs
(cherry picked from commit fc4e5f165c)
2024-07-24 13:15:18 +00:00
ruthra kumar
219310e817 refactor: provision for monthly re-evaluation
(cherry picked from commit ce2b9e0f1a)
2024-07-24 13:15:18 +00:00
mergify[bot]
298a5699f1 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>
2024-07-24 18:37:13 +05:30
ruthra kumar
bf34c94483 Merge pull request #42456 from frappe/mergify/bp/version-15-hotfix/pr-42390
refactor: cleaning up stale code related to reposting (backport #42390)
2024-07-24 17:34:53 +05:30
Smit Vora
a7d8202b4e Merge pull request #42440 from frappe/mergify/bp/version-15-hotfix/pr-42377
fix: ignore duplicates while creating default templates (backport #42377)
2024-07-24 14:25:15 +05:30
ruthra kumar
2ae94b2af2 chore: resolve conflicts 2024-07-24 13:01:51 +05:30
ruthra kumar
e607f3c78d refactor(test): remove assert on 'repost_required'
(cherry picked from commit e71cb4eab7)
2024-07-24 07:29:12 +00:00
ruthra kumar
d69361b1c9 refactor: remove attribute check on 'repost_required'
(cherry picked from commit 07fc952a43)
2024-07-24 07:29:11 +00:00
ruthra kumar
949d7f4b53 refactor: repost without checking on flag
(cherry picked from commit 09f429ffba)
2024-07-24 07:29:11 +00:00
ruthra kumar
01dfea3ffa chore: remove stale UI code related to repost
(cherry picked from commit fe46e1d089)
2024-07-24 07:29:11 +00:00
ruthra kumar
8b9860902c chore: remove 'repost_required' from Journal Entry
(cherry picked from commit e81373bb6a)

# Conflicts:
#	erpnext/accounts/doctype/journal_entry/journal_entry.json
2024-07-24 07:29:11 +00:00
ruthra kumar
3d8eac9b5a chore: remove 'repost_required' from purchase invoice
(cherry picked from commit a467888a67)
2024-07-24 07:29:11 +00:00
ruthra kumar
a8fe0e89a8 chore: remove stale 'repost_required' flag from sales invoice
(cherry picked from commit 06c5334f2a)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.json
2024-07-24 07:29:11 +00:00
ruthra kumar
9b52d89e03 chore: remove stale code from sales invoice
(cherry picked from commit f3fda9ce98)
2024-07-24 07:29:11 +00:00
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
Khushi Rawat
c045c9a6dd Merge pull request #42450 from frappe/mergify/bp/version-15-hotfix/pr-42372
fix: correct validation for depreciation posting date (backport #42372)
2024-07-24 12:10:00 +05:30
Syed Mujeer Hashmi
976abf7b3c fix: Update get_amount to return currency precision grand total
In case of multi-currency purchase invoice, we are getting the error "Total Payment Request amount cannot be greater than Purchase Invoice amount" because of rounding difference.
2024-07-24 11:59:45 +05:30
Raffael Meyer
8141c6504e Merge pull request #42437 from frappe/mergify/bp/version-15-hotfix/pr-42419
fix: provide initial value for `.reduce()` call (backport #42419)
2024-07-23 13:06:37 +02:00
Khushi Rawat
ffacf4222b fix: correct validation for depreciation posting date
(cherry picked from commit da4ed90a3e)
2024-07-23 09:54:44 +00:00
Smit Vora
aea8271f7e fix: ignore duplicates while creating default templates
(cherry picked from commit cf55c2ab3d)
2024-07-23 04:56:36 +00:00
barredterra
72bc539ffd fix: provide initial value for .reduce() call
Fixes the error "TypeError: Reduce of empty array with no initial value" (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Reduce_of_empty_array_with_no_initial_value#invalid_cases)

(cherry picked from commit 65f80abf2f)
2024-07-22 18:42:13 +00:00
mergify[bot]
926fd41a2b fix: qty in the 'Serial No Ledger' report (backport #42429) (#42433)
fix: qty in the 'Serial No Ledger' report (#42429)

(cherry picked from commit be2648245b)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-07-22 18:06:56 +05:30
ruthra kumar
f2bc064da2 Merge pull request #42409 from frappe/mergify/bp/version-15-hotfix/pr-42407
test: basic test case for item-wise purchase register (backport #42407)
2024-07-21 20:08:27 +05:30
mergify[bot]
555be2be11 fix: serial and batch bundle for POS Invoice (backport #41491) (#42396)
* fix: serial and batch bundle for POS Invoice (#41491)

(cherry picked from commit e5dfc5e545)

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

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-07-21 00:00:14 +05:30
mergify[bot]
8da28dcfb2 fix: Consider adding warranty period to serial nos (backport #42051) (#42182)
fix: Consider adding warranty period to serial nos (#42051)

(cherry picked from commit 55e2b876a2)

Co-authored-by: Syed Mujeer Hashmi <mujeerhashmi@4csolutions.in>
2024-07-20 11:12:17 +05:30
Smit Vora
5741f32080 Merge pull request #42420 from frappe/mergify/bp/version-15-hotfix/pr-42399
feat: add make_regional_gl_entries override for Sales Invoice (backport #42399)
2024-07-20 09:34:39 +05:30
HENRY Florian
22b17de2b4 feat: add make_regional_gl_entries override for Sales Invoice (#42399)
* feat: add make_regional_gl_entries override for Sales Invoice and Stock Controler

* chore: remove regionnal override for stock management

(cherry picked from commit 1bbe020cfd)
2024-07-20 02:56:01 +00:00
Khushi Rawat
96062dec10 Merge pull request #42413 from frappe/mergify/bp/version-15-hotfix/pr-42412
fix: set filter to show only submitted asset (backport #42412)
2024-07-19 19:24:24 +05:30
Khushi Rawat
29fc975fb8 fix: set filter to show only submitted asset
(cherry picked from commit 69b8e10e20)
2024-07-19 13:47:45 +00:00
ruthra kumar
0052ca9173 test: basic test case for item-wise purchase register
(cherry picked from commit c3c5d3f615)
2024-07-19 11:21:08 +00:00
mergify[bot]
54791e938b fix: rounding issue causing incorrect quantity in SE (backport #42380) (#42395)
fix: rounding issue causing incorrect quantity in SE (#42380)

(cherry picked from commit e1b9b432c3)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-07-19 14:49:56 +05:30
mergify[bot]
709be13e82 fix: Purchase Order Analysis Report Data (backport #42387) (#42394)
fix: Purchase Order Analysis Report Data (#42387)

(cherry picked from commit 67bf9bec47)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-07-19 14:49:39 +05:30
ruthra kumar
7893a957cb Merge pull request #42403 from frappe/mergify/bp/version-15-hotfix/pr-41959
fix: Don't allow negative amount on Payment Request #41905 (backport #41959)
2024-07-19 10:54:46 +05:30
ruthra kumar
a9146efc17 chore: resolve conflict 2024-07-19 10:36:42 +05:30
hiteshprajapati
aee2cc2e03 fix: Don't allow negative amount on Payment Request #41905
(cherry picked from commit b823aa66bf)

# Conflicts:
#	erpnext/accounts/doctype/payment_request/payment_request.json
2024-07-19 05:04:34 +00:00
ljain112
25fe08eb74 fix: set pos data if not return doc
(cherry picked from commit 65d672da65)
2024-07-19 04:56:27 +00:00
ruthra kumar
307dcea097 Merge pull request #42385 from frappe/mergify/bp/version-15-hotfix/pr-42374
fix: Show the rows in AR/AP report where outstanding equals to 0.01 (backport #42374)
2024-07-18 14:39:27 +05:30
ruthra kumar
0dae0a05d4 test: AR/AP report on miniscule outstanding
(cherry picked from commit bb9e42cce2)
2024-07-18 08:15:39 +00:00
Nabin Hait
886256c86b fix: Show the rows in AR/AP report where outstanding equals to 0.01
(cherry picked from commit e1dedc5402)
2024-07-18 08:15:39 +00:00
ruthra kumar
372a7e905c Merge pull request #42381 from frappe/mergify/bp/version-15-hotfix/pr-42369
fix: missing cr/dr notes on payment reconciliation (backport #42369)
2024-07-18 12:58:42 +05:30
ruthra kumar
3f820734b6 test: payment filter should not affect dr/cr notes
(cherry picked from commit 2d686c06ea)
2024-07-18 07:12:44 +00:00
ruthra kumar
0a41ccda99 fix: missing cr/dr notes on payment reconciliation
(cherry picked from commit a30af68e9e)
2024-07-18 07:12:44 +00:00
mergify[bot]
18500b8e3a fix: not able to save QC (backport #42371) (#42373)
fix: not able to save QC (#42371)

(cherry picked from commit 62fb495a65)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-07-17 21:36:47 +05:30
Smit Vora
bebd70d752 Merge pull request #42365 from frappe/mergify/bp/version-15-hotfix/pr-42307
fix: remove redundant proprietorship field from customer type and supplier type (backport #42307)
2024-07-17 18:55:22 +05:30
Sanket322
527781a588 fix: remove proprietorship and update it with individual
(cherry picked from commit c8ad6d1b2c)
2024-07-17 08:32:17 +00:00
216 changed files with 8254 additions and 1426 deletions

View File

@@ -2,8 +2,9 @@ import functools
import inspect
import frappe
from frappe.utils.user import is_website_user
__version__ = "15.30.0"
__version__ = "15.35.1"
def get_default_company(user=None):
@@ -149,3 +150,13 @@ def allow_regional(fn):
return frappe.get_attr(overrides[function_path][-1])(*args, **kwargs)
return caller
def check_app_permission():
if frappe.session.user == "Administrator":
return True
if is_website_user():
return False
return True

View File

@@ -202,7 +202,7 @@ class Account(NestedSet):
msg = _(
"There are ledger entries against this account. Changing {0} to non-{1} in live system will cause incorrect output in 'Accounts {2}' report"
).format(
frappe.bold("Account Type"), doc_before_save.account_type, doc_before_save.account_type
frappe.bold(_("Account Type")), doc_before_save.account_type, doc_before_save.account_type
)
frappe.msgprint(msg)
self.add_comment("Comment", msg)

View File

@@ -109,7 +109,8 @@
"Utility Expenses": {},
"Write Off": {},
"Exchange Gain/Loss": {},
"Gain/Loss on Asset Disposal": {}
"Gain/Loss on Asset Disposal": {},
"Impairment": {}
},
"root_type": "Expense"
},
@@ -132,7 +133,8 @@
"Source of Funds (Liabilities)": {
"Capital Account": {
"Reserves and Surplus": {},
"Shareholders Funds": {}
"Shareholders Funds": {},
"Revaluation Surplus": {}
},
"Current Liabilities": {
"Accounts Payable": {

View File

@@ -72,6 +72,7 @@ def get():
_("Write Off"): {},
_("Exchange Gain/Loss"): {},
_("Gain/Loss on Asset Disposal"): {},
_("Impairment"): {},
},
"root_type": "Expense",
},
@@ -104,6 +105,7 @@ def get():
_("Dividends Paid"): {"account_type": "Equity"},
_("Opening Balance Equity"): {"account_type": "Equity"},
_("Retained Earnings"): {"account_type": "Equity"},
_("Revaluation Surplus"): {"account_type": "Equity"},
"root_type": "Equity",
},
}

View File

@@ -73,7 +73,9 @@
"remarks_section",
"general_ledger_remarks_length",
"column_break_lvjk",
"receivable_payable_remarks_length"
"receivable_payable_remarks_length",
"payment_request_settings",
"create_pr_in_draft_status"
],
"fields": [
{
@@ -475,6 +477,18 @@
"fieldname": "calculate_depr_using_total_days",
"fieldtype": "Check",
"label": "Calculate daily depreciation using total days in depreciation period"
},
{
"description": "Payment Request created from Sales Order or Purchase Order will be in Draft status. When disabled document will be in unsaved state.",
"fieldname": "payment_request_settings",
"fieldtype": "Tab Break",
"label": "Payment Request"
},
{
"default": "1",
"fieldname": "create_pr_in_draft_status",
"fieldtype": "Check",
"label": "Create in Draft Status"
}
],
"icon": "icon-cog",
@@ -482,7 +496,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2024-07-12 00:24:20.957726",
"modified": "2024-07-26 06:48:52.714630",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",

View File

@@ -35,6 +35,7 @@ class AccountsSettings(Document):
book_tax_discount_loss: DF.Check
calculate_depr_using_total_days: DF.Check
check_supplier_invoice_uniqueness: DF.Check
create_pr_in_draft_status: DF.Check
credit_controller: DF.Link | None
delete_linked_ledger_entries: DF.Check
determine_address_tax_category_from: DF.Literal["Billing Address", "Shipping Address"]

View File

@@ -38,6 +38,11 @@ frappe.ui.form.on("Bank Clearance", {
frm.add_custom_button(__("Get Payment Entries"), () => frm.trigger("get_payment_entries"));
frm.change_custom_button_type(__("Get Payment Entries"), null, "primary");
if (frm.doc.payment_entries.length) {
frm.add_custom_button(__("Update Clearance Date"), () => frm.trigger("update_clearance_date"));
frm.change_custom_button_type(__("Get Payment Entries"), null, "default");
frm.change_custom_button_type(__("Update Clearance Date"), null, "primary");
}
},
update_clearance_date: function (frm) {
@@ -45,13 +50,7 @@ frappe.ui.form.on("Bank Clearance", {
method: "update_clearance_date",
doc: frm.doc,
callback: function (r, rt) {
frm.refresh_field("payment_entries");
frm.refresh_fields();
if (!frm.doc.payment_entries.length) {
frm.change_custom_button_type(__("Get Payment Entries"), null, "primary");
frm.change_custom_button_type(__("Update Clearance Date"), null, "default");
}
frm.refresh();
},
});
},
@@ -60,17 +59,8 @@ frappe.ui.form.on("Bank Clearance", {
return frappe.call({
method: "get_payment_entries",
doc: frm.doc,
callback: function (r, rt) {
frm.refresh_field("payment_entries");
if (frm.doc.payment_entries.length) {
frm.add_custom_button(__("Update Clearance Date"), () =>
frm.trigger("update_clearance_date")
);
frm.change_custom_button_type(__("Get Payment Entries"), null, "default");
frm.change_custom_button_type(__("Update Clearance Date"), null, "primary");
}
callback: function () {
frm.refresh();
},
});
},

View File

@@ -6,7 +6,7 @@ import frappe
from frappe import _, msgprint
from frappe.model.document import Document
from frappe.query_builder.custom import ConstantColumn
from frappe.utils import flt, fmt_money, getdate
from frappe.utils import flt, fmt_money, get_link_to_form, getdate
from pypika import Order
import erpnext
@@ -96,8 +96,11 @@ class BankClearance(Document):
if d.cheque_date and getdate(d.clearance_date) < getdate(d.cheque_date):
frappe.throw(
_("Row #{0}: Clearance date {1} cannot be before Cheque Date {2}").format(
d.idx, d.clearance_date, d.cheque_date
_("Row #{0}: For {1} Clearance date {2} cannot be before Cheque Date {3}").format(
d.idx,
get_link_to_form(d.payment_document, d.payment_entry),
d.clearance_date,
d.cheque_date,
)
)

View File

@@ -47,9 +47,11 @@ def validate_columns(data):
no_of_columns = max([len(d) for d in data])
if no_of_columns > 8:
if no_of_columns != 8:
frappe.throw(
_("More columns found than expected. Please compare the uploaded file with standard template"),
_(
"Columns are not according to template. Please compare the uploaded file with standard template"
),
title=(_("Wrong Template")),
)

View File

@@ -85,18 +85,16 @@ frappe.ui.form.on("Exchange Rate Revaluation", {
},
make_jv: function (frm) {
let revaluation_journal = null;
let zero_balance_journal = null;
frappe.call({
method: "make_jv_entries",
doc: frm.doc,
freeze: true,
freeze_message: "Making Journal Entries...",
freeze_message: __("Creating Journal Entries..."),
callback: function (r) {
if (r.message) {
let response = r.message;
if (response["revaluation_jv"] || response["zero_balance_jv"]) {
frappe.msgprint(__("Journals have been created"));
frappe.msgprint(__("Journal entries have been created"));
}
}
},

View File

@@ -25,30 +25,6 @@ frappe.ui.form.on("Journal Entry", {
refresh: function (frm) {
erpnext.toggle_naming_series();
if (frm.doc.repost_required && frm.doc.docstatus === 1) {
frm.set_intro(
__(
"Accounting entries for this Journal Entry need to be reposted. Please click on 'Repost' button to update."
)
);
frm.add_custom_button(__("Repost Accounting Entries"), () => {
frm.call({
doc: frm.doc,
method: "repost_accounting_entries",
freeze: true,
freeze_message: __("Reposting..."),
callback: (r) => {
if (!r.exc) {
frappe.msgprint(__("Accounting Entries are reposted."));
frm.refresh();
}
},
});
})
.removeClass("btn-default")
.addClass("btn-warning");
}
if (frm.doc.docstatus > 0) {
frm.add_custom_button(
__("Ledger"),

View File

@@ -64,8 +64,7 @@
"stock_entry",
"subscription_section",
"auto_repeat",
"amended_from",
"repost_required"
"amended_from"
],
"fields": [
{
@@ -544,15 +543,6 @@
"label": "Is System Generated",
"no_copy": 1,
"read_only": 1
},
{
"default": "0",
"fieldname": "repost_required",
"fieldtype": "Check",
"hidden": 1,
"label": "Repost Required",
"print_hide": 1,
"read_only": 1
}
],
"icon": "fa fa-file-text",
@@ -567,7 +557,7 @@
"table_fieldname": "payment_entries"
}
],
"modified": "2023-11-23 12:11:04.128015",
"modified": "2024-07-18 15:32:29.413598",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry",
@@ -618,4 +608,4 @@
"states": [],
"title_field": "title",
"track_changes": 1
}
}

View File

@@ -47,9 +47,7 @@ class JournalEntry(AccountsController):
if TYPE_CHECKING:
from frappe.types import DF
from erpnext.accounts.doctype.journal_entry_account.journal_entry_account import (
JournalEntryAccount,
)
from erpnext.accounts.doctype.journal_entry_account.journal_entry_account import JournalEntryAccount
accounts: DF.Table[JournalEntryAccount]
amended_from: DF.Link | None
@@ -197,14 +195,10 @@ class JournalEntry(AccountsController):
self.update_booked_depreciation()
def on_update_after_submit(self):
if hasattr(self, "repost_required"):
self.needs_repost = self.check_if_fields_updated(
fields_to_check=[], child_tables={"accounts": []}
)
if self.needs_repost:
self.validate_for_repost()
self.db_set("repost_required", self.needs_repost)
self.repost_accounting_entries()
self.needs_repost = self.check_if_fields_updated(fields_to_check=[], child_tables={"accounts": []})
if self.needs_repost:
self.validate_for_repost()
self.repost_accounting_entries()
def on_cancel(self):
# References for this Journal are removed on the `on_cancel` event in accounts_controller

View File

@@ -28,7 +28,12 @@ frappe.ui.form.on("Opening Invoice Creation Tool", {
frm.refresh_fields();
frm.page.clear_indicator();
frm.dashboard.hide_progress();
frappe.msgprint(__("Opening {0} Invoices created", [frm.doc.invoice_type]));
if (frm.doc.invoice_type == "Sales") {
frappe.msgprint(__("Opening Sales Invoices have been created."));
} else {
frappe.msgprint(__("Opening Purchase Invoices have been created."));
}
},
1500,
data.title
@@ -48,12 +53,19 @@ frappe.ui.form.on("Opening Invoice Creation Tool", {
!frm.doc.import_in_progress && frm.trigger("make_dashboard");
frm.page.set_primary_action(__("Create Invoices"), () => {
let btn_primary = frm.page.btn_primary.get(0);
let freeze_message;
if (frm.doc.invoice_type == "Sales") {
freeze_message = __("Creating Sales Invoices ...");
} else {
freeze_message = __("Creating Purchase Invoices ...");
}
return frm.call({
doc: frm.doc,
btn: $(btn_primary),
method: "make_invoices",
freeze: 1,
freeze_message: __("Creating {0} Invoice", [frm.doc.invoice_type]),
freeze_message: freeze_message,
});
});

View File

@@ -35,6 +35,11 @@ frappe.ui.form.on("Payment Entry", {
var account_types = ["Pay", "Internal Transfer"].includes(frm.doc.payment_type)
? ["Bank", "Cash"]
: [frappe.boot.party_account_types[frm.doc.party_type]];
if (frm.doc.party_type == "Shareholder") {
account_types.push("Equity");
}
return {
filters: {
account_type: ["in", account_types],
@@ -90,6 +95,9 @@ frappe.ui.form.on("Payment Entry", {
var account_types = ["Receive", "Internal Transfer"].includes(frm.doc.payment_type)
? ["Bank", "Cash"]
: [frappe.boot.party_account_types[frm.doc.party_type]];
if (frm.doc.party_type == "Shareholder") {
account_types.push("Equity");
}
return {
filters: {
account_type: ["in", account_types],
@@ -165,8 +173,25 @@ frappe.ui.form.on("Payment Entry", {
filters: filters,
};
});
},
frm.set_query("sales_taxes_and_charges_template", function () {
return {
filters: {
company: frm.doc.company,
disabled: false,
},
};
});
frm.set_query("purchase_taxes_and_charges_template", function () {
return {
filters: {
company: frm.doc.company,
disabled: false,
},
};
});
},
refresh: function (frm) {
erpnext.hide_company(frm);
frm.events.hide_unhide_fields(frm);
@@ -213,7 +238,7 @@ frappe.ui.form.on("Payment Entry", {
hide_unhide_fields: function (frm) {
var company_currency = frm.doc.company
? frappe.get_doc(":Company", frm.doc.company).default_currency
? frappe.get_doc(":Company", frm.doc.company)?.default_currency
: "";
frm.toggle_display(
@@ -280,7 +305,7 @@ frappe.ui.form.on("Payment Entry", {
set_dynamic_labels: function (frm) {
var company_currency = frm.doc.company
? frappe.get_doc(":Company", frm.doc.company).default_currency
? frappe.get_doc(":Company", frm.doc.company)?.default_currency
: "";
frm.set_currency_labels(
@@ -395,6 +420,12 @@ frappe.ui.form.on("Payment Entry", {
return {
query: "erpnext.controllers.queries.employee_query",
};
} else if (frm.doc.party_type == "Shareholder") {
return {
filters: {
company: frm.doc.company,
},
};
}
});
@@ -627,7 +658,7 @@ frappe.ui.form.on("Payment Entry", {
frm.set_value("source_exchange_rate", 1);
} else if (frm.doc.paid_from) {
if (["Internal Transfer", "Pay"].includes(frm.doc.payment_type)) {
let company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
let company_currency = frappe.get_doc(":Company", frm.doc.company)?.default_currency;
frappe.call({
method: "erpnext.setup.utils.get_exchange_rate",
args: {

View File

@@ -37,7 +37,6 @@ from erpnext.accounts.utils import (
get_account_currency,
get_balance_on,
get_outstanding_invoices,
get_party_types_from_account_type,
)
from erpnext.controllers.accounts_controller import (
AccountsController,
@@ -1119,90 +1118,82 @@ class PaymentEntry(AccountsController):
self.make_advance_gl_entries(cancel=cancel)
def add_party_gl_entries(self, gl_entries):
if self.party_account:
if self.payment_type == "Receive":
against_account = self.paid_to
else:
against_account = self.paid_from
if not self.party_account:
return
party_gl_dict = self.get_gl_dict(
if self.payment_type == "Receive":
against_account = self.paid_to
else:
against_account = self.paid_from
party_account_type = frappe.db.get_value("Party Type", self.party_type, "account_type")
party_gl_dict = 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,
},
item=self,
)
for d in self.get("references"):
# re-defining dr_or_cr for every reference in order to avoid the last value affecting calculation of reverse
dr_or_cr = "credit" if self.payment_type == "Receive" else "debit"
cost_center = self.cost_center
if d.reference_doctype == "Sales Invoice" and not cost_center:
cost_center = frappe.db.get_value(d.reference_doctype, d.reference_name, "cost_center")
gle = party_gl_dict.copy()
allocated_amount_in_company_currency = self.calculate_base_allocated_amount_for_reference(d)
if (
d.reference_doctype in ["Sales Invoice", "Purchase Invoice"]
and d.allocated_amount < 0
and (
(party_account_type == "Receivable" and self.payment_type == "Pay")
or (party_account_type == "Payable" and self.payment_type == "Receive")
)
):
# reversing dr_cr because because it will get reversed in gl processing due to negative amount
dr_or_cr = "debit" if dr_or_cr == "credit" else "credit"
gle.update(
{
"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,
},
item=self,
dr_or_cr: allocated_amount_in_company_currency,
dr_or_cr + "_in_account_currency": d.allocated_amount,
"against_voucher_type": d.reference_doctype,
"against_voucher": d.reference_name,
"cost_center": cost_center,
}
)
gl_entries.append(gle)
if self.unallocated_amount:
dr_or_cr = "credit" if self.payment_type == "Receive" else "debit"
exchange_rate = self.get_exchange_rate()
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,
}
)
dr_or_cr = "credit" if self.payment_type == "Receive" else "debit"
for d in self.get("references"):
# re-defining dr_or_cr for every reference in order to avoid the last value affecting calculation of reverse
dr_or_cr = "credit" if self.payment_type == "Receive" else "debit"
cost_center = self.cost_center
if d.reference_doctype == "Sales Invoice" and not cost_center:
cost_center = frappe.db.get_value(d.reference_doctype, d.reference_name, "cost_center")
gle = party_gl_dict.copy()
allocated_amount_in_company_currency = self.calculate_base_allocated_amount_for_reference(d)
reverse_dr_or_cr = 0
if d.reference_doctype in ["Sales Invoice", "Purchase Invoice"]:
is_return = frappe.db.get_value(d.reference_doctype, d.reference_name, "is_return")
payable_party_types = get_party_types_from_account_type("Payable")
receivable_party_types = get_party_types_from_account_type("Receivable")
if (
is_return
and self.party_type in receivable_party_types
and (self.payment_type == "Pay")
):
reverse_dr_or_cr = 1
elif (
is_return
and self.party_type in payable_party_types
and (self.payment_type == "Receive")
):
reverse_dr_or_cr = 1
if is_return and not reverse_dr_or_cr:
dr_or_cr = "debit" if dr_or_cr == "credit" else "credit"
if self.book_advance_payments_in_separate_party_account:
gle.update(
{
dr_or_cr: abs(allocated_amount_in_company_currency),
dr_or_cr + "_in_account_currency": abs(d.allocated_amount),
"against_voucher_type": d.reference_doctype,
"against_voucher": d.reference_name,
"cost_center": cost_center,
"against_voucher_type": "Payment Entry",
"against_voucher": self.name,
}
)
gl_entries.append(gle)
if self.unallocated_amount:
dr_or_cr = "credit" if self.payment_type == "Receive" else "debit"
exchange_rate = self.get_exchange_rate()
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,
}
)
if self.book_advance_payments_in_separate_party_account:
gle.update(
{
"against_voucher_type": "Payment Entry",
"against_voucher": self.name,
}
)
gl_entries.append(gle)
gl_entries.append(gle)
def make_advance_gl_entries(
self, entry: object | dict = None, cancel: bool = 0, update_outstanding: str = "Yes"
@@ -1749,7 +1740,7 @@ def get_outstanding_reference_documents(args, validate=False):
d["bill_no"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "bill_no")
# Get negative outstanding sales /purchase invoices
if args.get("party_type") != "Employee" and not args.get("voucher_no"):
if args.get("party_type") != "Employee":
negative_outstanding_invoices = get_negative_outstanding_invoices(
args.get("party_type"),
args.get("party"),

View File

@@ -36,7 +36,7 @@ frappe.ui.form.on("Payment Order", {
// payment Entry
if (frm.doc.docstatus === 1 && frm.doc.payment_order_type === "Payment Request") {
frm.add_custom_button(__("Create Payment Entries"), function () {
frm.add_custom_button(__("Create Journal Entries"), function () {
frm.trigger("make_payment_records");
});
}

View File

@@ -267,6 +267,7 @@ class PaymentReconciliation(Document):
conditions.append(doc.docstatus == 1)
conditions.append(doc[frappe.scrub(self.party_type)] == self.party)
conditions.append(doc.is_return == 1)
conditions.append(doc.outstanding_amount != 0)
if self.payment_name:
conditions.append(doc.name.like(f"%{self.payment_name}%"))

View File

@@ -1805,6 +1805,46 @@ class TestPaymentReconciliation(FrappeTestCase):
]
self.assertEqual(pl_entries, expected_ple)
def test_cr_note_payment_limit_filter(self):
transaction_date = nowdate()
amount = 100
for _ in range(6):
self.create_sales_invoice(qty=1, rate=amount, posting_date=transaction_date)
cr_note = self.create_sales_invoice(
qty=-1, rate=amount, posting_date=transaction_date, do_not_save=True, do_not_submit=True
)
cr_note.is_return = 1
cr_note = cr_note.save().submit()
pr = self.create_payment_reconciliation()
pr.get_unreconciled_entries()
self.assertEqual(len(pr.invoices), 6)
self.assertEqual(len(pr.payments), 6)
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}))
pr.reconcile()
pr.get_unreconciled_entries()
self.assertEqual(pr.get("invoices"), [])
self.assertEqual(pr.get("payments"), [])
self.create_sales_invoice(qty=1, rate=amount, posting_date=transaction_date)
cr_note = self.create_sales_invoice(
qty=-1, rate=amount, posting_date=transaction_date, do_not_save=True, do_not_submit=True
)
cr_note.is_return = 1
cr_note = cr_note.save().submit()
# Limit should not affect in fetching the unallocated cr_note
pr.invoice_limit = 5
pr.payment_limit = 5
pr.get_unreconciled_entries()
self.assertEqual(len(pr.invoices), 1)
self.assertEqual(len(pr.payments), 1)
def make_customer(customer_name, currency=None):
if not frappe.db.exists("Customer", customer_name):

View File

@@ -9,6 +9,7 @@
"transaction_date",
"column_break_2",
"naming_series",
"company",
"mode_of_payment",
"party_details",
"party_type",
@@ -144,6 +145,7 @@
"fieldname": "grand_total",
"fieldtype": "Currency",
"label": "Amount",
"non_negative": 1,
"options": "currency"
},
{
@@ -389,13 +391,20 @@
"options": "Payment Request",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"read_only": 1
}
],
"in_create": 1,
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2023-09-27 09:51:42.277638",
"modified": "2024-08-07 16:39:54.288002",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Request",
@@ -433,4 +442,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -15,7 +15,7 @@ from erpnext.accounts.doctype.payment_entry.payment_entry import (
)
from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate
from erpnext.accounts.party import get_party_account, get_party_bank_account
from erpnext.accounts.utils import get_account_currency
from erpnext.accounts.utils import get_account_currency, get_currency_precision
from erpnext.utilities import payment_app_import_guard
@@ -84,6 +84,7 @@ class PaymentRequest(Document):
subscription_plans: DF.Table[SubscriptionPlanDetail]
swift_number: DF.ReadOnly | None
transaction_date: DF.Date | None
company: DF.Link | None
# end: auto-generated types
def validate(self):
@@ -338,6 +339,17 @@ class PaymentRequest(Document):
payment_entry.received_amount = amount
payment_entry.get("references")[0].allocated_amount = amount
# Update 'Paid Amount' on Forex transactions
if self.currency != ref_doc.company_currency:
if (
self.payment_request_type == "Outward"
and payment_entry.paid_from_account_currency == ref_doc.company_currency
and payment_entry.paid_from_account_currency != payment_entry.paid_to_account_currency
):
payment_entry.paid_amount = payment_entry.base_paid_amount = (
payment_entry.target_exchange_rate * payment_entry.received_amount
)
for dimension in get_accounting_dimensions():
payment_entry.update({dimension: self.get(dimension)})
@@ -480,6 +492,7 @@ def make_payment_request(**args):
"message": gateway_account.get("message") or get_dummy_message(ref_doc),
"reference_doctype": args.dt,
"reference_name": args.dn,
"company": ref_doc.get("company"),
"party_type": args.get("party_type") or "Customer",
"party": args.get("party") or ref_doc.get("customer"),
"bank_account": bank_account,
@@ -500,8 +513,11 @@ def make_payment_request(**args):
if args.order_type == "Shopping Cart" or args.mute_email:
pr.flags.mute_email = True
pr.insert(ignore_permissions=True)
if frappe.db.get_single_value("Accounts Settings", "create_pr_in_draft_status", cache=True):
pr.insert(ignore_permissions=True)
if args.submit_doc:
if pr.get("__unsaved"):
pr.insert(ignore_permissions=True)
pr.submit()
if args.order_type == "Shopping Cart":
@@ -540,7 +556,7 @@ def get_amount(ref_doc, payment_account=None):
grand_total = ref_doc.outstanding_amount
if grand_total > 0:
return grand_total
return flt(grand_total, get_currency_precision())
else:
frappe.throw(_("Payment Entry is already created"))

View File

@@ -4,10 +4,12 @@
import unittest
import frappe
from frappe.tests.utils import FrappeTestCase
from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
from erpnext.setup.utils import get_exchange_rate
@@ -32,7 +34,7 @@ payment_method = [
]
class TestPaymentRequest(unittest.TestCase):
class TestPaymentRequest(FrappeTestCase):
def setUp(self):
if not frappe.db.get_value("Payment Gateway", payment_gateway["gateway"], "name"):
frappe.get_doc(payment_gateway).insert(ignore_permissions=True)
@@ -260,3 +262,19 @@ class TestPaymentRequest(unittest.TestCase):
# Try to make Payment Request more than SO amount, should give validation
pr2.grand_total = 900
self.assertRaises(frappe.ValidationError, pr2.save)
def test_conversion_on_foreign_currency_accounts(self):
po_doc = create_purchase_order(supplier="_Test Supplier USD", currency="USD", do_not_submit=1)
po_doc.conversion_rate = 80
po_doc.items[0].qty = 1
po_doc.items[0].rate = 10
po_doc.save().submit()
pr = make_payment_request(dt=po_doc.doctype, dn=po_doc.name, recipient_id="nabin@erpnext.com")
pr = frappe.get_doc(pr).save().submit()
pe = pr.create_payment_entry()
self.assertEqual(pe.base_paid_amount, 800)
self.assertEqual(pe.paid_amount, 800)
self.assertEqual(pe.base_received_amount, 800)
self.assertEqual(pe.received_amount, 10)

View File

@@ -87,19 +87,15 @@ class POSClosingEntry(StatusUpdater):
as_dict=1,
)[0]
if pos_invoice.consolidated_invoice:
invalid_row.setdefault("msg", []).append(
_("POS Invoice is {}").format(frappe.bold("already consolidated"))
)
invalid_row.setdefault("msg", []).append(_("POS Invoice is already consolidated"))
invalid_rows.append(invalid_row)
continue
if pos_invoice.pos_profile != self.pos_profile:
invalid_row.setdefault("msg", []).append(
_("POS Profile doesn't matches {}").format(frappe.bold(self.pos_profile))
_("POS Profile doesn't match {}").format(frappe.bold(self.pos_profile))
)
if pos_invoice.docstatus != 1:
invalid_row.setdefault("msg", []).append(
_("POS Invoice is not {}").format(frappe.bold("submitted"))
)
invalid_row.setdefault("msg", []).append(_("POS Invoice is not submitted"))
if pos_invoice.owner != self.user:
invalid_row.setdefault("msg", []).append(
_("POS Invoice isn't created by user {}").format(frappe.bold(self.owner))

View File

@@ -17,6 +17,10 @@ from erpnext.accounts.doctype.pos_invoice.test_pos_invoice import create_pos_inv
from erpnext.accounts.doctype.pos_opening_entry.test_pos_opening_entry import create_opening_entry
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
from erpnext.selling.page.point_of_sale.point_of_sale import get_items
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.serial_and_batch_bundle.test_serial_and_batch_bundle import (
get_batch_from_bundle,
)
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
@@ -179,6 +183,94 @@ class TestPOSClosingEntry(unittest.TestCase):
accounting_dimension_department.save()
disable_dimension()
def test_merging_into_sales_invoice_for_batched_item(self):
frappe.flags.print_message = False
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import (
init_user_and_profile,
)
from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import (
consolidate_pos_invoices,
)
from erpnext.stock.doctype.batch.batch import get_batch_qty
frappe.db.sql("delete from `tabPOS Invoice`")
item_doc = make_item(
"_Test Item With Batch FOR POS Merge Test",
properties={
"is_stock_item": 1,
"has_batch_no": 1,
"batch_number_series": "BATCH-PM-POS-MERGE-.####",
"create_new_batch": 1,
},
)
item_code = item_doc.name
se = make_stock_entry(
target="_Test Warehouse - _TC",
item_code=item_code,
qty=10,
basic_rate=100,
use_serial_batch_fields=0,
)
batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle)
test_user, pos_profile = init_user_and_profile()
opening_entry = create_opening_entry(pos_profile, test_user.name)
pos_inv = create_pos_invoice(
item_code=item_code, qty=5, rate=300, use_serial_batch_fields=1, batch_no=batch_no
)
pos_inv2 = create_pos_invoice(
item_code=item_code, qty=5, rate=300, use_serial_batch_fields=1, batch_no=batch_no
)
batch_qty = frappe.db.get_value("Batch", batch_no, "batch_qty")
self.assertEqual(batch_qty, 10)
batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code)
self.assertEqual(batch_qty_with_pos, 0.0)
pcv_doc = make_closing_entry_from_opening(opening_entry)
pcv_doc.submit()
piv_merge = frappe.db.get_value("POS Invoice Merge Log", {"pos_closing_entry": pcv_doc.name}, "name")
self.assertTrue(piv_merge)
piv_merge_doc = frappe.get_doc("POS Invoice Merge Log", piv_merge)
self.assertTrue(piv_merge_doc.pos_invoices[0].pos_invoice)
self.assertTrue(piv_merge_doc.pos_invoices[1].pos_invoice)
pos_inv.load_from_db()
self.assertTrue(pos_inv.consolidated_invoice)
pos_inv2.load_from_db()
self.assertTrue(pos_inv2.consolidated_invoice)
batch_qty = frappe.db.get_value("Batch", batch_no, "batch_qty")
self.assertEqual(batch_qty, 0.0)
batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code)
self.assertEqual(batch_qty_with_pos, 0.0)
frappe.flags.print_message = True
pcv_doc.reload()
pcv_doc.cancel()
batch_qty = frappe.db.get_value("Batch", batch_no, "batch_qty")
self.assertEqual(batch_qty, 10)
batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code)
self.assertEqual(batch_qty_with_pos, 0.0)
pos_inv.reload()
pos_inv2.reload()
pos_inv.cancel()
pos_inv2.cancel()
batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code)
self.assertEqual(batch_qty_with_pos, 10.0)
def init_user_and_profile(**args):
user = "test@example.com"

View File

@@ -188,7 +188,7 @@ class POSInvoice(SalesInvoice):
def validate(self):
if not cint(self.is_pos):
frappe.throw(
_("POS Invoice should have {} field checked.").format(frappe.bold("Include Payment"))
_("POS Invoice should have the field {0} checked.").format(frappe.bold(_("Include Payment")))
)
# run on validate method of selling controller
@@ -229,7 +229,9 @@ class POSInvoice(SalesInvoice):
self.check_phone_payments()
self.set_status(update=True)
self.make_bundle_for_sales_purchase_return()
self.submit_serial_batch_bundle()
for table_name in ["items", "packed_items"]:
self.make_bundle_using_old_serial_batch_fields(table_name)
self.submit_serial_batch_bundle(table_name)
if self.coupon_code:
from erpnext.accounts.doctype.pricing_rule.utils import update_coupon_code_count
@@ -283,10 +285,11 @@ class POSInvoice(SalesInvoice):
{"is_cancelled": 1, "voucher_no": ""},
)
frappe.get_doc("Serial and Batch Bundle", row.serial_and_batch_bundle).cancel()
row.db_set("serial_and_batch_bundle", None)
def submit_serial_batch_bundle(self):
for item in self.items:
def submit_serial_batch_bundle(self, table_name):
for item in self.get(table_name):
if item.serial_and_batch_bundle:
doc = frappe.get_doc("Serial and Batch Bundle", item.serial_and_batch_bundle)
@@ -355,10 +358,16 @@ class POSInvoice(SalesInvoice):
error_msg = []
for d in self.get("items"):
error_msg = ""
if d.get("has_serial_no") and not d.serial_and_batch_bundle:
if d.get("has_serial_no") and (
(not d.use_serial_batch_fields and not d.serial_and_batch_bundle)
or (d.use_serial_batch_fields and not d.serial_no)
):
error_msg = f"Row #{d.idx}: Please select Serial No. for item {bold(d.item_code)}"
elif d.get("has_batch_no") and not d.serial_and_batch_bundle:
elif d.get("has_batch_no") and (
(not d.use_serial_batch_fields and not d.serial_and_batch_bundle)
or (d.use_serial_batch_fields and not d.batch_no)
):
error_msg = f"Row #{d.idx}: Please select Batch No. for item {bold(d.item_code)}"
if error_msg:

View File

@@ -780,8 +780,6 @@ class TestPOSInvoice(unittest.TestCase):
pos_inv1.submit()
pos_inv1.reload()
self.assertFalse(pos_inv1.items[0].serial_and_batch_bundle)
batches = get_auto_batch_nos(
frappe._dict({"item_code": "_BATCH ITEM Test For Reserve", "warehouse": "_Test Warehouse - _TC"})
)
@@ -957,7 +955,7 @@ def create_pos_invoice(**args):
pos_inv.set_missing_values()
bundle_id = None
if args.get("batch_no") or args.get("serial_no"):
if not args.use_serial_batch_fields and (args.get("batch_no") or args.get("serial_no")):
type_of_transaction = args.type_of_transaction or "Outward"
if pos_inv.is_return:
@@ -998,6 +996,9 @@ def create_pos_invoice(**args):
"expense_account": args.expense_account or "Cost of Goods Sold - _TC",
"cost_center": args.cost_center or "_Test Cost Center - _TC",
"serial_and_batch_bundle": bundle_id,
"use_serial_batch_fields": args.use_serial_batch_fields,
"serial_no": args.serial_no if args.use_serial_batch_fields else None,
"batch_no": args.batch_no if args.use_serial_batch_fields else None,
}
# append in pos invoice items without item_code by checking flag without_item_code
if args.without_item_code:
@@ -1023,6 +1024,8 @@ def create_pos_invoice(**args):
pos_inv.insert()
if not args.do_not_submit:
pos_inv.submit()
if args.use_serial_batch_fields:
pos_inv.reload()
else:
pos_inv.payment_schedule = []
else:

View File

@@ -634,7 +634,6 @@
"depends_on": "eval:doc.use_serial_batch_fields === 1",
"fieldname": "batch_no",
"fieldtype": "Link",
"hidden": 1,
"label": "Batch No",
"options": "Batch",
"print_hide": 1
@@ -655,7 +654,6 @@
"depends_on": "eval:doc.use_serial_batch_fields === 1",
"fieldname": "serial_no",
"fieldtype": "Text",
"hidden": 1,
"in_list_view": 1,
"label": "Serial No",
"oldfieldname": "serial_no",
@@ -827,7 +825,7 @@
"read_only": 1
},
{
"depends_on": "eval:doc.use_serial_batch_fields === 1",
"depends_on": "eval:doc.use_serial_batch_fields === 0 || doc.serial_and_batch_bundle",
"fieldname": "serial_and_batch_bundle",
"fieldtype": "Link",
"label": "Serial and Batch Bundle",
@@ -853,7 +851,7 @@
],
"istable": 1,
"links": [],
"modified": "2024-02-25 15:50:17.140269",
"modified": "2024-05-07 15:56:53.343317",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Invoice Item",
@@ -863,4 +861,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -97,16 +97,15 @@ class POSInvoiceMergeLog(Document):
return_against_status = frappe.db.get_value("POS Invoice", return_against, "status")
if return_against_status != "Consolidated":
# if return entry is not getting merged in the current pos closing and if it is not consolidated
bold_unconsolidated = frappe.bold("not Consolidated")
msg = _("Row #{}: Original Invoice {} of return invoice {} is {}.").format(
d.idx, bold_return_against, bold_pos_invoice, bold_unconsolidated
)
msg = _(
"Row #{}: The original Invoice {} of return invoice {} is not consolidated."
).format(d.idx, bold_return_against, bold_pos_invoice)
msg += " "
msg += _(
"Original invoice should be consolidated before or along with the return invoice."
"The original invoice should be consolidated before or along with the return invoice."
)
msg += "<br><br>"
msg += _("You can add original invoice {} manually to proceed.").format(
msg += _("You can add the original invoice {} manually to proceed.").format(
bold_return_against
)
frappe.throw(msg)
@@ -131,6 +130,7 @@ class POSInvoiceMergeLog(Document):
pos_invoice_docs = [frappe.get_cached_doc("POS Invoice", d.pos_invoice) for d in self.pos_invoices]
self.update_pos_invoices(pos_invoice_docs)
self.serial_and_batch_bundle_reference_for_pos_invoice()
self.cancel_linked_invoices()
def process_merging_into_sales_invoice(self, data):
@@ -191,6 +191,7 @@ class POSInvoiceMergeLog(Document):
for i in items:
if (
i.item_code == item.item_code
and not i.serial_and_batch_bundle
and not i.serial_no
and not i.batch_no
and i.uom == item.uom
@@ -312,6 +313,12 @@ class POSInvoiceMergeLog(Document):
doc.set_status(update=True)
doc.save()
def serial_and_batch_bundle_reference_for_pos_invoice(self):
for d in self.pos_invoices:
pos_invoice = frappe.get_doc("POS Invoice", d.pos_invoice)
for table_name in ["items", "packed_items"]:
pos_invoice.set_serial_and_batch_bundle(table_name)
def cancel_linked_invoices(self):
for si_name in [self.consolidated_invoice, self.consolidated_credit_note]:
if not si_name:

View File

@@ -186,7 +186,8 @@ class PricingRule(Document):
if not self.priority:
throw(
_("As the field {0} is enabled, the field {1} is mandatory.").format(
frappe.bold("Apply Discount on Discounted Rate"), frappe.bold("Priority")
frappe.bold(_("Apply Discount on Discounted Rate")),
frappe.bold(_("Priority")),
)
)
@@ -194,7 +195,7 @@ class PricingRule(Document):
throw(
_(
"As the field {0} is enabled, the value of the field {1} should be more than 1."
).format(frappe.bold("Apply Discount on Discounted Rate"), frappe.bold("Priority"))
).format(frappe.bold(_("Apply Discount on Discounted Rate")), frappe.bold(_("Priority")))
)
def validate_applicable_for_selling_or_buying(self):

View File

@@ -6,7 +6,9 @@ import unittest
import frappe
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.controllers.sales_and_purchase_return import make_return_doc
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.get_item_details import get_item_details
@@ -1311,6 +1313,69 @@ class TestPricingRule(unittest.TestCase):
pricing_rule.is_recursive = True
self.assertRaises(frappe.ValidationError, pricing_rule.save)
def test_ignore_pricing_rule_for_credit_note(self):
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule")
pricing_rule = make_pricing_rule(
discount_percentage=20,
selling=1,
buying=1,
priority=1,
title="_Test Pricing Rule",
)
si = create_sales_invoice(do_not_submit=True, customer="_Test Customer 1", qty=1)
item = si.items[0]
si.submit()
self.assertEqual(item.discount_percentage, 20)
self.assertEqual(item.rate, 80)
# change discount on pricing rule
pricing_rule.discount_percentage = 30
pricing_rule.save()
credit_note = make_return_doc(si.doctype, si.name)
credit_note.save()
self.assertEqual(credit_note.ignore_pricing_rule, 1)
self.assertEqual(credit_note.pricing_rules, [])
self.assertEqual(credit_note.items[0].discount_percentage, 20)
self.assertEqual(credit_note.items[0].rate, 80)
self.assertEqual(credit_note.items[0].pricing_rules, None)
credit_note.delete()
si.cancel()
def test_ignore_pricing_rule_for_debit_note(self):
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule")
pricing_rule = make_pricing_rule(
discount_percentage=20,
buying=1,
priority=1,
title="_Test Pricing Rule",
)
pi = make_purchase_invoice(do_not_submit=True, supplier="_Test Supplier 1", qty=1)
item = pi.items[0]
pi.submit()
self.assertEqual(item.discount_percentage, 20)
self.assertEqual(item.rate, 40)
# change discount on pricing rule
pricing_rule.discount_percentage = 30
pricing_rule.save()
# create debit note from purchase invoice
debit_note = make_return_doc(pi.doctype, pi.name)
debit_note.save()
self.assertEqual(debit_note.ignore_pricing_rule, 1)
self.assertEqual(debit_note.pricing_rules, [])
self.assertEqual(debit_note.items[0].discount_percentage, 20)
self.assertEqual(debit_note.items[0].rate, 40)
self.assertEqual(debit_note.items[0].pricing_rules, None)
debit_note.delete()
pi.cancel()
test_dependencies = ["Campaign"]

View File

@@ -486,7 +486,7 @@ def get_qty_and_rate_for_other_item(doc, pr_doc, pricing_rules, row_item):
continue
stock_qty = row.get("qty") * (row.get("conversion_factor") or 1.0)
amount = stock_qty * (row.get("price_list_rate") or row.get("rate"))
amount = stock_qty * (flt(row.get("price_list_rate")) or flt(row.get("rate")))
pricing_rules = filter_pricing_rules_for_qty_amount(stock_qty, amount, pricing_rules, row)
if pricing_rules and pricing_rules[0]:

View File

@@ -20,6 +20,17 @@ frappe.ui.form.on("Process Payment Reconciliation", {
},
};
});
frm.set_query("default_advance_account", function (doc) {
return {
filters: {
company: doc.company,
is_group: 0,
account_type: doc.party_type == "Customer" ? "Receivable" : "Payable",
root_type: doc.party_type == "Customer" ? "Liability" : "Asset",
},
};
});
frm.set_query("cost_center", function (doc) {
return {
filters: {
@@ -102,6 +113,7 @@ frappe.ui.form.on("Process Payment Reconciliation", {
company(frm) {
frm.set_value("party", "");
frm.set_value("receivable_payable_account", "");
frm.set_value("default_advance_account", "");
},
party_type(frm) {
frm.set_value("party", "");
@@ -109,6 +121,7 @@ frappe.ui.form.on("Process Payment Reconciliation", {
party(frm) {
frm.set_value("receivable_payable_account", "");
frm.set_value("default_advance_account", "");
if (!frm.doc.receivable_payable_account && frm.doc.party_type && frm.doc.party) {
return frappe.call({
method: "erpnext.accounts.party.get_party_account",
@@ -116,10 +129,16 @@ frappe.ui.form.on("Process Payment Reconciliation", {
company: frm.doc.company,
party_type: frm.doc.party_type,
party: frm.doc.party,
include_advance: 1,
},
callback: (r) => {
if (!r.exc && r.message) {
frm.set_value("receivable_payable_account", r.message);
if (typeof r.message === "string") {
frm.set_value("receivable_payable_account", r.message);
} else if (Array.isArray(r.message)) {
frm.set_value("receivable_payable_account", r.message[0]);
frm.set_value("default_advance_account", r.message[1]);
}
}
frm.refresh();
},

View File

@@ -13,6 +13,7 @@
"column_break_io6c",
"party",
"receivable_payable_account",
"default_advance_account",
"filter_section",
"from_invoice_date",
"to_invoice_date",
@@ -141,12 +142,23 @@
{
"fieldname": "section_break_a8yx",
"fieldtype": "Section Break"
},
{
"depends_on": "eval:doc.party",
"description": "Only 'Payment Entries' made against this advance account are supported.",
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/advance-in-separate-party-account",
"fieldname": "default_advance_account",
"fieldtype": "Link",
"label": "Default Advance Account",
"mandatory_depends_on": "doc.party_type",
"options": "Account",
"reqd": 1
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2023-08-11 10:56:51.699137",
"modified": "2024-08-27 14:48:56.715320",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Process Payment Reconciliation",
@@ -180,4 +192,4 @@
"sort_order": "DESC",
"states": [],
"title_field": "company"
}
}

View File

@@ -23,6 +23,7 @@ class ProcessPaymentReconciliation(Document):
bank_cash_account: DF.Link | None
company: DF.Link
cost_center: DF.Link | None
default_advance_account: DF.Link
error_log: DF.LongText | None
from_invoice_date: DF.Date | None
from_payment_date: DF.Date | None
@@ -101,6 +102,7 @@ def get_pr_instance(doc: str):
"party_type",
"party",
"receivable_payable_account",
"default_advance_account",
"from_invoice_date",
"to_invoice_date",
"from_payment_date",

View File

@@ -16,6 +16,7 @@
"cost_center",
"territory",
"ignore_exchange_rate_revaluation_journals",
"ignore_cr_dr_notes",
"column_break_14",
"to_date",
"finance_book",
@@ -383,10 +384,16 @@
"fieldname": "ignore_exchange_rate_revaluation_journals",
"fieldtype": "Check",
"label": "Ignore Exchange Rate Revaluation Journals"
},
{
"default": "0",
"fieldname": "ignore_cr_dr_notes",
"fieldtype": "Check",
"label": "Ignore System Generated Credit / Debit Notes"
}
],
"links": [],
"modified": "2023-12-18 12:20:08.965120",
"modified": "2024-08-13 10:41:18.381165",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Process Statement Of Accounts",

View File

@@ -54,6 +54,7 @@ class ProcessStatementOfAccounts(Document):
frequency: DF.Literal["Weekly", "Monthly", "Quarterly"]
from_date: DF.Date | None
group_by: DF.Literal["", "Group by Voucher", "Group by Voucher (Consolidated)"]
ignore_cr_dr_notes: DF.Check
ignore_exchange_rate_revaluation_journals: DF.Check
include_ageing: DF.Check
include_break: DF.Check
@@ -133,6 +134,9 @@ def get_statement_dict(doc, get_statement_dict=False):
if doc.ignore_exchange_rate_revaluation_journals:
filters.update({"ignore_err": True})
if doc.ignore_cr_dr_notes:
filters.update({"ignore_cr_dr_notes": True})
if doc.report == "General Ledger":
filters.update(get_gl_filters(doc, entry, tax_id, presentation_currency))
col, res = get_soa(filters)

View File

@@ -2,6 +2,18 @@
// For license information, please see license.txt
frappe.ui.form.on("Promotional Scheme", {
setup: function (frm) {
frm.set_query("for_price_list", "price_discount_slabs", (doc) => {
return {
filters: {
selling: doc.selling,
buying: doc.buying,
currency: doc.currency,
},
};
});
},
refresh: function (frm) {
frm.trigger("set_options_for_applicable_for");
frm.trigger("toggle_reqd_apply_on");

View File

@@ -51,6 +51,7 @@ price_discount_fields = [
"discount_percentage",
"validate_applied_rule",
"apply_multiple_pricing_rules",
"for_price_list",
]
product_discount_fields = [
@@ -63,6 +64,7 @@ product_discount_fields = [
"recurse_for",
"apply_recursion_over",
"apply_multiple_pricing_rules",
"round_free_qty",
]

View File

@@ -21,6 +21,7 @@
"rate",
"discount_amount",
"discount_percentage",
"for_price_list",
"section_break_11",
"warehouse",
"threshold_percentage",
@@ -120,6 +121,13 @@
"fieldtype": "Float",
"label": "Discount Percentage"
},
{
"depends_on": "eval:doc.rate_or_discount!=\"Rate\"",
"fieldname": "for_price_list",
"fieldtype": "Link",
"label": "For Price List",
"options": "Price List"
},
{
"fieldname": "section_break_11",
"fieldtype": "Section Break"
@@ -169,7 +177,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2021-11-16 00:25:33.843996",
"modified": "2024-07-23 12:33:46.574950",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Promotional Scheme Price Discount",
@@ -177,4 +185,4 @@
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}
}

View File

@@ -19,6 +19,7 @@ class PromotionalSchemePriceDiscount(Document):
disable: DF.Check
discount_amount: DF.Currency
discount_percentage: DF.Float
for_price_list: DF.Link | None
max_amount: DF.Currency
max_qty: DF.Float
min_amount: DF.Currency

View File

@@ -22,6 +22,7 @@
"column_break_9",
"free_item_uom",
"free_item_rate",
"round_free_qty",
"section_break_12",
"warehouse",
"threshold_percentage",
@@ -181,12 +182,18 @@
"fieldtype": "Float",
"label": "Apply Recursion Over (As Per Transaction UOM)",
"mandatory_depends_on": "is_recursive"
},
{
"default": "0",
"fieldname": "round_free_qty",
"fieldtype": "Check",
"label": "Round Free Qty"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2024-03-12 12:53:58.199108",
"modified": "2024-07-22 17:25:07.880984",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Promotional Scheme Product Discount",
@@ -195,4 +202,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -53,6 +53,7 @@ class PromotionalSchemeProductDiscount(Document):
"20",
]
recurse_for: DF.Float
round_free_qty: DF.Check
rule_description: DF.SmallText
same_item: DF.Check
threshold_percentage: DF.Percent

View File

@@ -77,31 +77,6 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
erpnext.accounts.ledger_preview.show_stock_ledger_preview(this.frm);
}
if (this.frm.doc.repost_required && this.frm.doc.docstatus === 1) {
this.frm.set_intro(
__(
"Accounting entries for this invoice need to be reposted. Please click on 'Repost' button to update."
)
);
this.frm
.add_custom_button(__("Repost Accounting Entries"), () => {
this.frm.call({
doc: this.frm.doc,
method: "repost_accounting_entries",
freeze: true,
freeze_message: __("Reposting..."),
callback: (r) => {
if (!r.exc) {
frappe.msgprint(__("Accounting Entries are reposted."));
me.frm.refresh();
}
},
});
})
.removeClass("btn-default")
.addClass("btn-warning");
}
if (!doc.is_return && doc.docstatus == 1 && doc.outstanding_amount != 0) {
if (doc.on_hold) {
this.frm.add_custom_button(

View File

@@ -170,7 +170,6 @@
"against_expense_account",
"column_break_63",
"unrealized_profit_loss_account",
"repost_required",
"subscription_section",
"subscription",
"auto_repeat",
@@ -364,7 +363,8 @@
"description": "Once set, this invoice will be on hold till the set date",
"fieldname": "release_date",
"fieldtype": "Date",
"label": "Release Date"
"label": "Release Date",
"search_index": 1
},
{
"fieldname": "cb_17",
@@ -1603,15 +1603,6 @@
"fieldtype": "Check",
"label": "Use Company Default Round Off Cost Center"
},
{
"default": "0",
"fieldname": "repost_required",
"fieldtype": "Check",
"hidden": 1,
"label": "Repost Required",
"options": "Account",
"read_only": 1
},
{
"default": "0",
"fieldname": "use_transaction_date_exchange_rate",
@@ -1639,7 +1630,7 @@
"idx": 204,
"is_submittable": 1,
"links": [],
"modified": "2024-04-11 11:28:42.802211",
"modified": "2024-07-25 19:42:36.931278",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",

View File

@@ -159,7 +159,6 @@ class PurchaseInvoice(BuyingController):
rejected_warehouse: DF.Link | None
release_date: DF.Date | None
remarks: DF.SmallText | None
repost_required: DF.Check
represents_company: DF.Link | None
return_against: DF.Link | None
rounded_total: DF.Currency
@@ -286,7 +285,6 @@ class PurchaseInvoice(BuyingController):
self.set_against_expense_account()
self.validate_write_off_account()
self.validate_multiple_billing("Purchase Receipt", "pr_detail", "amount")
self.create_remarks()
self.set_status()
self.validate_purchase_receipt_if_update_stock()
validate_inter_company_party(
@@ -323,10 +321,11 @@ class PurchaseInvoice(BuyingController):
def create_remarks(self):
if not self.remarks:
if self.bill_no and self.bill_date:
self.remarks = _("Against Supplier Invoice {0} dated {1}").format(
self.bill_no, formatdate(self.bill_date)
)
if self.bill_no:
self.remarks = _("Against Supplier Invoice {0}").format(self.bill_no)
if self.bill_date:
self.remarks += " " + _("dated {0}").format(formatdate(self.bill_date))
else:
self.remarks = _("No Remarks")
@@ -378,16 +377,16 @@ class PurchaseInvoice(BuyingController):
if account.report_type != "Balance Sheet":
frappe.throw(
_(
"Please ensure {} account is a Balance Sheet account. You can change the parent account to a Balance Sheet account or select a different account."
).format(frappe.bold("Credit To")),
"Please ensure that the {0} account is a Balance Sheet account. You can change the parent account to a Balance Sheet account or select a different account."
).format(frappe.bold(_("Credit To"))),
title=_("Invalid Account"),
)
if self.supplier and account.account_type != "Payable":
frappe.throw(
_(
"Please ensure {} account {} is a Payable account. Change the account type to Payable or select a different account."
).format(frappe.bold("Credit To"), frappe.bold(self.credit_to)),
"Please ensure that the {0} account {1} is a Payable account. You can change the account type to Payable or select a different account."
).format(frappe.bold(_("Credit To")), frappe.bold(self.credit_to)),
title=_("Invalid Account"),
)
@@ -635,7 +634,7 @@ class PurchaseInvoice(BuyingController):
"To submit the invoice without purchase order please set {0} as {1} in {2}"
).format(
frappe.bold(_("Purchase Order Required")),
frappe.bold("No"),
frappe.bold(_("No")),
get_link_to_form("Buying Settings", "Buying Settings", "Buying Settings"),
)
throw(msg, title=_("Mandatory Purchase Order"))
@@ -656,7 +655,7 @@ class PurchaseInvoice(BuyingController):
"To submit the invoice without purchase receipt please set {0} as {1} in {2}"
).format(
frappe.bold(_("Purchase Receipt Required")),
frappe.bold("No"),
frappe.bold(_("No")),
get_link_to_form("Buying Settings", "Buying Settings", "Buying Settings"),
)
throw(msg, title=_("Mandatory Purchase Receipt"))
@@ -748,6 +747,9 @@ class PurchaseInvoice(BuyingController):
validate_docs_for_voucher_types(["Purchase Invoice"])
validate_docs_for_deferred_accounting([], [self.name])
def before_submit(self):
self.create_remarks()
def on_submit(self):
super().on_submit()
@@ -796,19 +798,17 @@ class PurchaseInvoice(BuyingController):
self.process_common_party_accounting()
def on_update_after_submit(self):
if hasattr(self, "repost_required"):
fields_to_check = [
"cash_bank_account",
"write_off_account",
"unrealized_profit_loss_account",
"is_opening",
]
child_tables = {"items": ("expense_account",), "taxes": ("account_head",)}
self.needs_repost = self.check_if_fields_updated(fields_to_check, child_tables)
if self.needs_repost:
self.validate_for_repost()
self.db_set("repost_required", self.needs_repost)
self.repost_accounting_entries()
fields_to_check = [
"cash_bank_account",
"write_off_account",
"unrealized_profit_loss_account",
"is_opening",
]
child_tables = {"items": ("expense_account",), "taxes": ("account_head",)}
self.needs_repost = self.check_if_fields_updated(fields_to_check, child_tables)
if self.needs_repost:
self.validate_for_repost()
self.repost_accounting_entries()
def make_gl_entries(self, gl_entries=None, from_repost=False):
update_outstanding = "No" if (cint(self.is_paid) or self.write_off_account) else "Yes"
@@ -1265,7 +1265,11 @@ class PurchaseInvoice(BuyingController):
def update_gross_purchase_amount_for_linked_assets(self, item):
assets = frappe.db.get_all(
"Asset",
filters={"purchase_invoice": self.name, "item_code": item.item_code},
filters={
"purchase_invoice": self.name,
"item_code": item.item_code,
"purchase_invoice_item": ("in", [item.name, ""]),
},
fields=["name", "asset_quantity"],
)
for asset in assets:
@@ -1705,6 +1709,9 @@ class PurchaseInvoice(BuyingController):
self.db_set("release_date", None)
def set_tax_withholding(self):
self.set("advance_tax", [])
self.set("tax_withheld_vouchers", [])
if not self.apply_tds:
return
@@ -1746,8 +1753,6 @@ class PurchaseInvoice(BuyingController):
self.remove(d)
## Add pending vouchers on which tax was withheld
self.set("tax_withheld_vouchers", [])
for voucher_no, voucher_details in voucher_wise_amount.items():
self.append(
"tax_withheld_vouchers",
@@ -1762,7 +1767,6 @@ class PurchaseInvoice(BuyingController):
self.calculate_taxes_and_totals()
def allocate_advance_tds(self, tax_withholding_details, advance_taxes):
self.set("advance_tax", [])
for tax in advance_taxes:
allocated_amount = 0
pending_amount = flt(tax.tax_amount - tax.allocated_amount)

View File

@@ -2014,8 +2014,6 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
["Service - _TC", 1000, 0.0, nowdate()],
]
check_gl_entries(self, pi.name, expected_gle, nowdate())
pi.load_from_db()
self.assertFalse(pi.repost_required)
@change_settings("Buying Settings", {"supplier_group": None})
def test_purchase_invoice_without_supplier_group(self):
@@ -2238,6 +2236,62 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
self.assertEqual(pi_expected_values[i][1], gle.debit)
self.assertEqual(pi_expected_values[i][2], gle.credit)
def test_adjust_incoming_rate_from_pi_with_multi_currency(self):
from erpnext.stock.doctype.landed_cost_voucher.test_landed_cost_voucher import (
make_landed_cost_voucher,
)
frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0)
frappe.db.set_single_value("Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 1)
# Increase the cost of the item
pr = make_purchase_receipt(
qty=10, rate=1, currency="USD", do_not_save=1, supplier="_Test Supplier USD"
)
pr.conversion_rate = 6300
pr.plc_conversion_rate = 1
pr.save()
pr.submit()
self.assertEqual(pr.conversion_rate, 6300)
self.assertEqual(pr.plc_conversion_rate, 1)
self.assertEqual(pr.base_grand_total, 6300 * 10)
stock_value_difference = frappe.db.get_value(
"Stock Ledger Entry",
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name},
"stock_value_difference",
)
self.assertEqual(stock_value_difference, 6300 * 10)
make_landed_cost_voucher(
company=pr.company,
receipt_document_type="Purchase Receipt",
receipt_document=pr.name,
charges=3000,
distribute_charges_based_on="Qty",
)
pi = create_purchase_invoice_from_receipt(pr.name)
for row in pi.items:
row.rate = 1.1
pi.save()
pi.submit()
stock_value_difference = frappe.db.get_value(
"Stock Ledger Entry",
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name},
"stock_value_difference",
)
self.assertEqual(stock_value_difference, 7230 * 10)
frappe.db.set_single_value("Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 0)
frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 1)
def set_advance_flag(company, flag, default_account):
frappe.db.set_value(

View File

@@ -57,6 +57,7 @@
"base_net_rate",
"base_net_amount",
"valuation_rate",
"sales_incoming_rate",
"item_tax_amount",
"landed_cost_voucher_amount",
"rm_supp_cost",
@@ -958,12 +959,22 @@
"print_hide": 1,
"read_only": 1,
"search_index": 1
},
{
"description": "Valuation rate for the item as per Sales Invoice (Only for Internal Transfers)",
"fieldname": "sales_incoming_rate",
"fieldtype": "Currency",
"hidden": 1,
"label": "Sales Incoming Rate",
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-06-14 11:57:07.171700",
"modified": "2024-07-19 12:12:42.449298",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@@ -79,6 +79,7 @@ class PurchaseInvoiceItem(Document):
rejected_serial_no: DF.Text | None
rejected_warehouse: DF.Link | None
rm_supp_cost: DF.Currency
sales_incoming_rate: DF.Currency
sales_invoice_item: DF.Data | None
serial_and_batch_bundle: DF.Link | None
serial_no: DF.Text | None

View File

@@ -68,31 +68,6 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends (
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
if (this.frm.doc.repost_required && this.frm.doc.docstatus === 1) {
this.frm.set_intro(
__(
"Accounting entries for this invoice needs to be reposted. Please click on 'Repost' button to update."
)
);
this.frm
.add_custom_button(__("Repost Accounting Entries"), () => {
this.frm.call({
doc: this.frm.doc,
method: "repost_accounting_entries",
freeze: true,
freeze_message: __("Reposting..."),
callback: (r) => {
if (!r.exc) {
frappe.msgprint(__("Accounting Entries are reposted"));
me.frm.refresh();
}
},
});
})
.removeClass("btn-default")
.addClass("btn-warning");
}
if (this.frm.doc.is_return) {
this.frm.return_print_format = "Sales Invoice Return";
}
@@ -157,7 +132,7 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends (
const payment_is_overdue = doc.payment_schedule
.map((row) => Date.parse(row.due_date) < Date.now())
.reduce((prev, current) => prev || current);
.reduce((prev, current) => prev || current, false);
if (payment_is_overdue) {
this.frm.add_custom_button(
@@ -502,11 +477,12 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends (
frappe.msgprint(__("Please specify Company to proceed"));
} else {
var me = this;
const for_validate = me.frm.doc.is_return ? true : false;
return this.frm.call({
doc: me.frm.doc,
method: "set_missing_values",
args: {
for_validate: true,
for_validate: for_validate,
},
callback: function (r) {
if (!r.exc) {

View File

@@ -213,7 +213,6 @@
"is_internal_customer",
"is_discounted",
"remarks",
"repost_required",
"connections_tab"
],
"fields": [
@@ -2125,15 +2124,6 @@
"label": "Write Off",
"width": "50%"
},
{
"default": "0",
"fieldname": "repost_required",
"fieldtype": "Check",
"hidden": 1,
"label": "Repost Required",
"no_copy": 1,
"read_only": 1
},
{
"fieldname": "incoterm",
"fieldtype": "Link",
@@ -2188,7 +2178,7 @@
"link_fieldname": "consolidated_invoice"
}
],
"modified": "2024-06-07 16:49:32.458402",
"modified": "2024-07-18 15:30:39.428519",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -161,7 +161,6 @@ class SalesInvoice(SellingController):
project: DF.Link | None
redeem_loyalty_points: DF.Check
remarks: DF.SmallText | None
repost_required: DF.Check
represents_company: DF.Link | None
return_against: DF.Link | None
rounded_total: DF.Currency
@@ -279,7 +278,6 @@ class SalesInvoice(SellingController):
self.check_sales_order_on_hold_or_close("sales_order")
self.validate_debit_to_acc()
self.clear_unallocated_advances("Sales Invoice Advance", "advances")
self.add_remarks()
self.validate_fixed_asset()
self.set_income_account_for_fixed_assets()
self.validate_item_cost_centers()
@@ -423,6 +421,9 @@ class SalesInvoice(SellingController):
self.set_account_for_mode_of_payment()
self.set_paid_amount()
def before_submit(self):
self.add_remarks()
def on_submit(self):
self.validate_pos_paid_amount()
@@ -515,7 +516,7 @@ class SalesInvoice(SellingController):
)
if pos_closing_entry and pos_closing_entry[0]:
msg = _("To cancel a {} you need to cancel the POS Closing Entry {}.").format(
frappe.bold("Consolidated Sales Invoice"),
frappe.bold(_("Consolidated Sales Invoice")),
get_link_to_form("POS Closing Entry", pos_closing_entry[0]),
)
frappe.throw(msg, title=_("Not Allowed"))
@@ -556,7 +557,6 @@ class SalesInvoice(SellingController):
self.repost_future_sle_and_gle()
self.db_set("status", "Cancelled")
self.db_set("repost_required", 0)
if frappe.db.get_single_value("Selling Settings", "sales_update_frequency") == "Each Transaction":
update_company_current_month_sales(self.company)
@@ -706,25 +706,23 @@ class SalesInvoice(SellingController):
data.sales_invoice = sales_invoice
def on_update_after_submit(self):
if hasattr(self, "repost_required"):
fields_to_check = [
"additional_discount_account",
"cash_bank_account",
"account_for_change_amount",
"write_off_account",
"loyalty_redemption_account",
"unrealized_profit_loss_account",
"is_opening",
]
child_tables = {
"items": ("income_account", "expense_account", "discount_account"),
"taxes": ("account_head",),
}
self.needs_repost = self.check_if_fields_updated(fields_to_check, child_tables)
if self.needs_repost:
self.validate_for_repost()
self.db_set("repost_required", self.needs_repost)
self.repost_accounting_entries()
fields_to_check = [
"additional_discount_account",
"cash_bank_account",
"account_for_change_amount",
"write_off_account",
"loyalty_redemption_account",
"unrealized_profit_loss_account",
"is_opening",
]
child_tables = {
"items": ("income_account", "expense_account", "discount_account"),
"taxes": ("account_head",),
}
self.needs_repost = self.check_if_fields_updated(fields_to_check, child_tables)
if self.needs_repost:
self.validate_for_repost()
self.repost_accounting_entries()
def set_paid_amount(self):
paid_amount = 0.0
@@ -862,7 +860,7 @@ class SalesInvoice(SellingController):
if account.report_type != "Balance Sheet":
msg = (
_("Please ensure {} account is a Balance Sheet account.").format(frappe.bold("Debit To"))
_("Please ensure {} account is a Balance Sheet account.").format(frappe.bold(_("Debit To")))
+ " "
)
msg += _(
@@ -873,7 +871,7 @@ class SalesInvoice(SellingController):
if self.customer and account.account_type != "Receivable":
msg = (
_("Please ensure {} account {} is a Receivable account.").format(
frappe.bold("Debit To"), frappe.bold(self.debit_to)
frappe.bold(_("Debit To")), frappe.bold(self.debit_to)
)
+ " "
)
@@ -950,10 +948,11 @@ class SalesInvoice(SellingController):
def add_remarks(self):
if not self.remarks:
if self.po_no and self.po_date:
self.remarks = _("Against Customer Order {0} dated {1}").format(
self.po_no, formatdate(self.po_date)
)
if self.po_no:
self.remarks = _("Against Customer Order {0}").format(self.po_no)
if self.po_date:
self.remarks += " " + _("dated {0}").format(formatdate(self.po_date))
else:
self.remarks = _("No Remarks")
@@ -1213,6 +1212,8 @@ class SalesInvoice(SellingController):
self.make_precision_loss_gl_entry(gl_entries)
self.make_discount_gl_entries(gl_entries)
gl_entries = make_regional_gl_entries(gl_entries, self)
# merge gl entries before adding pos entries
gl_entries = merge_similar_entries(gl_entries)
@@ -1318,6 +1319,10 @@ class SalesInvoice(SellingController):
for item in self.get("items"):
if flt(item.base_net_amount, item.precision("base_net_amount")):
# Do not book income for transfer within same company
if self.is_internal_transfer():
continue
if item.is_fixed_asset:
asset = self.get_asset(item)
@@ -1376,37 +1381,33 @@ class SalesInvoice(SellingController):
self.set_asset_status(asset)
else:
# Do not book income for transfer within same company
if not self.is_internal_transfer():
income_account = (
item.income_account
if (not item.enable_deferred_revenue or self.is_return)
else item.deferred_revenue_account
)
income_account = (
item.income_account
if (not item.enable_deferred_revenue or self.is_return)
else item.deferred_revenue_account
)
amount, base_amount = self.get_amount_and_base_amount(
item, enable_discount_accounting
)
amount, base_amount = self.get_amount_and_base_amount(item, enable_discount_accounting)
account_currency = get_account_currency(income_account)
gl_entries.append(
self.get_gl_dict(
{
"account": income_account,
"against": self.customer,
"credit": flt(base_amount, item.precision("base_net_amount")),
"credit_in_account_currency": (
flt(base_amount, item.precision("base_net_amount"))
if account_currency == self.company_currency
else flt(amount, item.precision("net_amount"))
),
"cost_center": item.cost_center,
"project": item.project or self.project,
},
account_currency,
item=item,
)
account_currency = get_account_currency(income_account)
gl_entries.append(
self.get_gl_dict(
{
"account": income_account,
"against": self.customer,
"credit": flt(base_amount, item.precision("base_net_amount")),
"credit_in_account_currency": (
flt(base_amount, item.precision("base_net_amount"))
if account_currency == self.company_currency
else flt(amount, item.precision("net_amount"))
),
"cost_center": item.cost_center,
"project": item.project or self.project,
},
account_currency,
item=item,
)
)
# expense account gl entries
if cint(self.update_stock) and erpnext.is_perpetual_inventory_enabled(self.company):
@@ -1481,6 +1482,10 @@ class SalesInvoice(SellingController):
if skip_change_gl_entries and payment_mode.account == self.account_for_change_amount:
payment_mode.base_amount -= flt(self.change_amount)
against_voucher = self.name
if self.is_return and self.return_against and not self.update_outstanding_for_self:
against_voucher = self.return_against
if payment_mode.base_amount:
# POS, make payment entries
gl_entries.append(
@@ -1494,7 +1499,7 @@ class SalesInvoice(SellingController):
"credit_in_account_currency": payment_mode.base_amount
if self.party_account_currency == self.company_currency
else payment_mode.amount,
"against_voucher": self.name,
"against_voucher": against_voucher,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center,
},
@@ -2226,6 +2231,11 @@ def make_inter_company_purchase_invoice(source_name, target_doc=None):
return make_inter_company_transaction("Sales Invoice", source_name, target_doc)
@erpnext.allow_regional
def make_regional_gl_entries(gl_entries, doc):
return gl_entries
def make_inter_company_transaction(doctype, source_name, target_doc=None):
if doctype in ["Sales Invoice", "Sales Order"]:
source_doc = frappe.get_doc(doctype, source_name)

View File

@@ -5,9 +5,10 @@ import copy
import json
import frappe
from frappe import qb
from frappe.model.dynamic_links import get_dynamic_link_map
from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import add_days, flt, getdate, nowdate, today
from frappe.utils import add_days, flt, format_date, getdate, nowdate, today
import erpnext
from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account
@@ -2952,9 +2953,6 @@ class TestSalesInvoice(FrappeTestCase):
check_gl_entries(self, si.name, expected_gle, add_days(nowdate(), -1))
si.load_from_db()
self.assertFalse(si.repost_required)
def test_asset_depreciation_on_sale_with_pro_rata(self):
"""
Tests if an Asset set to depreciate yearly on June 30, that gets sold on Sept 30, creates an additional depreciation entry on its date of sale.
@@ -3086,6 +3084,128 @@ class TestSalesInvoice(FrappeTestCase):
party_link.delete()
frappe.db.set_single_value("Accounts Settings", "enable_common_party_accounting", 0)
def test_sales_invoice_against_supplier_usd_with_dimensions(self):
from erpnext.accounts.doctype.opening_invoice_creation_tool.test_opening_invoice_creation_tool import (
make_customer,
)
from erpnext.accounts.doctype.party_link.party_link import create_party_link
from erpnext.buying.doctype.supplier.test_supplier import create_supplier
# create a customer
customer = make_customer(customer="_Test Common Supplier USD")
cust_doc = frappe.get_doc("Customer", customer)
cust_doc.default_currency = "USD"
cust_doc.save()
# create a supplier
supplier = create_supplier(supplier_name="_Test Common Supplier USD").name
supp_doc = frappe.get_doc("Supplier", supplier)
supp_doc.default_currency = "USD"
supp_doc.save()
# create a party link between customer & supplier
party_link = create_party_link("Supplier", supplier, customer)
# enable common party accounting
frappe.db.set_single_value("Accounts Settings", "enable_common_party_accounting", 1)
# create a dimension and make it mandatory
if not frappe.get_all("Accounting Dimension", filters={"document_type": "Department"}):
dim = frappe.get_doc(
{
"doctype": "Accounting Dimension",
"document_type": "Department",
"dimension_defaults": [{"company": "_Test Company", "mandatory_for_bs": True}],
}
)
dim.save()
else:
dim = frappe.get_doc(
"Accounting Dimension",
frappe.get_all("Accounting Dimension", filters={"document_type": "Department"})[0],
)
dim.disabled = False
dim.dimension_defaults = []
dim.append("dimension_defaults", {"company": "_Test Company", "mandatory_for_bs": True})
dim.save()
# create a sales invoice
si = create_sales_invoice(
customer=customer, parent_cost_center="_Test Cost Center - _TC", do_not_submit=True
)
si.department = "All Departments"
si.save().submit()
# check outstanding of sales invoice
si.reload()
self.assertEqual(si.status, "Paid")
self.assertEqual(flt(si.outstanding_amount), 0.0)
# check creation of journal entry
jv = frappe.get_all(
"Journal Entry Account",
{
"account": si.debit_to,
"party_type": "Customer",
"party": si.customer,
"reference_type": si.doctype,
"reference_name": si.name,
"department": "All Departments",
},
pluck="credit_in_account_currency",
)
self.assertTrue(jv)
self.assertEqual(jv[0], si.grand_total)
dim.disabled = True
dim.save()
party_link.delete()
frappe.db.set_single_value("Accounts Settings", "enable_common_party_accounting", 0)
def test_sales_invoice_cancel_with_common_party_advance_jv(self):
from erpnext.accounts.doctype.opening_invoice_creation_tool.test_opening_invoice_creation_tool import (
make_customer,
)
from erpnext.accounts.doctype.party_link.party_link import create_party_link
from erpnext.buying.doctype.supplier.test_supplier import create_supplier
# create a customer
customer = make_customer(customer="_Test Common Supplier")
# create a supplier
supplier = create_supplier(supplier_name="_Test Common Supplier").name
# create a party link between customer & supplier
party_link = create_party_link("Supplier", supplier, customer)
# enable common party accounting
frappe.db.set_single_value("Accounts Settings", "enable_common_party_accounting", 1)
# create a sales invoice
si = create_sales_invoice(customer=customer)
# check creation of journal entry
jv = frappe.db.get_value(
"Journal Entry Account",
filters={
"reference_type": si.doctype,
"reference_name": si.name,
"docstatus": 1,
},
fieldname="parent",
)
self.assertTrue(jv)
# cancel sales invoice
si.cancel()
# check cancellation of journal entry
jv_status = frappe.db.get_value("Journal Entry", jv, "docstatus")
self.assertEqual(jv_status, 2)
party_link.delete()
frappe.db.set_single_value("Accounts Settings", "enable_common_party_accounting", 0)
def test_payment_statuses(self):
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
@@ -3761,6 +3881,130 @@ class TestSalesInvoice(FrappeTestCase):
]
self.assertEqual(expected, actual)
def test_pos_returns_without_update_outstanding_for_self(self):
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_sales_return
pos_profile = make_pos_profile()
pos_profile.payments = []
pos_profile.append("payments", {"default": 1, "mode_of_payment": "Cash"})
pos_profile.save()
pos = create_sales_invoice(qty=10, do_not_save=True)
pos.is_pos = 1
pos.pos_profile = pos_profile.name
pos.append(
"payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - _TC", "amount": 500}
)
pos.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 500})
pos.save().submit()
pos_return = make_sales_return(pos.name)
pos_return.update_outstanding_for_self = False
pos_return.save().submit()
gle = qb.DocType("GL Entry")
res = (
qb.from_(gle)
.select(gle.against_voucher)
.distinct()
.where(
gle.is_cancelled.eq(0) & gle.voucher_no.eq(pos_return.name) & gle.against_voucher.notnull()
)
.run(as_list=1)
)
self.assertEqual(len(res), 1)
self.assertEqual(res[0][0], pos_return.return_against)
@change_settings("Accounts Settings", {"enable_common_party_accounting": True})
def test_common_party_with_foreign_currency_jv(self):
from erpnext.accounts.doctype.account.test_account import create_account
from erpnext.accounts.doctype.opening_invoice_creation_tool.test_opening_invoice_creation_tool import (
make_customer,
)
from erpnext.accounts.doctype.party_link.party_link import create_party_link
from erpnext.buying.doctype.supplier.test_supplier import create_supplier
from erpnext.setup.utils import get_exchange_rate
creditors = create_account(
account_name="Creditors USD",
parent_account="Accounts Payable - _TC",
company="_Test Company",
account_currency="USD",
account_type="Payable",
)
debtors = create_account(
account_name="Debtors USD",
parent_account="Accounts Receivable - _TC",
company="_Test Company",
account_currency="USD",
account_type="Receivable",
)
# create a customer
customer = make_customer(customer="_Test Common Party USD")
cust_doc = frappe.get_doc("Customer", customer)
cust_doc.default_currency = "USD"
test_account_details = {
"company": "_Test Company",
"account": debtors,
}
cust_doc.append("accounts", test_account_details)
cust_doc.save()
# create a supplier
supplier = create_supplier(supplier_name="_Test Common Party USD").name
supp_doc = frappe.get_doc("Supplier", supplier)
supp_doc.default_currency = "USD"
test_account_details = {
"company": "_Test Company",
"account": creditors,
}
supp_doc.append("accounts", test_account_details)
supp_doc.save()
# create a party link between customer & supplier
create_party_link("Supplier", supplier, customer)
# create a sales invoice
si = create_sales_invoice(
customer=customer,
currency="USD",
conversion_rate=get_exchange_rate("USD", "INR"),
debit_to=debtors,
do_not_save=1,
)
si.party_account_currency = "USD"
si.save()
si.submit()
# check outstanding of sales invoice
si.reload()
self.assertEqual(si.status, "Paid")
self.assertEqual(flt(si.outstanding_amount), 0.0)
# check creation of journal entry
jv = frappe.get_all(
"Journal Entry Account",
{
"account": si.debit_to,
"party_type": "Customer",
"party": si.customer,
"reference_type": si.doctype,
"reference_name": si.name,
},
pluck="credit_in_account_currency",
)
self.assertTrue(jv)
self.assertEqual(jv[0], si.grand_total)
def test_invoice_remarks(self):
si = frappe.copy_doc(test_records[0])
si.po_no = "Test PO"
si.po_date = nowdate()
si.save()
si.submit()
self.assertEqual(si.remarks, f"Against Customer Order Test PO dated {format_date(nowdate())}")
def set_advance_flag(company, flag, default_account):
frappe.db.set_value(

View File

@@ -38,6 +38,12 @@ frappe.ui.form.on("Subscription", {
__("Actions")
);
frm.add_custom_button(
__("Force-Fetch Subscription Updates"),
() => frm.trigger("force_fetch_subscription_updates"),
__("Actions")
);
frm.add_custom_button(
__("Cancel Subscription"),
() => frm.trigger("cancel_this_subscription"),
@@ -82,4 +88,11 @@ frappe.ui.form.on("Subscription", {
}
});
},
force_fetch_subscription_updates: function (frm) {
frm.call("force_fetch_subscription_updates").then((r) => {
if (!r.exec) {
frm.reload_doc();
}
});
},
});

View File

@@ -717,6 +717,28 @@ class Subscription(Document):
self.update_subscription_period(posting_date or nowdate())
self.save()
@frappe.whitelist()
def force_fetch_subscription_updates(self):
"""
Process Subscription and create Invoices even if current date doesn't lie between current_invoice_start and currenct_invoice_end
It makes use of 'Proces Subscription' to force processing in a specific 'posting_date'
"""
# Don't process future subscriptions
if nowdate() < self.current_invoice_start:
frappe.msgprint(_("Subscription for Future dates cannot be processed."))
return
processing_date = None
if self.generate_invoice_at == "Beginning of the current subscription period":
processing_date = self.current_invoice_start
elif self.generate_invoice_at == "End of the current subscription period":
processing_date = self.current_invoice_end
elif self.generate_invoice_at == "Days before the current subscription period":
processing_date = add_days(self.current_invoice_start, -self.number_of_days)
self.process(posting_date=processing_date)
def is_prorate() -> int:
return cint(frappe.db.get_single_value("Subscription Settings", "prorate"))

View File

@@ -521,6 +521,18 @@ class TestSubscription(FrappeTestCase):
subscription.process(posting_date="2023-01-22")
self.assertEqual(len(subscription.invoices), 2)
def test_future_subscription(self):
"""Force-Fetch should not process future subscriptions"""
subscription = create_subscription(
start_date=add_months(nowdate(), 1),
submit_invoice=0,
generate_new_invoices_past_due_date=1,
party="_Test Subscription Customer John Doe",
)
subscription.force_fetch_subscription_updates()
subscription.reload()
self.assertEqual(len(subscription.invoices), 0)
def make_plans():
create_plan(plan_name="_Test Plan Name", cost=900, currency="INR")

View File

@@ -268,6 +268,11 @@ def get_tax_amount(party_type, parties, inv, tax_details, posting_date, pan_no=N
vouchers, voucher_wise_amount = get_invoice_vouchers(
parties, tax_details, inv.company, party_type=party_type
)
payment_entry_vouchers = get_payment_entry_vouchers(
parties, tax_details, inv.company, party_type=party_type
)
advance_vouchers = get_advance_vouchers(
parties,
company=inv.company,
@@ -275,7 +280,8 @@ def get_tax_amount(party_type, parties, inv, tax_details, posting_date, pan_no=N
to_date=tax_details.to_date,
party_type=party_type,
)
taxable_vouchers = vouchers + advance_vouchers
taxable_vouchers = vouchers + advance_vouchers + payment_entry_vouchers
tax_deducted_on_advances = 0
if inv.doctype == "Purchase Invoice":
@@ -369,12 +375,14 @@ def get_invoice_vouchers(parties, tax_details, company, party_type="Supplier"):
AND ja.party in %s
AND j.apply_tds = 1
AND j.tax_withholding_category = %s
AND j.company = %s
""",
(
tax_details.from_date,
tax_details.to_date,
tuple(parties),
tax_details.get("tax_withholding_category"),
company,
),
as_dict=1,
)
@@ -387,6 +395,20 @@ def get_invoice_vouchers(parties, tax_details, company, party_type="Supplier"):
return vouchers, voucher_wise_amount
def get_payment_entry_vouchers(parties, tax_details, company, party_type="Supplier"):
payment_entry_filters = {
"party_type": party_type,
"party": ("in", parties),
"docstatus": 1,
"apply_tax_withholding_amount": 1,
"posting_date": ["between", (tax_details.from_date, tax_details.to_date)],
"tax_withholding_category": tax_details.get("tax_withholding_category"),
"company": company,
}
return frappe.db.get_all("Payment Entry", filters=payment_entry_filters, pluck="name")
def get_advance_vouchers(parties, company=None, from_date=None, to_date=None, party_type="Supplier"):
"""
Use Payment Ledger to fetch unallocated Advance Payments
@@ -477,6 +499,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
"unallocated_amount": (">", 0),
"posting_date": ["between", (tax_details.from_date, tax_details.to_date)],
"tax_withholding_category": tax_details.get("tax_withholding_category"),
"company": inv.company,
}
field = "sum(tax_withholding_net_total)"

View File

@@ -68,7 +68,7 @@ def get_party_details(
pos_profile=None,
):
if not party:
return {}
return frappe._dict()
if not frappe.db.exists(party_type, party):
frappe.throw(_("{0}: {1} does not exists").format(party_type, party))
return _get_party_details(

View File

@@ -61,32 +61,10 @@ frappe.query_reports["Accounts Payable"] = {
default: "Due Date",
},
{
fieldname: "range1",
label: __("Ageing Range 1"),
fieldtype: "Int",
default: "30",
reqd: 1,
},
{
fieldname: "range2",
label: __("Ageing Range 2"),
fieldtype: "Int",
default: "60",
reqd: 1,
},
{
fieldname: "range3",
label: __("Ageing Range 3"),
fieldtype: "Int",
default: "90",
reqd: 1,
},
{
fieldname: "range4",
label: __("Ageing Range 4"),
fieldtype: "Int",
default: "120",
reqd: 1,
fieldname: "range",
label: __("Ageing Range"),
fieldtype: "Data",
default: "30, 60, 90, 120",
},
{
fieldname: "payment_terms_template",
@@ -162,6 +140,11 @@ frappe.query_reports["Accounts Payable"] = {
label: __("In Party Currency"),
fieldtype: "Check",
},
{
fieldname: "handle_employee_advances",
label: __("Handle Employee Advances"),
fieldtype: "Check",
},
],
formatter: function (value, row, column, data, default_formatter) {

View File

@@ -30,10 +30,7 @@ class TestAccountsPayable(AccountsTestMixin, FrappeTestCase):
"party_type": "Supplier",
"party": [self.supplier],
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
"in_party_currency": 1,
}

View File

@@ -24,32 +24,10 @@ frappe.query_reports["Accounts Payable Summary"] = {
default: "Due Date",
},
{
fieldname: "range1",
label: __("Ageing Range 1"),
fieldtype: "Int",
default: "30",
reqd: 1,
},
{
fieldname: "range2",
label: __("Ageing Range 2"),
fieldtype: "Int",
default: "60",
reqd: 1,
},
{
fieldname: "range3",
label: __("Ageing Range 3"),
fieldtype: "Int",
default: "90",
reqd: 1,
},
{
fieldname: "range4",
label: __("Ageing Range 4"),
fieldtype: "Int",
default: "120",
reqd: 1,
fieldname: "range",
label: __("Ageing Range"),
fieldtype: "Data",
default: "30, 60, 90, 120",
},
{
fieldname: "finance_book",

View File

@@ -89,32 +89,10 @@ frappe.query_reports["Accounts Receivable"] = {
default: "Due Date",
},
{
fieldname: "range1",
label: __("Ageing Range 1"),
fieldtype: "Int",
default: "30",
reqd: 1,
},
{
fieldname: "range2",
label: __("Ageing Range 2"),
fieldtype: "Int",
default: "60",
reqd: 1,
},
{
fieldname: "range3",
label: __("Ageing Range 3"),
fieldtype: "Int",
default: "90",
reqd: 1,
},
{
fieldname: "range4",
label: __("Ageing Range 4"),
fieldtype: "Int",
default: "120",
reqd: 1,
fieldname: "range",
label: __("Ageing Range"),
fieldtype: "Data",
default: "30, 60, 90, 120",
},
{
fieldname: "customer_group",

View File

@@ -50,6 +50,11 @@ class ReceivablePayableReport:
getdate(nowdate()) if self.filters.report_date > getdate(nowdate()) else self.filters.report_date
)
if not self.filters.range:
self.filters.range = "30, 60, 90, 120"
self.ranges = [num.strip() for num in self.filters.range.split(",") if num.strip().isdigit()]
self.range_numbers = [num for num in range(1, len(self.ranges) + 2)]
def run(self, args):
self.filters.update(args)
self.set_defaults()
@@ -112,6 +117,26 @@ class ReceivablePayableReport:
self.build_data()
def build_voucher_dict(self, ple):
return frappe._dict(
voucher_type=ple.voucher_type,
voucher_no=ple.voucher_no,
party=ple.party,
party_account=ple.account,
posting_date=ple.posting_date,
account_currency=ple.account_currency,
remarks=ple.remarks,
invoiced=0.0,
paid=0.0,
credit_note=0.0,
outstanding=0.0,
invoiced_in_account_currency=0.0,
paid_in_account_currency=0.0,
credit_note_in_account_currency=0.0,
outstanding_in_account_currency=0.0,
cost_center=ple.cost_center,
)
def init_voucher_balance(self):
# build all keys, since we want to exclude vouchers beyond the report date
for ple in self.ple_entries:
@@ -123,23 +148,8 @@ class ReceivablePayableReport:
key = (ple.account, ple.voucher_type, ple.voucher_no, ple.party)
if key not in self.voucher_balance:
self.voucher_balance[key] = frappe._dict(
voucher_type=ple.voucher_type,
voucher_no=ple.voucher_no,
party=ple.party,
party_account=ple.account,
posting_date=ple.posting_date,
account_currency=ple.account_currency,
remarks=ple.remarks,
invoiced=0.0,
paid=0.0,
credit_note=0.0,
outstanding=0.0,
invoiced_in_account_currency=0.0,
paid_in_account_currency=0.0,
credit_note_in_account_currency=0.0,
outstanding_in_account_currency=0.0,
)
self.voucher_balance[key] = self.build_voucher_dict(ple)
self.get_invoices(ple)
if self.filters.get("group_by_party"):
@@ -207,6 +217,18 @@ class ReceivablePayableReport:
row = self.voucher_balance.get(key)
# Build and use a separate row for Employee Advances.
# This allows Payments or Journals made against Emp Advance to be processed.
if (
not row
and ple.against_voucher_type == "Employee Advance"
and self.filters.handle_employee_advances
):
_d = self.build_voucher_dict(ple)
_d.voucher_type = ple.against_voucher_type
_d.voucher_no = ple.against_voucher_no
row = self.voucher_balance[key] = _d
if not row:
# no invoice, this is an invoice / stand-alone payment / credit note
if self.filters.get("ignore_accounts"):
@@ -253,7 +275,7 @@ class ReceivablePayableReport:
row.paid -= amount
row.paid_in_account_currency -= amount_in_account_currency
if ple.cost_center:
if not row.cost_center and ple.cost_center:
row.cost_center = str(ple.cost_center)
def update_sub_total_row(self, row, party):
@@ -288,13 +310,13 @@ class ReceivablePayableReport:
must_consider = False
if self.filters.get("for_revaluation_journals"):
if (abs(row.outstanding) > 0.0 / 10**self.currency_precision) or (
abs(row.outstanding_in_account_currency) > 0.0 / 10**self.currency_precision
if (abs(row.outstanding) >= 0.0 / 10**self.currency_precision) or (
abs(row.outstanding_in_account_currency) >= 0.0 / 10**self.currency_precision
):
must_consider = True
else:
if (abs(row.outstanding) > 1.0 / 10**self.currency_precision) and (
(abs(row.outstanding_in_account_currency) > 1.0 / 10**self.currency_precision)
if (abs(row.outstanding) >= 1.0 / 10**self.currency_precision) and (
(abs(row.outstanding_in_account_currency) >= 1.0 / 10**self.currency_precision)
or (row.voucher_no in self.err_journals)
):
must_consider = True
@@ -716,37 +738,22 @@ class ReceivablePayableReport:
# ageing buckets should not have amounts if due date is not reached
if getdate(entry_date) > getdate(self.filters.report_date):
row.range1 = row.range2 = row.range3 = row.range4 = row.range5 = 0.0
[setattr(row, f"range{i}", 0.0) for i in self.range_numbers]
row.total_due = row.range1 + row.range2 + row.range3 + row.range4 + row.range5
row.total_due = sum(row[f"range{i}"] for i in self.range_numbers)
def get_ageing_data(self, entry_date, row):
# [0-30, 30-60, 60-90, 90-120, 120-above]
row.range1 = row.range2 = row.range3 = row.range4 = row.range5 = 0.0
[setattr(row, f"range{i}", 0.0) for i in self.range_numbers]
if not (self.age_as_on and entry_date):
return
row.age = (getdate(self.age_as_on) - getdate(entry_date)).days or 0
index = None
if not (self.filters.range1 and self.filters.range2 and self.filters.range3 and self.filters.range4):
self.filters.range1, self.filters.range2, self.filters.range3, self.filters.range4 = (
30,
60,
90,
120,
)
for i, days in enumerate(
[self.filters.range1, self.filters.range2, self.filters.range3, self.filters.range4]
):
if cint(row.age) <= cint(days):
index = i
break
if index is None:
index = 4
index = next(
(i for i, days in enumerate(self.ranges) if cint(row.age) <= cint(days)), len(self.ranges)
)
row["range" + str(index + 1)] = row.outstanding
def get_ple_entries(self):
@@ -1058,6 +1065,7 @@ class ReceivablePayableReport:
self.add_column(_("Debit Note"), fieldname="credit_note")
self.add_column(_("Outstanding Amount"), fieldname="outstanding")
self.add_column(label=_("Age (Days)"), fieldname="age", fieldtype="Int", width=80)
self.setup_ageing_columns()
self.add_column(
@@ -1116,34 +1124,26 @@ class ReceivablePayableReport:
def setup_ageing_columns(self):
# for charts
self.ageing_column_labels = []
self.add_column(label=_("Age (Days)"), fieldname="age", fieldtype="Int", width=80)
ranges = [*self.ranges, "Above"]
prev_range_value = 0
for idx, curr_range_value in enumerate(ranges):
label = f"{prev_range_value}-{curr_range_value}"
self.add_column(label=label, fieldname="range" + str(idx + 1))
for i, label in enumerate(
[
"0-{range1}".format(range1=self.filters["range1"]),
"{range1}-{range2}".format(
range1=cint(self.filters["range1"]) + 1, range2=self.filters["range2"]
),
"{range2}-{range3}".format(
range2=cint(self.filters["range2"]) + 1, range3=self.filters["range3"]
),
"{range3}-{range4}".format(
range3=cint(self.filters["range3"]) + 1, range4=self.filters["range4"]
),
_("{range4}-Above").format(range4=cint(self.filters["range4"]) + 1),
]
):
self.add_column(label=label, fieldname="range" + str(i + 1))
self.ageing_column_labels.append(label)
if curr_range_value.isdigit():
prev_range_value = cint(curr_range_value) + 1
def get_chart_data(self):
precision = cint(frappe.db.get_default("float_precision")) or 2
rows = []
for row in self.data:
row = frappe._dict(row)
if not cint(row.bold):
values = [row.range1, row.range2, row.range3, row.range4, row.range5]
precision = cint(frappe.db.get_default("float_precision")) or 2
rows.append({"values": [flt(val, precision) for val in values]})
values = [flt(row.get(f"range{i}", None), precision) for i in self.range_numbers]
rows.append({"values": values})
self.chart = {
"data": {"labels": self.ageing_column_labels, "datasets": rows},

View File

@@ -53,11 +53,13 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
si = si.submit()
return si
def create_payment_entry(self, docname):
def create_payment_entry(self, docname, do_not_submit=False):
pe = get_payment_entry("Sales Invoice", docname, bank_account=self.cash, party_amount=40)
pe.paid_from = self.debit_to
pe.insert()
pe.submit()
if not do_not_submit:
pe.submit()
return pe
def create_credit_note(self, docname, do_not_submit=False):
credit_note = create_sales_invoice(
@@ -81,10 +83,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
"party": [self.customer],
"report_date": add_days(today(), 2),
"based_on_payment_terms": 0,
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
"show_remarks": False,
}
@@ -114,10 +113,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
"company": self.company,
"based_on_payment_terms": 1,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
"show_remarks": True,
}
@@ -170,10 +166,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
"show_remarks": True,
}
@@ -264,10 +257,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
"company": self.company,
"based_on_payment_terms": 0,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
}
report = execute(filters)
@@ -326,10 +316,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
}
report = execute(filters)
@@ -395,10 +382,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
}
report = execute(filters)
self.assertEqual(report[1], [])
@@ -414,10 +398,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
"group_by_party": True,
}
report = execute(filters)[1]
@@ -491,10 +472,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
"show_future_payments": True,
}
report = execute(filters)[1]
@@ -553,10 +531,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
"sales_person": sales_person.name,
"show_sales_person": True,
}
@@ -573,10 +548,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
"cost_center": self.cost_center,
}
report = execute(filters)[1]
@@ -591,10 +563,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
"customer_group": cus_group,
}
report = execute(filters)[1]
@@ -616,10 +585,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
"customer_group": cus_groups_list, # Use the list of customer groups
}
report = execute(filters)[1]
@@ -658,10 +624,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
"party_account": self.debit_to,
}
report = execute(filters)[1]
@@ -709,10 +672,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
"party_type": "Customer",
"party": [self.customer],
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
"in_party_currency": 1,
}
@@ -752,10 +712,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
"party_type": "Customer",
"party": [self.customer1, self.customer3],
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
}
si1 = self.create_sales_invoice(no_payment_schedule=True, do_not_submit=True)
@@ -835,10 +792,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
}
report_ouput = execute(filters)[1]
@@ -901,10 +855,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
{
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
"show_future_payments": True,
"in_party_currency": False,
}
@@ -955,3 +906,63 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
self.assertEqual(
expected_data, [row.invoiced, row.outstanding, row.remaining_balance, row.future_amount]
)
def test_accounts_receivable_output_for_minor_outstanding(self):
"""
AR/AP should report miniscule outstanding of 0.01. Or else there will be slight difference with General Ledger/Trial Balance
"""
filters = {
"company": self.company,
"report_date": today(),
"range": "30, 60, 90, 120",
}
# check invoice grand total and invoiced column's value for 3 payment terms
si = self.create_sales_invoice(no_payment_schedule=True)
pe = get_payment_entry("Sales Invoice", si.name, bank_account=self.cash, party_amount=99.99)
pe.paid_from = self.debit_to
pe.save().submit()
report = execute(filters)
expected_data_after_payment = [100, 100, 99.99, 0.01]
self.assertEqual(len(report[1]), 1)
row = report[1][0]
self.assertEqual(
expected_data_after_payment,
[row.invoice_grand_total, row.invoiced, row.paid, row.outstanding],
)
def test_cost_center_on_report_output(self):
filters = {
"company": self.company,
"report_date": today(),
"range": "30, 60, 90, 120",
}
# check invoice grand total and invoiced column's value for 3 payment terms
si = self.create_sales_invoice(no_payment_schedule=True, do_not_submit=True)
si.cost_center = self.cost_center
si.save().submit()
new_cc = frappe.get_doc(
{
"doctype": "Cost Center",
"cost_center_name": "East Wing",
"parent_cost_center": self.company + " - " + self.company_abbr,
"company": self.company,
}
)
new_cc.save()
# check invoice grand total, invoiced, paid and outstanding column's value after payment
pe = self.create_payment_entry(si.name, do_not_submit=True)
pe.cost_center = new_cc.name
pe.save().submit()
report = execute(filters)
expected_data_after_payment = [si.name, si.cost_center, 60]
self.assertEqual(len(report[1]), 1)
row = report[1][0]
self.assertEqual(expected_data_after_payment, [row.voucher_no, row.cost_center, row.outstanding])

View File

@@ -24,32 +24,10 @@ frappe.query_reports["Accounts Receivable Summary"] = {
default: "Due Date",
},
{
fieldname: "range1",
label: __("Ageing Range 1"),
fieldtype: "Int",
default: "30",
reqd: 1,
},
{
fieldname: "range2",
label: __("Ageing Range 2"),
fieldtype: "Int",
default: "60",
reqd: 1,
},
{
fieldname: "range3",
label: __("Ageing Range 3"),
fieldtype: "Int",
default: "90",
reqd: 1,
},
{
fieldname: "range4",
label: __("Ageing Range 4"),
fieldtype: "Int",
default: "120",
reqd: 1,
fieldname: "range",
label: __("Ageing Range"),
fieldtype: "Data",
default: "30, 60, 90, 120",
},
{
fieldname: "finance_book",

View File

@@ -104,25 +104,23 @@ class AccountsReceivableSummary(ReceivablePayableReport):
self.set_party_details(d)
def init_party_total(self, row):
default_dict = {
"invoiced": 0.0,
"paid": 0.0,
"credit_note": 0.0,
"outstanding": 0.0,
"total_due": 0.0,
"future_amount": 0.0,
"sales_person": [],
"party_type": row.party_type,
}
for i in self.range_numbers:
range_key = f"range{i}"
default_dict[range_key] = 0.0
self.party_total.setdefault(
row.party,
frappe._dict(
{
"invoiced": 0.0,
"paid": 0.0,
"credit_note": 0.0,
"outstanding": 0.0,
"range1": 0.0,
"range2": 0.0,
"range3": 0.0,
"range4": 0.0,
"range5": 0.0,
"total_due": 0.0,
"future_amount": 0.0,
"sales_person": [],
"party_type": row.party_type,
}
),
frappe._dict(default_dict),
)
def set_party_details(self, row):
@@ -173,6 +171,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
self.add_column(_("Difference"), fieldname="diff")
self.setup_ageing_columns()
self.add_column(label="Total Amount Due", fieldname="total_due")
if self.filters.show_future_payments:
self.add_column(label=_("Future Payment Amount"), fieldname="future_amount")
@@ -206,27 +205,6 @@ class AccountsReceivableSummary(ReceivablePayableReport):
label=_("Currency"), fieldname="currency", fieldtype="Link", options="Currency", width=80
)
def setup_ageing_columns(self):
for i, label in enumerate(
[
"0-{range1}".format(range1=self.filters["range1"]),
"{range1}-{range2}".format(
range1=cint(self.filters["range1"]) + 1, range2=self.filters["range2"]
),
"{range2}-{range3}".format(
range2=cint(self.filters["range2"]) + 1, range3=self.filters["range3"]
),
"{range3}-{range4}".format(
range3=cint(self.filters["range3"]) + 1, range4=self.filters["range4"]
),
"{range4}-{above}".format(range4=cint(self.filters["range4"]) + 1, above=_("Above")),
]
):
self.add_column(label=label, fieldname="range" + str(i + 1))
# Add column for total due amount
self.add_column(label="Total Amount Due", fieldname="total_due")
def get_gl_balance(report_date, company):
return frappe._dict(

View File

@@ -27,10 +27,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
"company": self.company,
"customer": self.customer,
"posting_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
}
si = create_sales_invoice(
@@ -121,10 +118,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
"company": self.company,
"customer": self.customer,
"posting_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"range": "30, 60, 90, 120",
}
si = create_sales_invoice(

View File

@@ -46,5 +46,11 @@ frappe.query_reports["Asset Depreciations and Balances"] = {
options: "Asset",
depends_on: "eval: doc.group_by == 'Asset'",
},
{
fieldname: "finance_book",
label: __("Finance Book"),
fieldtype: "Link",
options: "Finance Book",
},
],
};

View File

@@ -69,6 +69,9 @@ def get_asset_categories_for_grouped_by_category(filters):
condition = ""
if filters.get("asset_category"):
condition += " and asset_category = %(asset_category)s"
if filters.get("finance_book"):
condition += " and exists (select 1 from `tabAsset Depreciation Schedule` ads where ads.asset = a.name and ads.finance_book = %(finance_book)s)"
# nosemgrep
return frappe.db.sql(
f"""
@@ -119,6 +122,7 @@ def get_asset_categories_for_grouped_by_category(filters):
"from_date": filters.from_date,
"company": filters.company,
"asset_category": filters.get("asset_category"),
"finance_book": filters.get("finance_book"),
},
as_dict=1,
)
@@ -128,6 +132,10 @@ def get_asset_details_for_grouped_by_category(filters):
condition = ""
if filters.get("asset"):
condition += " and name = %(asset)s"
if filters.get("finance_book"):
condition += " and exists (select 1 from `tabAsset Depreciation Schedule` ads where ads.asset = `tabAsset`.name and ads.finance_book = %(finance_book)s)"
# nosemgrep
return frappe.db.sql(
f"""
SELECT name,
@@ -176,6 +184,7 @@ def get_asset_details_for_grouped_by_category(filters):
"from_date": filters.from_date,
"company": filters.company,
"asset": filters.get("asset"),
"finance_book": filters.get("finance_book"),
},
as_dict=1,
)

View File

@@ -46,4 +46,20 @@ frappe.query_reports["Bank Reconciliation Statement"] = {
fieldtype: "Check",
},
],
formatter: function (value, row, column, data, default_formatter, filter) {
if (column.fieldname == "payment_entry" && value == "Cheques and Deposits incorrectly cleared") {
column.link_onclick =
"frappe.query_reports['Bank Reconciliation Statement'].open_utility_report()";
}
return default_formatter(value, row, column, data);
},
open_utility_report: function () {
frappe.route_options = {
company: frappe.query_report.get_filter_value("company"),
account: frappe.query_report.get_filter_value("account"),
report_date: frappe.query_report.get_filter_value("report_date"),
};
frappe.open_in_new_tab = true;
frappe.set_route("query-report", "Cheques and Deposits Incorrectly cleared");
},
};

View File

@@ -154,8 +154,8 @@ def get_payment_entries(filters):
select
"Payment Entry" as payment_document, name as payment_entry,
reference_no, reference_date as ref_date,
if(paid_to=%(account)s, received_amount, 0) as debit,
if(paid_from=%(account)s, paid_amount, 0) as credit,
if(paid_to=%(account)s, received_amount_after_tax, 0) as debit,
if(paid_from=%(account)s, paid_amount_after_tax, 0) as credit,
posting_date, ifnull(party,if(paid_from=%(account)s,paid_to,paid_from)) as against_account, clearance_date,
if(paid_to=%(account)s, paid_to_account_currency, paid_from_account_currency) as account_currency
from `tabPayment Entry`

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Cheques and Deposits Incorrectly cleared"] = {
filters: [
{
fieldname: "company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
reqd: 1,
default: frappe.defaults.get_user_default("Company"),
},
{
fieldname: "account",
label: __("Bank Account"),
fieldtype: "Link",
options: "Account",
default: frappe.defaults.get_user_default("Company")
? locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]
: "",
reqd: 1,
get_query: function () {
var company = frappe.query_report.get_filter_value("company");
return {
query: "erpnext.controllers.queries.get_account_list",
filters: [
["Account", "account_type", "in", "Bank, Cash"],
["Account", "is_group", "=", 0],
["Account", "disabled", "=", 0],
["Account", "company", "=", company],
],
};
},
},
{
fieldname: "report_date",
label: __("Date"),
fieldtype: "Date",
default: frappe.datetime.get_today(),
reqd: 1,
},
],
};

View File

@@ -0,0 +1,29 @@
{
"add_total_row": 0,
"columns": [],
"creation": "2024-07-30 17:20:07.570971",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 0,
"is_standard": "Yes",
"letterhead": null,
"modified": "2024-07-30 17:20:07.570971",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cheques and Deposits Incorrectly cleared",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Payment Entry",
"report_name": "Cheques and Deposits Incorrectly cleared",
"report_type": "Script Report",
"roles": [
{
"role": "Accounts User"
},
{
"role": "Accounts Manager"
}
]
}

View File

@@ -0,0 +1,153 @@
# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
import frappe
from frappe import _, qb
from frappe.query_builder import CustomFunction
from frappe.query_builder.custom import ConstantColumn
def execute(filters=None):
columns = get_columns()
data = build_data(filters)
return columns, data
def build_payment_entry_dict(row: dict) -> dict:
row_dict = frappe._dict()
row_dict.update(
{
"payment_document": row.get("doctype"),
"payment_entry": row.get("name"),
"posting_date": row.get("posting_date"),
"clearance_date": row.get("clearance_date"),
}
)
if row.get("payment_type") == "Receive" and row.get("party_type") in ["Customer", "Supplier"]:
row_dict.update(
{
"debit": row.get("amount"),
"credit": 0,
}
)
else:
row_dict.update(
{
"debit": 0,
"credit": row.get("amount"),
}
)
return row_dict
def build_journal_entry_dict(row: dict) -> dict:
row_dict = frappe._dict()
row_dict.update(
{
"payment_document": row.get("doctype"),
"payment_entry": row.get("name"),
"posting_date": row.get("posting_date"),
"clearance_date": row.get("clearance_date"),
"debit": row.get("debit_in_account_currency"),
"credit": row.get("credit_in_account_currency"),
}
)
return row_dict
def build_data(filters):
vouchers = get_amounts_not_reflected_in_system_for_bank_reconciliation_statement(filters)
data = []
for x in vouchers:
if x.doctype == "Payment Entry":
data.append(build_payment_entry_dict(x))
elif x.doctype == "Journal Entry":
data.append(build_journal_entry_dict(x))
return data
def get_amounts_not_reflected_in_system_for_bank_reconciliation_statement(filters):
je = qb.DocType("Journal Entry")
jea = qb.DocType("Journal Entry Account")
doctype_name = ConstantColumn("Journal Entry")
journals = (
qb.from_(je)
.inner_join(jea)
.on(je.name == jea.parent)
.select(
doctype_name.as_("doctype"),
je.name,
jea.debit_in_account_currency,
jea.credit_in_account_currency,
je.posting_date,
je.clearance_date,
)
.where(
je.docstatus.eq(1)
& jea.account.eq(filters.account)
& je.posting_date.gt(filters.report_date)
& je.clearance_date.lte(filters.report_date)
& (je.is_opening.isnull() | je.is_opening.eq("No"))
)
.run(as_dict=1)
)
ifelse = CustomFunction("IF", ["condition", "then", "else"])
pe = qb.DocType("Payment Entry")
doctype_name = ConstantColumn("Payment Entry")
payments = (
qb.from_(pe)
.select(
doctype_name.as_("doctype"),
pe.name,
ifelse(pe.paid_from.eq(filters.account), pe.paid_amount, pe.received_amount).as_("amount"),
pe.payment_type,
pe.party_type,
pe.posting_date,
pe.clearance_date,
)
.where(
pe.docstatus.eq(1)
& (pe.paid_from.eq(filters.account) | pe.paid_to.eq(filters.account))
& pe.posting_date.gt(filters.report_date)
& pe.clearance_date.lte(filters.report_date)
)
.run(as_dict=1)
)
return journals + payments
def get_columns():
return [
{
"fieldname": "payment_document",
"label": _("Payment Document Type"),
"fieldtype": "Data",
"width": 220,
},
{
"fieldname": "payment_entry",
"label": _("Payment Document"),
"fieldtype": "Dynamic Link",
"options": "payment_document",
"width": 220,
},
{
"fieldname": "debit",
"label": _("Debit"),
"fieldtype": "Currency",
"options": "account_currency",
"width": 120,
},
{
"fieldname": "credit",
"label": _("Credit"),
"fieldtype": "Currency",
"options": "account_currency",
"width": 120,
},
{"fieldname": "posting_date", "label": _("Posting Date"), "fieldtype": "Date", "width": 110},
{"fieldname": "clearance_date", "label": _("Clearance Date"), "fieldtype": "Date", "width": 110},
]

View File

@@ -104,7 +104,7 @@ def get_balance_sheet_data(fiscal_year, companies, columns, filters):
if total_credit:
data.append(total_credit)
report_summary = get_bs_summary(
report_summary, primitive_summary = get_bs_summary(
companies,
asset,
liability,
@@ -175,7 +175,7 @@ def get_profit_loss_data(fiscal_year, companies, columns, filters):
chart = get_pl_chart_data(filters, columns, income, expense, net_profit_loss)
report_summary = get_pl_summary(
report_summary, primitive_summary = get_pl_summary(
companies, "", income, expense, net_profit_loss, company_currency, filters, True
)

View File

@@ -48,8 +48,9 @@
<br>
{% } %}
<br>{%= __("Remarks") %}: {%= data[i].remarks %}
{% if(data[i].bill_no) { %}
{% if(data[i].remarks) { %}
<br>{%= __("Remarks") %}: {%= data[i].remarks %}
{% } else if(data[i].bill_no) { %}
<br>{%= __("Supplier Invoice No") %}: {%= data[i].bill_no %}
{% } %}
</span>

View File

@@ -209,6 +209,11 @@ frappe.query_reports["General Ledger"] = {
label: __("Ignore Exchange Rate Revaluation Journals"),
fieldtype: "Check",
},
{
fieldname: "ignore_cr_dr_notes",
label: __("Ignore System Generated Credit / Debit Notes"),
fieldtype: "Check",
},
],
};

View File

@@ -236,6 +236,23 @@ def get_conditions(filters):
if err_journals:
filters.update({"voucher_no_not_in": [x[0] for x in err_journals]})
if filters.get("ignore_cr_dr_notes"):
system_generated_cr_dr_journals = frappe.db.get_all(
"Journal Entry",
filters={
"company": filters.get("company"),
"docstatus": 1,
"voucher_type": ("in", ["Credit Note", "Debit Note"]),
"is_system_generated": 1,
},
as_list=True,
)
if system_generated_cr_dr_journals:
vouchers_to_ignore = (filters.get("voucher_no_not_in") or []) + [
x[0] for x in system_generated_cr_dr_journals
]
filters.update({"voucher_no_not_in": vouchers_to_ignore})
if filters.get("voucher_no_not_in"):
conditions.append("voucher_no not in %(voucher_no_not_in)s")

View File

@@ -2,13 +2,32 @@
# MIT License. See license.txt
import frappe
from frappe import qb
from frappe.tests.utils import FrappeTestCase
from frappe.utils import flt, today
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.report.general_ledger.general_ledger import execute
from erpnext.controllers.sales_and_purchase_return import make_return_doc
class TestGeneralLedger(FrappeTestCase):
def setUp(self):
self.company = "_Test Company"
self.clear_old_entries()
def clear_old_entries(self):
doctype_list = [
"GL Entry",
"Payment Ledger Entry",
"Sales Invoice",
"Purchase Invoice",
"Payment Entry",
"Journal Entry",
]
for doctype in doctype_list:
qb.from_(qb.DocType(doctype)).delete().where(qb.DocType(doctype).company == self.company).run()
def test_foreign_account_balance_after_exchange_rate_revaluation(self):
"""
Checks the correctness of balance after exchange rate revaluation
@@ -248,3 +267,68 @@ class TestGeneralLedger(FrappeTestCase):
)
)
self.assertIn(revaluation_jv.name, set([x.voucher_no for x in data]))
def test_ignore_cr_dr_notes_filter(self):
si = create_sales_invoice()
cr_note = make_return_doc(si.doctype, si.name)
cr_note.submit()
pr = frappe.get_doc("Payment Reconciliation")
pr.company = si.company
pr.party_type = "Customer"
pr.party = si.customer
pr.receivable_payable_account = si.debit_to
pr.get_unreconciled_entries()
invoices = [invoice.as_dict() for invoice in pr.invoices if invoice.invoice_number == si.name]
payments = [payment.as_dict() for payment in pr.payments if payment.reference_name == cr_note.name]
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
pr.reconcile()
system_generated_journal = frappe.db.get_all(
"Journal Entry",
filters={
"docstatus": 1,
"reference_type": si.doctype,
"reference_name": si.name,
"voucher_type": "Credit Note",
"is_system_generated": True,
},
fields=["name"],
)
self.assertEqual(len(system_generated_journal), 1)
expected = set([si.name, cr_note.name, system_generated_journal[0].name])
# Without ignore_cr_dr_notes
columns, data = execute(
frappe._dict(
{
"company": si.company,
"from_date": si.posting_date,
"to_date": si.posting_date,
"account": [si.debit_to],
"group_by": "Group by Voucher (Consolidated)",
"ignore_cr_dr_notes": False,
}
)
)
actual = set([x.voucher_no for x in data if x.voucher_no])
self.assertEqual(expected, actual)
# Without ignore_cr_dr_notes
expected = set([si.name, cr_note.name])
columns, data = execute(
frappe._dict(
{
"company": si.company,
"from_date": si.posting_date,
"to_date": si.posting_date,
"account": [si.debit_to],
"group_by": "Group by Voucher (Consolidated)",
"ignore_cr_dr_notes": True,
}
)
)
actual = set([x.voucher_no for x in data if x.voucher_no])
self.assertEqual(expected, actual)

View File

@@ -0,0 +1,51 @@
// Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
function get_filters() {
let filters = [
{
fieldname: "company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
default: frappe.defaults.get_user_default("Company"),
reqd: 1,
},
{
fieldname: "from_date",
label: __("Start Date"),
fieldtype: "Date",
reqd: 1,
default: frappe.datetime.add_months(frappe.datetime.get_today(), -1),
},
{
fieldname: "to_date",
label: __("End Date"),
fieldtype: "Date",
reqd: 1,
default: frappe.datetime.get_today(),
},
{
fieldname: "account",
label: __("Account"),
fieldtype: "MultiSelectList",
options: "Account",
get_data: function (txt) {
return frappe.db.get_link_options("Account", txt, {
company: frappe.query_report.get_filter_value("company"),
});
},
},
{
fieldname: "voucher_no",
label: __("Voucher No"),
fieldtype: "Data",
width: 100,
},
];
return filters;
}
frappe.query_reports["Invalid Ledger Entries"] = {
filters: get_filters(),
};

View File

@@ -0,0 +1,23 @@
{
"add_total_row": 0,
"columns": [],
"creation": "2024-09-09 12:31:25.295976",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 0,
"is_standard": "Yes",
"letterhead": null,
"modified": "2024-09-09 12:31:25.295976",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Invalid Ledger Entries",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "GL Entry",
"report_name": "Invalid Ledger Entries",
"report_type": "Script Report",
"roles": [],
"timeout": 0
}

View File

@@ -0,0 +1,137 @@
# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
import frappe
from frappe import _, qb
from frappe.query_builder import Criterion
from frappe.query_builder.custom import ConstantColumn
def execute(filters: dict | None = None):
"""Return columns and data for the report.
This is the main entry point for the report. It accepts the filters as a
dictionary and should return columns and data. It is called by the framework
every time the report is refreshed or a filter is updated.
"""
validate_filters(filters)
columns = get_columns()
data = get_data(filters)
return columns, data
def get_columns() -> list[dict]:
"""Return columns for the report.
One field definition per column, just like a DocType field definition.
"""
return [
{"label": _("Voucher Type"), "fieldname": "voucher_type", "fieldtype": "Link", "options": "DocType"},
{
"label": _("Voucher No"),
"fieldname": "voucher_no",
"fieldtype": "Dynamic Link",
"options": "voucher_type",
},
]
def get_data(filters) -> list[list]:
"""Return data for the report.
The report data is a list of rows, with each row being a list of cell values.
"""
active_vouchers = get_active_vouchers_for_period(filters)
invalid_vouchers = identify_cancelled_vouchers(active_vouchers)
return invalid_vouchers
def identify_cancelled_vouchers(active_vouchers: list[dict] | list | None = None) -> list[dict]:
cancelled_vouchers = []
if active_vouchers:
# Group by voucher types and use single query to identify cancelled vouchers
vtypes = set([x.voucher_type for x in active_vouchers])
for _t in vtypes:
_names = [x.voucher_no for x in active_vouchers if x.voucher_type == _t]
dt = qb.DocType(_t)
non_active_vouchers = (
qb.from_(dt)
.select(ConstantColumn(_t).as_("voucher_type"), dt.name.as_("voucher_no"))
.where(dt.docstatus.ne(1) & dt.name.isin(_names))
.run(as_dict=True)
)
if non_active_vouchers:
cancelled_vouchers.extend(non_active_vouchers)
return cancelled_vouchers
def validate_filters(filters: dict | None = None):
if not filters:
frappe.throw(_("Filters missing"))
if not filters.company:
frappe.throw(_("Company is mandatory"))
if filters.from_date > filters.to_date:
frappe.throw(_("Start Date should be lower than End Date"))
def build_query_filters(filters: dict | None = None) -> list:
qb_filters = []
if filters:
if filters.account:
qb_filters.append(qb.Field("account").isin(filters.account))
if filters.voucher_no:
qb_filters.append(qb.Field("voucher_no").eq(filters.voucher_no))
return qb_filters
def get_active_vouchers_for_period(filters: dict | None = None) -> list[dict]:
uniq_vouchers = []
if filters:
gle = qb.DocType("GL Entry")
ple = qb.DocType("Payment Ledger Entry")
qb_filters = build_query_filters(filters)
gl_vouchers = (
qb.from_(gle)
.select(gle.voucher_type)
.distinct()
.select(gle.voucher_no)
.distinct()
.where(
gle.is_cancelled.eq(0)
& gle.company.eq(filters.company)
& gle.posting_date[filters.from_date : filters.to_date]
)
.where(Criterion.all(qb_filters))
.run(as_dict=True)
)
pl_vouchers = (
qb.from_(ple)
.select(ple.voucher_type)
.distinct()
.select(ple.voucher_no)
.distinct()
.where(
ple.delinked.eq(0)
& ple.company.eq(filters.company)
& ple.posting_date[filters.from_date : filters.to_date]
)
.where(Criterion.all(qb_filters))
.run(as_dict=True)
)
uniq_vouchers.extend(gl_vouchers)
uniq_vouchers.extend(pl_vouchers)
return uniq_vouchers

View File

@@ -315,8 +315,9 @@ def apply_conditions(query, pi, pii, filters):
def get_items(filters, additional_table_columns):
pi = frappe.qb.DocType("Purchase Invoice")
pii = frappe.qb.DocType("Purchase Invoice Item")
doctype = "Purchase Invoice"
pi = frappe.qb.DocType(doctype)
pii = frappe.qb.DocType(f"{doctype} Item")
Item = frappe.qb.DocType("Item")
query = (
frappe.qb.from_(pi)
@@ -353,6 +354,7 @@ def get_items(filters, additional_table_columns):
pi.mode_of_payment,
)
.where(pi.docstatus == 1)
.where(pii.parenttype == doctype)
)
if filters.get("supplier"):

View File

@@ -0,0 +1,63 @@
import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import getdate, today
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.accounts.report.item_wise_purchase_register.item_wise_purchase_register import execute
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
class TestItemWisePurchaseRegister(AccountsTestMixin, FrappeTestCase):
def setUp(self):
self.create_company()
self.create_supplier()
self.create_item()
def tearDown(self):
frappe.db.rollback()
def create_purchase_invoice(self, do_not_submit=False):
pi = make_purchase_invoice(
item=self.item,
company=self.company,
supplier=self.supplier,
is_return=False,
update_stock=False,
do_not_save=1,
rate=100,
price_list_rate=100,
qty=1,
)
pi = pi.save()
if not do_not_submit:
pi = pi.submit()
return pi
def test_basic_report_output(self):
pi = self.create_purchase_invoice()
filters = frappe._dict({"from_date": today(), "to_date": today(), "company": self.company})
report = execute(filters)
self.assertEqual(len(report[1]), 1)
expected_result = {
"item_code": pi.items[0].item_code,
"invoice": pi.name,
"posting_date": getdate(),
"supplier": pi.supplier,
"credit_to": pi.credit_to,
"company": self.company,
"expense_account": pi.items[0].expense_account,
"stock_qty": 1.0,
"stock_uom": pi.items[0].stock_uom,
"rate": 100.0,
"amount": 100.0,
"total_tax": 0,
"total": 100.0,
"currency": "INR",
}
report_output = {k: v for k, v in report[1][0].items() if k in expected_result}
self.assertDictEqual(report_output, expected_result)

View File

@@ -410,8 +410,9 @@ def apply_group_by_conditions(query, si, ii, filters):
def get_items(filters, additional_query_columns, additional_conditions=None):
si = frappe.qb.DocType("Sales Invoice")
sii = frappe.qb.DocType("Sales Invoice Item")
doctype = "Sales Invoice"
si = frappe.qb.DocType(doctype)
sii = frappe.qb.DocType(f"{doctype} Item")
item = frappe.qb.DocType("Item")
query = (
@@ -459,6 +460,7 @@ def get_items(filters, additional_query_columns, additional_conditions=None):
sii.qty,
)
.where(si.docstatus == 1)
.where(sii.parenttype == doctype)
)
if additional_query_columns:

View File

@@ -336,7 +336,7 @@ def get_tds_docs(filters):
def get_tds_docs_query(filters, bank_accounts, tds_accounts):
if not tds_accounts:
frappe.throw(
_("No {0} Accounts found for this company.").format(frappe.bold("Tax Withholding")),
_("No {0} Accounts found for this company.").format(frappe.bold(_("Tax Withholding"))),
title=_("Accounts Missing Error"),
)
gle = frappe.qb.DocType("GL Entry")

View File

@@ -14,8 +14,8 @@ DEFAULT_FILTERS = {
REPORT_FILTER_TEST_CASES: list[tuple[ReportName, ReportFilters]] = [
("General Ledger", {"group_by": "Group by Voucher (Consolidated)"}),
("General Ledger", {"group_by": "Group by Voucher (Consolidated)", "include_dimensions": 1}),
("Accounts Payable", {"range1": 30, "range2": 60, "range3": 90, "range4": 120}),
("Accounts Receivable", {"range1": 30, "range2": 60, "range3": 90, "range4": 120}),
("Accounts Payable", {"range": "30, 60, 90, 120"}),
("Accounts Receivable", {"range": "30, 60, 90, 120"}),
("Consolidated Financial Statement", {"report": "Balance Sheet"}),
("Consolidated Financial Statement", {"report": "Profit and Loss Statement"}),
("Consolidated Financial Statement", {"report": "Cash Flow"}),

View File

@@ -781,6 +781,46 @@ def cancel_exchange_gain_loss_journal(
gain_loss_je.cancel()
def cancel_common_party_journal(self):
if self.doctype not in ["Sales Invoice", "Purchase Invoice"]:
return
if not frappe.db.get_single_value("Accounts Settings", "enable_common_party_accounting"):
return
party_link = self.get_common_party_link()
if not party_link:
return
journal_entry = frappe.db.get_value(
"Journal Entry Account",
filters={
"reference_type": self.doctype,
"reference_name": self.name,
"docstatus": 1,
},
fieldname="parent",
)
if not journal_entry:
return
common_party_journal = frappe.db.get_value(
"Journal Entry",
filters={
"name": journal_entry,
"is_system_generated": True,
"docstatus": 1,
},
)
if not common_party_journal:
return
common_party_je = frappe.get_doc("Journal Entry", common_party_journal)
common_party_je.cancel()
def update_accounting_ledgers_after_reference_removal(
ref_type: str | None = None, ref_no: str | None = None, payment_name: str | None = None
):
@@ -1598,6 +1638,18 @@ def auto_create_exchange_rate_revaluation_weekly() -> None:
create_err_and_its_journals(companies)
def auto_create_exchange_rate_revaluation_monthly() -> None:
"""
Executed by background job
"""
companies = frappe.db.get_all(
"Company",
filters={"auto_exchange_rate_revaluation": 1, "auto_err_frequency": "Montly"},
fields=["name", "submit_err_jv"],
)
create_err_and_its_journals(companies)
def get_payment_ledger_entries(gl_entries, cancel=0):
ple_map = []
if gl_entries:

View File

@@ -188,11 +188,21 @@ frappe.ui.form.on("Asset", {
frm.toggle_reqd("finance_books", frm.doc.calculate_depreciation);
if (frm.doc.is_composite_asset) {
$(".primary-action").prop("hidden", true);
$(".form-message").text("Capitalize this asset to confirm");
frappe.call({
method: "erpnext.assets.doctype.asset.asset.has_active_capitalization",
args: {
asset: frm.doc.name,
},
callback: function (r) {
if (!r.message) {
$(".primary-action").prop("hidden", true);
$(".form-message").text("Capitalize this asset to confirm");
frm.add_custom_button(__("Capitalize Asset"), function () {
frm.trigger("create_asset_capitalization");
frm.add_custom_button(__("Capitalize Asset"), function () {
frm.trigger("create_asset_capitalization");
});
}
},
});
}
}
@@ -496,6 +506,7 @@ frappe.ui.form.on("Asset", {
create_asset_repair: function (frm) {
frappe.call({
args: {
company: frm.doc.company,
asset: frm.doc.name,
asset_name: frm.doc.asset_name,
},
@@ -510,6 +521,7 @@ frappe.ui.form.on("Asset", {
create_asset_capitalization: function (frm) {
frappe.call({
args: {
company: frm.doc.company,
asset: frm.doc.name,
asset_name: frm.doc.asset_name,
item_code: frm.doc.item_code,
@@ -518,6 +530,7 @@ frappe.ui.form.on("Asset", {
callback: function (r) {
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
$(".primary-action").prop("hidden", false);
},
});
},
@@ -660,6 +673,11 @@ frappe.ui.form.on("Asset", {
if (item.asset_location) {
frm.set_value("location", item.asset_location);
}
if (doctype === "Purchase Receipt") {
frm.set_value("purchase_receipt_item", item.name);
} else if (doctype === "Purchase Invoice") {
frm.set_value("purchase_invoice_item", item.name);
}
});
},
@@ -775,11 +793,8 @@ frappe.ui.form.on("Asset Finance Book", {
depreciation_start_date: function (frm, cdt, cdn) {
const book = locals[cdt][cdn];
if (
frm.doc.available_for_use_date &&
book.depreciation_start_date == frm.doc.available_for_use_date
) {
frappe.msgprint(__("Depreciation Posting Date should not be equal to Available for Use Date."));
if (frm.doc.available_for_use_date && book.depreciation_start_date < frm.doc.available_for_use_date) {
frappe.msgprint(__("Depreciation Posting Date cannot be before Available-for-use Date"));
book.depreciation_start_date = "";
frm.refresh_field("finance_books");
}

View File

@@ -33,14 +33,16 @@
"dimension_col_break",
"purchase_details_section",
"purchase_receipt",
"purchase_receipt_item",
"purchase_invoice",
"purchase_invoice_item",
"purchase_date",
"available_for_use_date",
"total_asset_cost",
"additional_asset_cost",
"column_break_23",
"gross_purchase_amount",
"asset_quantity",
"purchase_date",
"additional_asset_cost",
"total_asset_cost",
"section_break_23",
"calculate_depreciation",
"column_break_33",
@@ -221,7 +223,6 @@
"read_only": 1
},
{
"depends_on": "eval:!doc.is_composite_asset",
"fieldname": "gross_purchase_amount",
"fieldtype": "Currency",
"label": "Gross Purchase Amount",
@@ -537,6 +538,20 @@
"fieldname": "opening_number_of_booked_depreciations",
"fieldtype": "Int",
"label": "Opening Number of Booked Depreciations"
},
{
"fieldname": "purchase_receipt_item",
"fieldtype": "Link",
"hidden": 1,
"label": "Purchase Receipt Item",
"options": "Purchase Receipt Item"
},
{
"fieldname": "purchase_invoice_item",
"fieldtype": "Link",
"hidden": 1,
"label": "Purchase Invoice Item",
"options": "Purchase Invoice Item"
}
],
"idx": 72,
@@ -580,7 +595,7 @@
"link_fieldname": "target_asset"
}
],
"modified": "2024-07-07 22:27:14.733839",
"modified": "2024-08-26 23:28:29.095139",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset",

View File

@@ -94,7 +94,9 @@ class Asset(AccountsController):
purchase_amount: DF.Currency
purchase_date: DF.Date | None
purchase_invoice: DF.Link | None
purchase_invoice_item: DF.Link | None
purchase_receipt: DF.Link | None
purchase_receipt_item: DF.Link | None
split_from: DF.Link | None
status: DF.Literal[
"Draft",
@@ -123,7 +125,6 @@ class Asset(AccountsController):
self.validate_cost_center()
self.set_missing_values()
self.validate_gross_and_purchase_amount()
self.validate_expected_value_after_useful_life()
self.validate_finance_books()
if not self.split_from:
@@ -144,6 +145,7 @@ class Asset(AccountsController):
"Asset Depreciation Schedules created:<br>{0}<br><br>Please check, edit if needed, and submit the Asset."
).format(asset_depr_schedules_links)
)
self.validate_expected_value_after_useful_life()
self.set_total_booked_depreciations()
self.total_asset_cost = self.gross_purchase_amount
self.status = self.get_status()
@@ -267,10 +269,10 @@ class Asset(AccountsController):
frappe.throw(_("Available for use date is required"))
for d in self.finance_books:
if d.depreciation_start_date == self.available_for_use_date:
if getdate(d.depreciation_start_date) < getdate(self.available_for_use_date):
frappe.throw(
_(
"Row #{}: Depreciation Posting Date should not be equal to Available for Use Date."
"Depreciation Row {0}: Depreciation Posting Date cannot be before Available-for-use Date"
).format(d.idx),
title=_("Incorrect Date"),
)
@@ -669,7 +671,7 @@ class Asset(AccountsController):
if not fixed_asset_account:
frappe.throw(
_("Set {0} in asset category {1} for company {2}").format(
frappe.bold("Fixed Asset Account"),
frappe.bold(_("Fixed Asset Account")),
frappe.bold(self.asset_category),
frappe.bold(self.company),
),
@@ -691,12 +693,17 @@ class Asset(AccountsController):
return cwip_account
def make_gl_entries(self):
if self.check_asset_capitalization_gl_entries():
return
gl_entries = []
purchase_document = self.get_purchase_document()
fixed_asset_account, cwip_account = self.get_fixed_asset_account(), self.get_cwip_account()
if purchase_document and self.purchase_amount and getdate(self.available_for_use_date) <= getdate():
if (self.is_composite_asset or (purchase_document and self.purchase_amount)) and getdate(
self.available_for_use_date
) <= getdate():
gl_entries.append(
self.get_gl_dict(
{
@@ -733,6 +740,24 @@ class Asset(AccountsController):
make_gl_entries(gl_entries)
self.db_set("booked_fixed_asset", 1)
def check_asset_capitalization_gl_entries(self):
if self.is_composite_asset:
result = frappe.db.get_value(
"Asset Capitalization",
{"target_asset": self.name, "docstatus": 1},
["name", "target_fixed_asset_account"],
)
if result:
asset_capitalization, target_fixed_asset_account = result
# Check GL entries for the retrieved Asset Capitalization and target fixed asset account
return has_gl_entries(
"Asset Capitalization", asset_capitalization, target_fixed_asset_account
)
# return if there are no submitted capitalization for given asset
return True
return False
@frappe.whitelist()
def get_depreciation_rate(self, args, on_validate=False):
if isinstance(args, str):
@@ -779,6 +804,22 @@ class Asset(AccountsController):
return flt((100 * (1 - depreciation_rate)), float_precision)
def has_gl_entries(doctype, docname, target_account):
gl_entry = frappe.qb.DocType("GL Entry")
gl_entries = (
frappe.qb.from_(gl_entry)
.select(gl_entry.account)
.where(
(gl_entry.voucher_type == doctype)
& (gl_entry.voucher_no == docname)
& (gl_entry.debit != 0)
& (gl_entry.account == target_account)
)
.run(as_dict=True)
)
return len(gl_entries) > 0
def update_maintenance_status():
assets = frappe.get_all(
"Asset", filters={"docstatus": 1, "maintenance_required": 1, "disposal_date": ("is", "not set")}
@@ -854,18 +895,19 @@ def create_asset_maintenance(asset, item_code, item_name, asset_category, compan
@frappe.whitelist()
def create_asset_repair(asset, asset_name):
def create_asset_repair(company, asset, asset_name):
asset_repair = frappe.new_doc("Asset Repair")
asset_repair.update({"asset": asset, "asset_name": asset_name})
asset_repair.update({"company": company, "asset": asset, "asset_name": asset_name})
return asset_repair
@frappe.whitelist()
def create_asset_capitalization(asset, asset_name, item_code):
def create_asset_capitalization(company, asset, asset_name, item_code):
asset_capitalization = frappe.new_doc("Asset Capitalization")
asset_capitalization.update(
{
"target_asset": asset,
"company": company,
"capitalization_method": "Choose a WIP composite asset",
"target_asset_name": asset_name,
"target_item_code": item_code,
@@ -904,7 +946,7 @@ def transfer_asset(args):
@frappe.whitelist()
def get_item_details(item_code, asset_category, gross_purchase_amount):
asset_category_doc = frappe.get_doc("Asset Category", asset_category)
asset_category_doc = frappe.get_cached_doc("Asset Category", asset_category)
books = []
for d in asset_category_doc.finance_books:
books.append(
@@ -1035,6 +1077,14 @@ def get_asset_value_after_depreciation(asset_name, finance_book=None):
return asset.get_value_after_depreciation(finance_book)
@frappe.whitelist()
def has_active_capitalization(asset):
active_capitalizations = frappe.db.count(
"Asset Capitalization", filters={"target_asset": asset, "docstatus": 1}
)
return active_capitalizations > 0
@frappe.whitelist()
def split_asset(asset_name, split_qty):
asset = frappe.get_doc("Asset", asset_name)

View File

@@ -234,7 +234,7 @@ class TestAsset(AssetSetup):
pro_rata_amount, _, _ = _get_pro_rata_amt(
asset.finance_books[0],
9000,
get_last_day(add_months(purchase_date, 1)),
add_days(get_last_day(add_months(purchase_date, 1)), 1),
date,
original_schedule_date=get_last_day(nowdate()),
)
@@ -320,7 +320,7 @@ class TestAsset(AssetSetup):
pro_rata_amount, _, _ = _get_pro_rata_amt(
asset.finance_books[0],
9000,
get_last_day(add_months(purchase_date, 1)),
add_days(get_last_day(add_months(purchase_date, 1)), 1),
date,
original_schedule_date=get_last_day(nowdate()),
)
@@ -740,7 +740,7 @@ class TestDepreciationMethods(AssetSetup):
available_for_use_date="2030-06-06",
is_existing_asset=1,
opening_number_of_booked_depreciations=2,
opening_accumulated_depreciation=47095.89,
opening_accumulated_depreciation=47178.08,
expected_value_after_useful_life=10000,
depreciation_start_date="2032-12-31",
total_number_of_depreciations=3,
@@ -748,7 +748,7 @@ class TestDepreciationMethods(AssetSetup):
)
self.assertEqual(asset.status, "Draft")
expected_schedules = [["2032-12-31", 42904.11, 90000.0]]
expected_schedules = [["2032-12-31", 30000.0, 77178.08], ["2033-06-06", 12821.92, 90000.0]]
schedules = [
[cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount]
for d in get_depr_schedule(asset.name, "Draft")

View File

@@ -11,6 +11,7 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
onload() {
this.setup_queries();
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
}
refresh() {

View File

@@ -317,7 +317,16 @@ class AssetCapitalization(StockController):
if not self.target_is_fixed_asset and not self.get("asset_items"):
frappe.throw(_("Consumed Asset Items is mandatory for Decapitalization"))
if not (self.get("stock_items") or self.get("asset_items") or self.get("service_items")):
if self.capitalization_method == "Create a new composite asset" and not (
self.get("stock_items") or self.get("asset_items")
):
frappe.throw(
_(
"Consumed Stock Items or Consumed Asset Items are mandatory for creating new composite asset"
)
)
elif not (self.get("stock_items") or self.get("asset_items") or self.get("service_items")):
frappe.throw(
_(
"Consumed Stock Items, Consumed Asset Items or Consumed Service Items is mandatory for Capitalization"
@@ -460,13 +469,24 @@ class AssetCapitalization(StockController):
self.get_gl_entries_for_consumed_asset_items(gl_entries, target_account, target_against, precision)
self.get_gl_entries_for_consumed_service_items(gl_entries, target_account, target_against, precision)
self.get_gl_entries_for_target_item(gl_entries, target_against, precision)
self.get_gl_entries_for_target_item(gl_entries, target_account, target_against, precision)
return gl_entries
def get_target_account(self):
if self.target_is_fixed_asset:
return self.target_fixed_asset_account
from erpnext.assets.doctype.asset.asset import is_cwip_accounting_enabled
asset_category = frappe.get_cached_value("Asset", self.target_asset, "asset_category")
if is_cwip_accounting_enabled(asset_category):
target_account = get_asset_category_account(
"capital_work_in_progress_account",
asset_category=asset_category,
company=self.company,
)
return target_account if target_account else self.target_fixed_asset_account
else:
return self.target_fixed_asset_account
else:
return self.warehouse_account[self.target_warehouse]["account"]
@@ -554,13 +574,13 @@ class AssetCapitalization(StockController):
)
)
def get_gl_entries_for_target_item(self, gl_entries, target_against, precision):
def get_gl_entries_for_target_item(self, gl_entries, target_account, target_against, precision):
if self.target_is_fixed_asset:
# Capitalization
gl_entries.append(
self.get_gl_dict(
{
"account": self.target_fixed_asset_account,
"account": target_account,
"against": ", ".join(target_against),
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
"debit": flt(self.total_value, precision),

View File

@@ -31,6 +31,12 @@ class TestAssetCapitalization(unittest.TestCase):
def test_capitalization_with_perpetual_inventory(self):
company = "_Test Company with perpetual inventory"
set_depreciation_settings_in_company(company=company)
name = frappe.db.get_value(
"Asset Category Account",
filters={"parent": "Computers", "company_name": company},
fieldname=["name"],
)
frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", "")
# Variables
consumed_asset_value = 100000
@@ -187,9 +193,10 @@ class TestAssetCapitalization(unittest.TestCase):
# Test General Ledger Entries
default_expense_account = frappe.db.get_value("Company", company, "default_expense_account")
expected_gle = {
"_Test Fixed Asset - _TC": 3000,
"Expenses Included In Asset Valuation - _TC": -1000,
default_expense_account: -2000,
"_Test Fixed Asset - _TC": -100000.0,
default_expense_account: -2000.0,
"CWIP Account - _TC": 103000.0,
"Expenses Included In Asset Valuation - _TC": -1000.0,
}
actual_gle = get_actual_gle_dict(asset_capitalization.name)
@@ -214,6 +221,12 @@ class TestAssetCapitalization(unittest.TestCase):
def test_capitalization_with_wip_composite_asset(self):
company = "_Test Company with perpetual inventory"
set_depreciation_settings_in_company(company=company)
name = frappe.db.get_value(
"Asset Category Account",
filters={"parent": "Computers", "company_name": company},
fieldname=["name"],
)
frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", "")
stock_rate = 1000
stock_qty = 2
@@ -424,7 +437,7 @@ class TestAssetCapitalization(unittest.TestCase):
self.assertEqual(target_asset.purchase_amount, total_amount)
expected_gle = {
"_Test Fixed Asset - _TC": 1000.0,
"CWIP Account - _TC": 1000.0,
"Expenses Included In Asset Valuation - _TC": -1000.0,
}

View File

@@ -291,7 +291,9 @@ class AssetDepreciationSchedule(Document):
if skip_row:
continue
schedule_date = add_months(row.depreciation_start_date, n * cint(row.frequency_of_depreciation))
schedule_date = get_last_day(
add_months(row.depreciation_start_date, n * cint(row.frequency_of_depreciation))
)
if not current_fiscal_year_end_date:
current_fiscal_year_end_date = get_fiscal_year(row.depreciation_start_date)[2]
elif getdate(schedule_date) > getdate(current_fiscal_year_end_date):
@@ -330,8 +332,10 @@ class AssetDepreciationSchedule(Document):
getdate(asset_doc.available_for_use_date),
(asset_doc.opening_number_of_booked_depreciations * row.frequency_of_depreciation),
)
if is_last_day_of_the_month(getdate(asset_doc.available_for_use_date)):
from_date = get_last_day(from_date)
if self.depreciation_schedule:
from_date = self.depreciation_schedule[-1].schedule_date
from_date = add_days(self.depreciation_schedule[-1].schedule_date, 1)
depreciation_amount, days, months = _get_pro_rata_amt(
row,
@@ -353,9 +357,8 @@ class AssetDepreciationSchedule(Document):
and not self.opening_accumulated_depreciation
and not self.flags.wdv_it_act_applied
):
from_date = add_days(
asset_doc.available_for_use_date, -1
) # needed to calc depr amount for available_for_use_date too
from_date = asset_doc.available_for_use_date
# needed to calc depr amount for available_for_use_date too
depreciation_amount, days, months = _get_pro_rata_amt(
row,
depreciation_amount,
@@ -406,6 +409,8 @@ class AssetDepreciationSchedule(Document):
(n + self.opening_number_of_booked_depreciations)
* cint(row.frequency_of_depreciation),
)
if is_last_day_of_the_month(getdate(asset_doc.available_for_use_date)):
asset_doc.to_date = get_last_day(asset_doc.to_date)
depreciation_amount_without_pro_rata = depreciation_amount
@@ -421,7 +426,7 @@ class AssetDepreciationSchedule(Document):
depreciation_amount_without_pro_rata, depreciation_amount
)
schedule_date = add_days(schedule_date, days)
schedule_date = add_days(schedule_date, days - 1)
if not depreciation_amount:
continue
@@ -504,7 +509,10 @@ class AssetDepreciationSchedule(Document):
continue
if not accumulated_depreciation:
if i > 0 and asset_doc.flags.decrease_in_asset_value_due_to_value_adjustment:
if i > 0 and (
asset_doc.flags.decrease_in_asset_value_due_to_value_adjustment
or asset_doc.flags.increase_in_asset_value_due_to_repair
):
accumulated_depreciation = self.get("depreciation_schedule")[
i - 1
].accumulated_depreciation_amount
@@ -552,9 +560,20 @@ def _check_is_pro_rata(asset_doc, row, wdv_or_dd_non_yearly=False):
# if not existing asset, from_date = available_for_use_date
# otherwise, if opening_number_of_booked_depreciations = 2, available_for_use_date = 01/01/2020 and frequency_of_depreciation = 12
# from_date = 01/01/2022
from_date = _get_modified_available_for_use_date(asset_doc, row, wdv_or_dd_non_yearly=False)
days = date_diff(row.depreciation_start_date, from_date) + 1
total_days = get_total_days(row.depreciation_start_date, row.frequency_of_depreciation)
if row.depreciation_method in ("Straight Line", "Manual"):
prev_depreciation_start_date = get_last_day(
add_months(
row.depreciation_start_date,
(row.frequency_of_depreciation * -1) * asset_doc.opening_number_of_booked_depreciations,
)
)
from_date = asset_doc.available_for_use_date
days = date_diff(prev_depreciation_start_date, from_date) + 1
total_days = get_total_days(prev_depreciation_start_date, row.frequency_of_depreciation)
else:
from_date = _get_modified_available_for_use_date(asset_doc, row, wdv_or_dd_non_yearly=False)
days = date_diff(row.depreciation_start_date, from_date) + 1
total_days = get_total_days(row.depreciation_start_date, row.frequency_of_depreciation)
if days <= 0:
frappe.throw(
_(
@@ -601,7 +620,7 @@ def _get_pro_rata_amt(
has_wdv_or_dd_non_yearly_pro_rata=False,
original_schedule_date=None,
):
days = date_diff(to_date, from_date)
days = date_diff(to_date, from_date) + 1
months = month_diff(to_date, from_date)
if has_wdv_or_dd_non_yearly_pro_rata:
total_days = get_total_days(original_schedule_date or to_date, 12)
@@ -661,7 +680,7 @@ def get_straight_line_or_manual_depr_amount(
# if the Depreciation Schedule is being modified after Asset Repair due to increase in asset value
elif asset.flags.increase_in_asset_value_due_to_repair:
return (flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)) / flt(
row.total_number_of_depreciations
number_of_pending_depreciations
)
# if the Depreciation Schedule is being modified after Asset Value Adjustment due to decrease in asset value
elif asset.flags.decrease_in_asset_value_due_to_value_adjustment:
@@ -682,20 +701,15 @@ def get_straight_line_or_manual_depr_amount(
# if the Depreciation Schedule is being prepared for the first time
else:
if row.daily_prorata_based:
amount = (
flt(asset.gross_purchase_amount)
- flt(asset.opening_accumulated_depreciation)
- flt(row.expected_value_after_useful_life)
)
amount = flt(asset.gross_purchase_amount) - flt(row.expected_value_after_useful_life)
return get_daily_prorata_based_straight_line_depr(
asset, row, schedule_idx, number_of_pending_depreciations, amount
)
else:
return (
flt(asset.gross_purchase_amount)
- flt(asset.opening_accumulated_depreciation)
- flt(row.expected_value_after_useful_life)
) / flt(row.total_number_of_depreciations - asset.opening_number_of_booked_depreciations)
depreciation_amount = (
flt(asset.gross_purchase_amount) - flt(row.expected_value_after_useful_life)
) / flt(row.total_number_of_depreciations)
return depreciation_amount
def get_daily_prorata_based_straight_line_depr(
@@ -725,7 +739,16 @@ def get_daily_depr_amount(asset, row, schedule_idx, amount):
)
),
add_days(
get_last_day(add_months(row.depreciation_start_date, -1 * row.frequency_of_depreciation)),
get_last_day(
add_months(
row.depreciation_start_date,
(
row.frequency_of_depreciation
* (asset.opening_number_of_booked_depreciations + 1)
)
* -1,
),
),
1,
),
)
@@ -744,8 +767,12 @@ def get_daily_depr_amount(asset, row, schedule_idx, amount):
every_year_depr = amount / total_years
depr_period_start_date = add_days(
get_last_day(add_months(row.depreciation_start_date, row.frequency_of_depreciation * -1)), 1
)
year_start_date = add_years(
row.depreciation_start_date, (row.frequency_of_depreciation * schedule_idx) // 12
depr_period_start_date, ((row.frequency_of_depreciation * schedule_idx) // 12)
)
year_end_date = add_days(add_years(year_start_date, 1), -1)
@@ -904,7 +931,7 @@ def _get_daily_prorata_based_default_wdv_or_dd_depr_amount(
def get_monthly_depr_amount(fb_row, schedule_idx, depreciable_value):
""" "
"""
Returns monthly depreciation amount when year changes
1. Calculate per day depr based on new year
2. Calculate monthly amount based on new per day amount
@@ -1021,6 +1048,7 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones(
date_of_return=None,
value_after_depreciation=None,
ignore_booked_entry=False,
difference_amount=None,
):
for row in asset_doc.get("finance_books"):
current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(
@@ -1035,6 +1063,8 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones(
)
new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc)
if asset_doc.flags.decrease_in_asset_value_due_to_value_adjustment and not value_after_depreciation:
value_after_depreciation = row.value_after_depreciation + difference_amount
if asset_doc.flags.increase_in_asset_value_due_to_repair and row.depreciation_method in (
"Written Down Value",

View File

@@ -75,6 +75,116 @@ class TestAssetDepreciationSchedule(FrappeTestCase):
]
self.assertEqual(schedules, expected_schedules)
def test_schedule_for_slm_for_existing_asset_daily_pro_rata_enabled(self):
frappe.db.set_single_value("Accounts Settings", "calculate_depr_using_total_days", 1)
asset = create_asset(
calculate_depreciation=1,
depreciation_method="Straight Line",
available_for_use_date="2023-10-10",
is_existing_asset=1,
opening_number_of_booked_depreciations=9,
opening_accumulated_depreciation=265,
depreciation_start_date="2024-07-31",
total_number_of_depreciations=24,
frequency_of_depreciation=1,
gross_purchase_amount=731,
daily_prorata_based=1,
)
expected_schedules = [
["2024-07-31", 31.0, 296.0],
["2024-08-31", 31.0, 327.0],
["2024-09-30", 30.0, 357.0],
["2024-10-31", 31.0, 388.0],
["2024-11-30", 30.0, 418.0],
["2024-12-31", 31.0, 449.0],
["2025-01-31", 31.0, 480.0],
["2025-02-28", 28.0, 508.0],
["2025-03-31", 31.0, 539.0],
["2025-04-30", 30.0, 569.0],
["2025-05-31", 31.0, 600.0],
["2025-06-30", 30.0, 630.0],
["2025-07-31", 31.0, 661.0],
["2025-08-31", 31.0, 692.0],
["2025-09-30", 30.0, 722.0],
["2025-10-10", 9.0, 731.0],
]
schedules = [
[cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount]
for d in get_depr_schedule(asset.name, "Draft")
]
self.assertEqual(schedules, expected_schedules)
frappe.db.set_single_value("Accounts Settings", "calculate_depr_using_total_days", 0)
def test_schedule_for_slm_for_existing_asset(self):
asset = create_asset(
calculate_depreciation=1,
depreciation_method="Straight Line",
available_for_use_date="2023-10-10",
is_existing_asset=1,
opening_number_of_booked_depreciations=9,
opening_accumulated_depreciation=265.30,
depreciation_start_date="2024-07-31",
total_number_of_depreciations=24,
frequency_of_depreciation=1,
gross_purchase_amount=731,
)
expected_schedules = [
["2024-07-31", 30.46, 295.76],
["2024-08-31", 30.46, 326.22],
["2024-09-30", 30.46, 356.68],
["2024-10-31", 30.46, 387.14],
["2024-11-30", 30.46, 417.6],
["2024-12-31", 30.46, 448.06],
["2025-01-31", 30.46, 478.52],
["2025-02-28", 30.46, 508.98],
["2025-03-31", 30.46, 539.44],
["2025-04-30", 30.46, 569.9],
["2025-05-31", 30.46, 600.36],
["2025-06-30", 30.46, 630.82],
["2025-07-31", 30.46, 661.28],
["2025-08-31", 30.46, 691.74],
["2025-09-30", 30.46, 722.2],
["2025-10-10", 8.8, 731.0],
]
schedules = [
[cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount]
for d in get_depr_schedule(asset.name, "Draft")
]
self.assertEqual(schedules, expected_schedules)
def test_schedule_sl_method_for_existing_asset_with_frequency_of_3_months(self):
asset = create_asset(
calculate_depreciation=1,
depreciation_method="Straight Line",
available_for_use_date="2023-11-01",
is_existing_asset=1,
opening_number_of_booked_depreciations=4,
opening_accumulated_depreciation=223.15,
depreciation_start_date="2024-12-31",
total_number_of_depreciations=12,
frequency_of_depreciation=3,
gross_purchase_amount=731,
)
expected_schedules = [
["2024-12-31", 60.92, 284.07],
["2025-03-31", 60.92, 344.99],
["2025-06-30", 60.92, 405.91],
["2025-09-30", 60.92, 466.83],
["2025-12-31", 60.92, 527.75],
["2026-03-31", 60.92, 588.67],
["2026-06-30", 60.92, 649.59],
["2026-09-30", 60.92, 710.51],
["2026-11-01", 20.49, 731.0],
]
schedules = [
[cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount]
for d in get_depr_schedule(asset.name, "Draft")
]
self.assertEqual(schedules, expected_schedules)
# Enable Checkbox to Calculate depreciation using total days in depreciation period
def test_daily_prorata_based_depr_after_enabling_configuration(self):
frappe.db.set_single_value("Accounts Settings", "calculate_depr_using_total_days", 1)

View File

@@ -3,6 +3,15 @@
frappe.ui.form.on("Asset Maintenance", {
setup: (frm) => {
frm.set_query("asset_name", function () {
return {
filters: {
company: frm.doc.company,
docstatus: 1,
},
};
});
frm.set_query("assign_to", "asset_maintenance_tasks", function (doc) {
return {
query: "erpnext.assets.doctype.asset_maintenance.asset_maintenance.get_team_members",

View File

@@ -29,6 +29,15 @@ frappe.ui.form.on("Asset Repair", {
};
});
frm.set_query("purchase_invoice", function () {
return {
filters: {
company: frm.doc.company,
docstatus: 1,
},
};
});
frm.set_query("warehouse", "stock_items", function () {
return {
filters: {

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