Compare commits

..

589 Commits

Author SHA1 Message Date
marination
7e5cf18066 fix: Wrong bank_ac_no filter + simplify convoluted logic 2025-01-07 13:08:07 +05:30
mergify[bot]
01254da4e0 fix: update customer contact details on pos (backport #45071) (#45106)
fix: update customer contact details on pos (#45071)

* fix: update customer contact details on pos

* refactor: removed console log statement

(cherry picked from commit d79e561248)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-01-06 15:01:23 +05:30
rohitwaghchaure
dadc8266dc Merge pull request #45098 from frappe/mergify/bp/version-15-hotfix/pr-45084
fix: Alternative Items button in Work Order (backport #45084)
2025-01-06 14:48:02 +05:30
ruthra kumar
100b4e9274 Merge pull request #45103 from frappe/mergify/bp/version-15-hotfix/pr-45006
fix: pos search by term items price (backport #45006)
2025-01-06 14:43:56 +05:30
diptanilsaha
59af144e29 fix: load search term price with customer default price list
(cherry picked from commit 2beb485d77)
2025-01-06 08:39:58 +00:00
diptanilsaha
452dffab48 fix: load price list rate for pos search term
(cherry picked from commit 4b6cae156e)
2025-01-06 08:39:57 +00:00
ruthra kumar
eff12cbfbe Merge pull request #45101 from frappe/mergify/bp/version-15-hotfix/pr-45099
fix: show new button in coa if create access (backport #45099)
2025-01-06 13:56:43 +05:30
sokumon
89155f529e fix: show new button in coa if create access
(cherry picked from commit 3125bc8a16)
2025-01-06 08:20:01 +00:00
Mihir Kandoi
642b89782d fix: Alternative Item button dissapearing on Save event
(cherry picked from commit b8838bd9b9)
2025-01-06 06:52:16 +00:00
Mihir Kandoi
3194807a41 fix: Alternative Items button in Work Order
(cherry picked from commit e28382afc1)
2025-01-06 06:52:16 +00:00
ruthra kumar
2333d33362 Merge pull request #45095 from frappe/mergify/bp/version-15-hotfix/pr-44943
fix: Bank Reconciliation Statement Report Company Filter (backport #44943)
2025-01-06 10:51:48 +05:30
creative-paramu
622bfa6633 fix: Bank Reconciliation Statement Report Company Filter
(cherry picked from commit 50c92034ba)
2025-01-06 10:30:24 +05:30
ruthra kumar
e22771c729 Merge pull request #45080 from frappe/mergify/bp/version-15-hotfix/pr-44983
fix: add monthly distributation and write query in qb (backport #44983)
2025-01-06 10:28:18 +05:30
ruthra kumar
5b066f4a59 Merge pull request #45096 from frappe/mergify/bp/version-15-hotfix/pr-44952
fix: Hold_to_On_Hold (backport #44952)
2025-01-06 10:09:35 +05:30
mahsem
9ecafdc680 fix: Hold_to_On_Hold
(cherry picked from commit 92b1f314ef)
2025-01-06 03:15:30 +00:00
ruthra kumar
05763d226a Merge pull request #45093 from frappe/mergify/bp/version-15-hotfix/pr-45051
fix: ignore currency validation while canceling the voucher (backport #45051)
2025-01-06 08:44:46 +05:30
venkat102
0f1c6ff1c9 fix: ignore party account validation while canceling the voucher
(cherry picked from commit 49885f8eae)
2025-01-06 02:55:50 +00:00
venkat102
8874f4a9e4 fix: ignore currency validation while canceling the voucher
(cherry picked from commit 15d488b9aa)
2025-01-06 02:55:49 +00:00
rohitwaghchaure
21a83c508a Merge pull request #45089 from frappe/mergify/bp/version-15-hotfix/pr-45087
fix: invoice against purchase receipt with returned quantity (backport #45087)
2025-01-05 19:02:07 +05:30
rohitwaghchaure
90b8860a40 chore: fix conflicts 2025-01-05 16:24:15 +05:30
Rohit Waghchaure
9daabfca8a fix: invoice against purchase receipt with returned quantity
(cherry picked from commit d5babf4237)

# Conflicts:
#	erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
2025-01-04 15:08:10 +00:00
rohitwaghchaure
10a4b54a67 Merge pull request #45086 from frappe/mergify/bp/version-15-hotfix/pr-45083
fix: consider expired batches in stock reco (backport #45083)
2025-01-04 20:37:16 +05:30
Rohit Waghchaure
c924feb0d0 fix: consider expired batches in stock reco
(cherry picked from commit f51c9f578c)
2025-01-04 13:57:04 +00:00
Joseph Mania
cfa062df86 refactor: phone number field when channel is phone on Payment Request (#44949)
Co-authored-by: maniamartial <martialamania19@gmail.com>
2025-01-04 05:23:41 +05:30
ruthra kumar
2e67a33412 refactor: store result in variable before enumeration
helps to inspect result while debugging

(cherry picked from commit b60bd17d1d)
2025-01-03 23:48:40 +00:00
Sanket322
03b06fc3ff fix: add monthly distributation and write query in qb
(cherry picked from commit 27195c7c96)
2025-01-03 23:48:40 +00:00
mergify[bot]
500deff3e9 feat: validate discount date in payment schedule (backport #44646) (#44727)
Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
2025-01-03 13:19:34 +01:00
ruthra kumar
2c487af2df Merge pull request #45058 from frappe/mergify/bp/version-15-hotfix/pr-45056
chore: partial revert #44989 (backport #45056)
2025-01-02 21:04:22 +05:30
ruthra kumar
4dfc5a664a chore: partial revert #44989
(cherry picked from commit 63d547fb4a)
2025-01-02 15:27:40 +00:00
rohitwaghchaure
d3ea8b8e77 Merge pull request #45054 from frappe/mergify/bp/version-15-hotfix/pr-45053
fix(style): set image width in BOM (backport #45053)
2025-01-02 19:07:29 +05:30
sokumon
6247d5aadb fix(style): set image width in BOM
(cherry picked from commit b634ba7f54)
2025-01-02 13:31:21 +00:00
rohitwaghchaure
85167bf934 Merge pull request #45044 from frappe/mergify/bp/version-15-hotfix/pr-45043
fix: validate components and their qty as per BOM in the stock entry (backport #45043)
2025-01-02 14:19:38 +05:30
Rohit Waghchaure
b5f6926140 fix: validate components and their qty as per BOM in the stock entry
(cherry picked from commit b1de82ddad)
2025-01-02 08:16:03 +00:00
rohitwaghchaure
c615df5ac4 Merge pull request #45042 from frappe/mergify/bp/version-15-hotfix/pr-45039
fix: removed unused code (backport #45039)
2025-01-02 12:36:25 +05:30
rohitwaghchaure
d26d0c6282 Merge pull request #45031 from frappe/mergify/bp/version-15-hotfix/pr-44999
fix: Added patch and fallback code to prevent future issues similar … (backport #44999)
2025-01-02 12:18:18 +05:30
Rohit Waghchaure
d31b0a507f fix: removed unused code
(cherry picked from commit dc5f2d35ac)
2025-01-02 06:47:38 +00:00
rohitwaghchaure
bd12c1475a Merge pull request #45038 from frappe/mergify/bp/version-15-hotfix/pr-45036
fix: Auto BOM cost update issue (backport #45036)
2025-01-02 12:15:50 +05:30
Mihir Kandoi
f9d038ee4a fix: removed unknown patch? 2025-01-02 10:51:11 +05:30
Rohit Waghchaure
00102a15e3 fix: BOM cost update issue
(cherry picked from commit 28ea3ddd51)
2025-01-02 04:55:22 +00:00
Mihir Kandoi
3049027f43 fix: Removed patch as instructed by mentor 2025-01-01 17:13:49 +05:30
Mihir Kandoi
ab87265395 fix: Added patch and fallback code to prevent future issues similiar to helpdesk ticket 28246 2025-01-01 17:12:10 +05:30
Mihir Kandoi
163af91c37 fix: Removed patch as instructed by mentor
(cherry picked from commit d1d01482df)

# Conflicts:
#	erpnext/patches.txt
2025-01-01 11:06:27 +00:00
Mihir Kandoi
b3b808335f fix: Fixed logic in if condition causing tests to fail
(cherry picked from commit 575fb43f9c)
2025-01-01 11:06:27 +00:00
Mihir Kandoi
66544bfa10 fix: Added patch and fallback code to prevent future issues similiar to helpdesk ticket 28246
(cherry picked from commit 65dc3505c4)

# Conflicts:
#	erpnext/patches.txt
2025-01-01 11:06:27 +00:00
mergify[bot]
85ba96e0f3 fix: slow stock transactions (backport #45025) (#45027)
fix: slow stock transactions (#45025)

(cherry picked from commit e92af10f14)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2025-01-01 15:11:01 +05:30
ruthra kumar
1a1476afa4 Merge pull request #45008 from frappe/mergify/bp/version-15-hotfix/pr-44884
fix: update item_tax_rate in backend (backport #44884)
2025-01-01 13:48:50 +05:30
ruthra kumar
e7f4a9bf77 Merge pull request #45023 from frappe/mergify/bp/version-15-hotfix/pr-44989
fix: apply apply_pricing_rule on date change (backport #44989)
2025-01-01 10:19:11 +05:30
DHINESH00
f09acc784f fix: apply apply_pricing_rule date change
(cherry picked from commit 2cbab9b875)
2025-01-01 04:42:48 +00:00
mergify[bot]
0a2cc6bcd7 fix: incorrect quality inspection linked in purchase receipt (backport #44985) (#45020)
* fix: incorrect quality inspection linked in purchase receipt (#44985)

(cherry picked from commit b84c8ff960)

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

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2025-01-01 09:24:48 +05:30
mergify[bot]
52bdf5b170 fix: precision issue (backport #45013) (#45019)
fix: precision issue (#45013)

(cherry picked from commit 7db9bcaeac)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2025-01-01 09:08:16 +05:30
rohitwaghchaure
8d650e56ba fix: duplicate validate for closing stock balance (#45015) 2025-01-01 08:29:02 +05:30
ruthra kumar
e09fb87597 refactor: use existing method parameters 2024-12-31 17:12:34 +05:30
ruthra kumar
a11aee3ab3 Merge pull request #44936 from frappe/mergify/bp/version-15-hotfix/pr-44904
fix: ignore duplicate while creating default templates (backport #44904)
2024-12-31 17:01:03 +05:30
ruthra kumar
92ad2ce554 Merge pull request #44979 from frappe/mergify/bp/version-15-hotfix/pr-44855
fix: in_context_translation_fixes (backport #44855)
2024-12-31 16:59:05 +05:30
ruthra kumar
3533c25969 Merge pull request #45011 from frappe/mergify/bp/version-15-hotfix/pr-44940
fix(Bank Reconciliation Tool): fetch amount in company  currency (backport #44940)
2024-12-31 16:22:00 +05:30
ruthra kumar
aff83051a6 Merge pull request #45010 from frappe/mergify/bp/version-15-hotfix/pr-44903
fix: set paid amount in party currency in bank reco payment entry (backport #44903)
2024-12-31 16:16:16 +05:30
DHINESH00
b135a684a5 fix: fetch amount in company currency
(cherry picked from commit a984aaae36)
2024-12-31 10:28:46 +00:00
ruthra kumar
885dd31c5c chore: resolve conflict 2024-12-31 15:54:06 +05:30
ljain112
6703a457fe fix: set paid amount in party currency in bank reco payment entry
(cherry picked from commit 70b1077286)
2024-12-31 10:23:42 +00:00
ljain112
8885b07114 fix: update item_tax_rate in backend
(cherry picked from commit de54c0b41f)

# Conflicts:
#	erpnext/controllers/taxes_and_totals.py
2024-12-31 10:21:39 +00:00
mergify[bot]
6f7138996a fix: negative stock balance (backport #44990) (#44996)
* fix: negative stock balance (#44990)

(cherry picked from commit 7c4aecf834)

# Conflicts:
#	erpnext/stock/deprecated_serial_batch.py

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-31 13:17:18 +05:30
Khushi Rawat
8d5fe20c7c Merge pull request #44997 from frappe/mergify/bp/version-15-hotfix/pr-44964
fix: copy accounting dimensions to asset and sales invoice (backport #44964)
2024-12-31 13:13:15 +05:30
Khushi Rawat
b8922823a3 fix: remove unused variable 2024-12-31 12:55:41 +05:30
mergify[bot]
20efe7bb80 fix: load customer default price list in pos during item selection (backport #44991) (#44993)
fix: load customer default price list in pos during item selection (#44991)

fix: load customer default price list in pos
(cherry picked from commit d1ae0d784e)

Co-authored-by: Diptanil Saha <diptanil.dev@gmail.com>
2024-12-31 12:52:23 +05:30
mergify[bot]
ea4b6e8dd7 fix(report): Purchase Order Analysis pymysql.err (backport #44957) (#44994)
fix(report): Purchase Order Analysis pymysql.err (#44957)

(cherry picked from commit d6980a9493)

Co-authored-by: Vishnu  VS <Vishnuviswambaran2002@gmail.com>
2024-12-31 12:52:13 +05:30
Khushi Rawat
00ae829d89 fix: resolved conflicts 2024-12-31 12:43:38 +05:30
Khushi Rawat
839ffb3f2a fix: copy accounting dimensions to asset and sales invoice (#44964)
* fix: copy accounting dimensions to asset and sales invoice

* fix: replace sql query with query builder

* refactor: reuse function for accounting dimensions

* fix: loop handling

* fix: use explicit param

(cherry picked from commit 079ec864de)

# Conflicts:
#	erpnext/controllers/buying_controller.py
2024-12-31 07:07:16 +00:00
mergify[bot]
d6903fbc8d fix: Validate party on non receivable / payable account (backport #44883) (#44973)
* fix: validate party on non receivable / payable account

(cherry picked from commit c6a2d86ba6)

* test: add unit test to validate on non receivable / payable account

(cherry picked from commit a10a15b2c3)

* fix: Set account type payable for advance account

(cherry picked from commit 8abbece7c4)

---------

Co-authored-by: Karuppasamy923 <karuppasamylivak@gmail.com>
2024-12-31 12:09:33 +05:30
mergify[bot]
9853bd9ba1 fix: incorrect filter for BOM (backport #44954) (#44956)
fix: incorrect filter for BOM (#44954)

(cherry picked from commit 9fdeb5f826)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-30 23:38:49 +05:30
mergify[bot]
c33e07550c fix: ignore validate while making WO from MR (backport #44939) (#44942)
fix: ignore validate while making WO from MR (#44939)

(cherry picked from commit 9661c1d081)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-30 23:38:14 +05:30
mergify[bot]
772b7b95ac fix: ignore inventory dimension for SABB and Pick List (backport #44933) (#44941)
fix: ignore inventory dimension for SABB and Pick List (#44933)

(cherry picked from commit 303c52f134)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-30 23:37:52 +05:30
ruthra kumar
2e9c507dfa chore: resolve conflicts 2024-12-30 16:18:18 +05:30
ruthra kumar
e3dc5d0de4 Merge pull request #44897 from frappe/mergify/bp/version-15-hotfix/pr-44787
fix: refactor query in`get_total_allocated_amount` in bank_transaction (backport #44787)
2024-12-30 16:16:15 +05:30
mahsem
2efc701e4e fix: whitespace
(cherry picked from commit 1f4e1811de)
2024-12-30 10:27:17 +00:00
mahsem
1353a14a6b fix: in_contex_translation_fixes
(cherry picked from commit a87e7fde03)

# Conflicts:
#	erpnext/accounts/utils.py
#	erpnext/templates/pages/order.html
2024-12-30 10:27:17 +00:00
ruthra kumar
8b4f5261b4 Merge pull request #44978 from frappe/mergify/bp/version-15-hotfix/pr-44975
fix: add company filter to project (backport #44975)
2024-12-30 15:55:00 +05:30
venkat102
74220430e5 fix: include company in filter condition
(cherry picked from commit b92f8bc514)
2024-12-30 09:59:09 +00:00
venkat102
d550b433c1 fix: add company filter to project
(cherry picked from commit 1a7b09e576)
2024-12-30 09:59:09 +00:00
ruthra kumar
8e55d5cc39 Merge pull request #44974 from frappe/mergify/bp/version-15-hotfix/pr-44552
Fix: Added Order Number and Order Date fields to the Blanket Order form. (backport #44552)
2024-12-30 15:27:50 +05:30
ruthra kumar
4a74ee7b6e Merge pull request #44977 from frappe/mergify/bp/version-15-hotfix/pr-44761
fix: apply discount on qty change (backport #44761)
2024-12-30 15:04:22 +05:30
DHINESH00
c19725ca74 fix: apply discount on qty change
(cherry picked from commit 352b82bc0b)
2024-12-30 09:27:31 +00:00
ruthra kumar
7b90742409 chore: resolve conflict 2024-12-30 14:50:23 +05:30
Himanshu Shivhare
583182180a refactor: Order Number and Order Date fields to Blanket Order
(cherry picked from commit 5a284df51d)

# Conflicts:
#	erpnext/manufacturing/doctype/blanket_order/blanket_order.json
2024-12-30 08:32:49 +00:00
mergify[bot]
28442f3414 fix: limit discount value to 100 in pos cart (backport #44916) (#44932)
fix: limit discount value to 100 in pos cart (#44916)

* fix: limit discount value to 100 in pos cart

* fix: error message on invalid discount

(cherry picked from commit ac26622d6e)

Co-authored-by: Diptanil Saha <50792171+diptanilsaha@users.noreply.github.com>
2024-12-30 14:00:08 +05:30
mergify[bot]
cc827c8077 fix: fetch advance payment entries on pos invoice (backport #44856) (#44931)
fix: fetch advance payment entries on pos invoice

(cherry picked from commit a7078e5702)

Co-authored-by: Diptanil Saha <diptanilsaha@Diptanils-MacBook-Air.local>
2024-12-30 13:59:42 +05:30
mergify[bot]
40f46b76fa fix (pos closing entry): validation for 100 pc discount on pos invoice (backport #44899) (#44930)
fix (pos closing entry): validation for 100 pc discount on pos invoice (#44899)

(cherry picked from commit cfcc24a341)

Co-authored-by: Diptanil Saha <50792171+diptanilsaha@users.noreply.github.com>
2024-12-30 13:58:58 +05:30
mergify[bot]
7dd2b0c189 fix: pos payment using non-default mode of payment (backport #44920) (#44971)
fix: pos payment using non-default mode of payment (#44920)

* fix: pos payment using non-default mode of payment (#41108)

* fix: included css syntax

* refactor: created a function to sanitize the class name

* refactor: reusing method to sanitize class name

* refactor: function rename

(cherry picked from commit 98cbb7e900)

Co-authored-by: Diptanil Saha <diptanil.dev@gmail.com>
2024-12-30 13:56:55 +05:30
ruthra kumar
3a361eac4e Merge pull request #44966 from frappe/mergify/bp/version-15-hotfix/pr-44921
fix: get item tax template based on posting date (backport #44921)
2024-12-30 13:09:15 +05:30
ruthra kumar
61ee292957 Merge pull request #44955 from frappe/mergify/bp/version-15-hotfix/pr-44636
fix: SQL syntax error in Purchase Receipt query for empty filters (backport #44636)
2024-12-30 12:38:02 +05:30
ruthra kumar
c2d9ac11f0 Merge pull request #44960 from frappe/mergify/bp/version-15-hotfix/pr-44958
refactor(test): make manufacturing test idempotent (backport #44958)
2024-12-30 12:37:37 +05:30
ljain112
2feeebb5fb fix: get item tax template based on posting date
(cherry picked from commit 976e35d547)
2024-12-30 12:35:07 +05:30
ruthra kumar
f6a9051291 Merge pull request #44963 from frappe/mergify/bp/version-15-hotfix/pr-44906
fix: set/update billing address on change of company (backport #44906)
2024-12-30 12:27:59 +05:30
Sanket322
e582ff862e fix: use meta to check field instead of doctype
(cherry picked from commit 187c74ae09)
2024-12-30 06:52:56 +00:00
Sanket322
98631eb266 fix: move code from purchase invoice to buying controller
(cherry picked from commit cb197fd01f)
2024-12-30 06:52:55 +00:00
Sanket322
cfa432dbca fix: set/update billing address on change of company
(cherry picked from commit 0adfebee85)
2024-12-30 06:52:55 +00:00
ruthra kumar
a11f7d5a82 chore: fix linter 2024-12-30 12:18:09 +05:30
ruthra kumar
f83112520d refactor(test): make manufacturing test idempotent
(cherry picked from commit f3be246df3)
2024-12-30 12:02:01 +05:30
Navin R C
2f279a6eb4 fix: SQL syntax error in Purchase Receipt query for empty filters (#44636)
fix(po-analysis): handle SQL error due to empty data in IN() clause

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit 48b49cdea4)
2024-12-30 04:11:08 +00:00
Sanket322
6c206c1cb3 fix: ignore duplicate while creating default templates
(cherry picked from commit 9368485594)
2024-12-27 09:17:44 +00:00
ruthra kumar
6bb2b76040 Merge pull request #44935 from frappe/mergify/bp/version-15-hotfix/pr-44892
fix: clear payment schedule in purchase invoice for is_paid (backport #44892)
2024-12-27 13:52:26 +05:30
ruthra kumar
508435ac9f refactor: early return is always better
validate_advance_entries() has a heavy IO bound operation. Early
return on unwanted cases is always better.

(cherry picked from commit 0589fa7f3e)
2024-12-27 07:54:44 +00:00
Sanket322
6cc70605fa fix: clear payment schedule in purchase invoice for is_paid
(cherry picked from commit e1fc239f3d)
2024-12-27 07:54:44 +00:00
mergify[bot]
488d8080c8 fix: strings for translation (backport #44816) (#44927)
* fix: strings for translation

(cherry picked from commit 3be633f6f1)

# Conflicts:
#	erpnext/accounts/utils.py

* fix: resolved conflict

---------

Co-authored-by: mahsem <137205921+mahsem@users.noreply.github.com>
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2024-12-27 11:33:09 +05:30
mergify[bot]
5cc9e10923 fix: Show order tax amount in customer currency on the portal (backport #44915) (#44923)
fix: Show order tax amount in customer currency on the portal (#44915)

(cherry picked from commit b998933ef0)

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2024-12-27 11:24:57 +05:30
ruthra kumar
b45b77df93 Merge pull request #44926 from frappe/mergify/bp/version-15-hotfix/pr-44815
fix: relabel rate to tax rate (backport #44815)
2024-12-27 10:55:54 +05:30
mahsem
991a3366a8 fix: relabel rate to tax rate
(cherry picked from commit 1eb8b0ceef)
2024-12-27 05:25:16 +00:00
mergify[bot]
042d12b2c1 fix: material request status (backport #44917) (#44918)
* fix: material request status (#44917)

(cherry picked from commit 1319ce4bc1)

* chore: fix test case

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-26 22:58:29 +05:30
mergify[bot]
c241262266 fix: not able to make purchase receipt from SCR (backport #44919) (#44925)
* fix: not able to make purchase receipt from SCR (#44919)

(cherry picked from commit ab1cca0c40)

* chore: fix test case

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-26 22:58:11 +05:30
mergify[bot]
9060e4ce57 fix: allow zero valuation rate (backport #44902) (#44910)
fix: allow zero valuation rate (#44902)

(cherry picked from commit 614a8f106d)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-26 11:03:13 +05:30
vishakhdesai
61367ee1ed fix: failing tests fixed
(cherry picked from commit 2ce07865d3)
2024-12-24 12:23:58 +00:00
vishakhdesai
944dc966bc fix: refactor query in get_total_allocated_amount in bank_transaction
(cherry picked from commit 6b847cdb62)
2024-12-24 12:23:58 +00:00
ruthra kumar
9c6832a622 Merge pull request #44894 from frappe/mergify/bp/version-15-hotfix/pr-44878
fix: show profit and loss after period closing (backport #44878)
2024-12-24 17:52:53 +05:30
venkat102
771632a5e2 fix: show profit and loss after period closing
(cherry picked from commit dc5cd93bf0)
2024-12-24 11:33:39 +00:00
ruthra kumar
7a81c0f10f Merge pull request #44891 from frappe/mergify/bp/version-15-hotfix/pr-44889
refactor: use db_set instead of set_value to trigger notification (backport #44889)
2024-12-24 17:02:58 +05:30
venkat102
69ed2a9dfe refactor: use db_set instead of set_value to trigger notification
(cherry picked from commit f8b923edfe)
2024-12-24 11:12:44 +00:00
mergify[bot]
57e6ed4645 fix: set project in GL from the SLE (backport #44879) (#44885)
fix: set project in GL from the SLE (#44879)

(cherry picked from commit 021d077808)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-24 15:12:32 +05:30
ruthra kumar
b48f46ed5a Merge pull request #44882 from frappe/mergify/bp/version-15-hotfix/pr-44794
fix: correct tds rate with lower deduction certificate (backport #44794)
2024-12-24 14:37:35 +05:30
ruthra kumar
72b720477c Merge pull request #44872 from frappe/mergify/bp/version-15-hotfix/pr-44870
fix: posting_time issue (backport #44870)
2024-12-24 13:56:10 +05:30
ljain112
5ca60f3e0a fix: correct tds rate with lower deduction certificate
(cherry picked from commit cb9c12d495)
2024-12-24 08:16:03 +00:00
ruthra kumar
ddc58f0146 Merge pull request #44877 from Abdeali099/backport-uom-handle
fix: add `Stock UOM` when adding new item in POS list (#44780)
2024-12-24 11:18:47 +05:30
Abdeali Chharchhodawala
96cc9e29a1 fix: add Stock UOM when adding new item in POS list (#44780) 2024-12-24 11:08:54 +05:30
mergify[bot]
ca7c229e86 fix: Paid + Write Off Amount issue in Sales Invoice (backport #44763) (#44874)
fix: Paid + Write Off Amount issue in Sales Invoice

(cherry picked from commit 1fd7ba7c88)

Co-authored-by: vishakhdesai <vishakhdesai@gmail.com>
2024-12-24 10:48:15 +05:30
rohitwaghchaure
90aadcdcbc chore: fix conflicts 2024-12-24 10:16:53 +05:30
rohitwaghchaure
7a5c30fe9b fix: posting_time issue (#44870)
(cherry picked from commit 079b86044e)

# Conflicts:
#	erpnext/stock/deprecated_serial_batch.py
2024-12-24 03:37:25 +00:00
Khushi Rawat
f0671d45de Merge pull request #44871 from frappe/mergify/bp/version-15-hotfix/pr-44854
fix: asset fields precision check (backport #44854)
2024-12-24 00:21:26 +05:30
Khushi Rawat
ddfead2cde fix: test case correction
(cherry picked from commit 2f7e6230a6)
2024-12-23 18:31:28 +00:00
Khushi Rawat
516a325a31 fix: asset field precision check
(cherry picked from commit 92b8768ae2)
2024-12-23 18:31:28 +00:00
mergify[bot]
d6001e5ef9 fix: stock entry not fetching expired batches (backport #44863) (#44868)
fix: stock entry not fetching expired batches (#44863)

(cherry picked from commit c9b143b509)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-23 22:31:16 +05:30
mergify[bot]
f32cf84413 fix: Warehouse wise Stock Value chart roles (backport #44865) (#44867)
fix: Warehouse wise Stock Value chart roles (#44865)

(cherry picked from commit 7d41805d0e)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-23 22:30:58 +05:30
mergify[bot]
8092d58d9c fix: do not validate qc for scrap item (backport #44844) (#44853)
fix: do not validate qc for scrap item (#44844)

(cherry picked from commit a2c2b8b5ad)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-23 19:15:46 +05:30
mergify[bot]
3f3df7ef2a perf: slow query related to stock ledger entry (backport #44861) (#44862)
perf: slow query related to stock ledger entry (#44861)

(cherry picked from commit 54d7b742ab)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-23 19:15:32 +05:30
mergify[bot]
0969877cd7 fix: incoming rate should be zero for rejected items (backport #44857) (#44859)
fix: incoming rate should be zero for rejected items (#44857)

(cherry picked from commit a515a399cf)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-23 18:11:53 +05:30
ruthra kumar
9543a4c66f Merge pull request #44852 from frappe/mergify/bp/version-15-hotfix/pr-44716
fix: avg. buying amount for product bundle item with serial and batch no in gross profit report (backport #44716)
2024-12-23 15:35:43 +05:30
ruthra kumar
3eb56cbbfb Merge pull request #44841 from frappe/mergify/bp/version-15-hotfix/pr-44808
feat: Added difference_posting_date field in Sales Invoice Advance and Purchase Invoice Advance (backport #44808)
2024-12-23 15:18:16 +05:30
ruthra kumar
dc1ed406a1 Merge pull request #44849 from frappe/mergify/bp/version-15-hotfix/pr-44797
fix(ux): purchase invoice link in error message (backport #44797)
2024-12-23 15:17:47 +05:30
ljain112
2edb6f3224 fix: avg. buying amount for product bundle item with serial and batch no in gross profit report
(cherry picked from commit cc3f4bb0b0)
2024-12-23 09:34:15 +00:00
ruthra kumar
4e23e3191d Merge pull request #44847 from frappe/mergify/bp/version-15-hotfix/pr-44738
fix: fetch tax withholding category from the voucher (backport #44738)
2024-12-23 15:03:02 +05:30
ruthra kumar
55470fefdb Merge pull request #44843 from frappe/mergify/bp/version-15-hotfix/pr-44813
fix: update correct cost center in Accounts Receivable Report (backport #44813)
2024-12-23 14:55:45 +05:30
ruthra kumar
33fc987d95 refactor(test): remove hardcoded names 2024-12-23 14:52:02 +05:30
Nijith anil
01c1ed98ac fix(ux): purchase invoice link in error message (#44797)
* fix(ux): purchase invoice link in error message

* chore: fix linter

---------

Co-authored-by: ruthra kumar <ruthra@erpnext.com>
(cherry picked from commit 6f00a87a9c)
2024-12-23 09:20:17 +00:00
venkat102
8f8dd1c088 fix: fetch tax withholding category from the voucher
(cherry picked from commit 09e64594db)
2024-12-23 09:07:13 +00:00
venkat102
f005bef218 chore: use get function
(cherry picked from commit 1663c7983e)
2024-12-23 09:07:13 +00:00
vishakhdesai
19a8ea217e fix: do not set cost_center update_voucher_balance as it is set in init_voucher_balance
(cherry picked from commit 3b36ce560c)
2024-12-23 08:51:37 +00:00
vishakhdesai
4c5540aef9 fix: update correct cost center in Accounts Receivable Report
(cherry picked from commit 09776e9a5a)
2024-12-23 08:51:36 +00:00
ruthra kumar
cf4068d1a3 chore: resolve conflicts 2024-12-23 14:11:05 +05:30
rs-rethik
3ab4acfafa fix: update query
(cherry picked from commit 854e37c05c)
2024-12-23 08:39:55 +00:00
rs-rethik
13123a0412 refactor: convert sql query to query builder
(cherry picked from commit 2d58e845e6)
2024-12-23 08:39:54 +00:00
rs-rethik
4884849f23 test: add unit test to validate journal entry posting date
(cherry picked from commit c14a2d73bf)
2024-12-23 08:39:54 +00:00
rs-rethik
7498cdf644 feat: use difference_posting_date for journal entry posting_date
(cherry picked from commit ff1d040a6e)
2024-12-23 08:39:54 +00:00
rs-rethik
bec1f972b3 feat: add difference_posting_date field
(cherry picked from commit 225e56cbca)

# Conflicts:
#	erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json
#	erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json
2024-12-23 08:39:54 +00:00
mergify[bot]
497029f958 fix: incorrect Material Transferred for Manufacturing qty (backport #44823) (#44832)
* fix: incorrect Material Transferred for Manufacturing qty (#44823)

(cherry picked from commit fe0036e707)

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

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-23 13:38:21 +05:30
ruthra kumar
b0a10c6b2a Merge pull request #44840 from frappe/mergify/bp/version-15-hotfix/pr-44786
fix: correct args for get_advance_payment_entries_for_regional (backport #44786)
2024-12-23 13:23:27 +05:30
ljain112
875797e655 fix: correct args for get_advance_payment_entries_for_regional
(cherry picked from commit df13a4cc2f)
2024-12-23 07:28:34 +00:00
ruthra kumar
1a9dfec115 Merge pull request #44838 from frappe/mergify/bp/version-15-hotfix/pr-44751
fix: buying rate for service item in gross profit report (backport #44751)
2024-12-23 12:06:23 +05:30
ruthra kumar
59841408ac Merge pull request #44836 from frappe/mergify/bp/version-15-hotfix/pr-44681
fix: Stock Entry uses incorrect company when generated from Pick List (backport #44679) (backport #44681)
2024-12-23 11:56:32 +05:30
ljain112
a55aaea5a1 fix: buying rate for service item in gross profit report
(cherry picked from commit 8d6e79a16f)
2024-12-23 06:16:24 +00:00
ruthra kumar
041d94f3cf Merge pull request #44834 from frappe/mergify/bp/version-15-hotfix/pr-44644
fix: permissions for marking Quotation as lost (backport #44644)
2024-12-23 11:31:47 +05:30
Nicolas Pereira
58e846709e fix: Stock Entry uses incorrect company when generated from Pick List (#44679)
(cherry picked from commit 00898be8e4)
(cherry picked from commit cd693b5fa4)
2024-12-23 05:59:10 +00:00
ruthra kumar
7f5c19a81e Merge pull request #44830 from frappe/mergify/bp/version-15-hotfix/pr-44826
fix: Remove typo from `Bank Account` on trash (backport #44826)
2024-12-23 11:26:19 +05:30
ruthra kumar
3d4a4e661c chore: resolve conflicts 2024-12-23 11:14:33 +05:30
barredterra
e6390bfba1 fix: permissions for marking Quotation as lost
(cherry picked from commit 4d5241486f)

# Conflicts:
#	erpnext/crm/doctype/competitor/competitor.json
#	erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json
2024-12-23 05:41:57 +00:00
Abdeali Chharchhoda
13a3c816d7 fix: Remove typo
(cherry picked from commit ba28f6bf73)
2024-12-23 04:52:25 +00:00
ruthra kumar
4869847bc7 Merge pull request #44828 from frappe/mergify/bp/version-15-hotfix/pr-44825
fix: Ledger repost support for extending app doctypes (backport #44825)
2024-12-23 10:19:08 +05:30
Deepesh Garg
b5596d98e3 fix: Add hooks for repost allowed doctypes
(cherry picked from commit 919abd2c03)
2024-12-23 04:19:48 +00:00
Deepesh Garg
d137f780bd fix: Ledger repost support for extending app doctypes
(cherry picked from commit ed231abb54)
2024-12-23 04:19:48 +00:00
mergify[bot]
16b013fab2 fix: Duplicate entry ' EF1DE8B2E1B6' for key 'PRIMARY' (backport #44809) (#44814)
fix: Duplicate entry ' EF1DE8B2E1B6' for key 'PRIMARY' (#44809)

(cherry picked from commit 56f561cdaa)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-21 10:26:25 +05:30
mergify[bot]
ad57e33cd7 fix: slow posting datetime update (backport #44799) (#44805)
fix: slow posting datetime update (#44799)

(cherry picked from commit a7b5e2565b)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-20 19:38:52 +05:30
Smit Vora
58c0e24f2d Merge pull request #44735 from frappe/mergify/bp/version-15-hotfix/pr-44660
fix: better indicator base amount for Tax Witholding in Journal Entry (backport #44660)
2024-12-20 16:28:43 +05:30
ruthra kumar
162380d9da Merge pull request #44810 from frappe/mergify/bp/version-15-hotfix/pr-44703
fix: Swedish tax templates (backport #44703)
2024-12-20 14:32:41 +05:30
mahsem
cc1834b0cc fix: Swedish tax templates
(cherry picked from commit 73112fa3c9)
2024-12-20 08:42:38 +00:00
ruthra kumar
9449055b1e Merge pull request #44807 from frappe/mergify/bp/version-15-hotfix/pr-44665
fix: add Swedish_2024_COA (backport #44665)
2024-12-20 12:24:44 +05:30
mergify[bot]
8f811728d9 feat(subcontracting): Added provision to create multiple Subcontracting Orders against a single Purchase Order (backport #44711) (#44782)
* feat(subcontracting): Added provision to create multiple Subcontracting Orders against a single Purchase Order (#44711)

* feat(subcontracting): Added provision to create multiple Subcontracting Orders from a single Subcontracted Purchase Order

* refactor(new_sc_flow_2): Fixed error thrown by semgrep

(cherry picked from commit 3eba6bf3dd)

# Conflicts:
#	erpnext/buying/doctype/purchase_order/purchase_order.js
#	erpnext/buying/doctype/purchase_order/test_purchase_order.py
#	erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
#	erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json
#	erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json

* feat(subcontracting): Added provision to create multiple Subcontracting Orders against a single Purchase Order (#44711)

* feat(subcontracting): Added provision to create multiple Subcontracting Orders from a single Subcontracted Purchase Order

* refactor(new_sc_flow_2): Fixed error thrown by semgrep

* fix: Resolved errors and removed code from develop branch merged by mistake

---------

Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2024-12-20 12:18:01 +05:30
mahsem
98cc79d942 feat: swedish COA
(cherry picked from commit 8a5f7ec4d7)
2024-12-20 06:27:14 +00:00
Smit Vora
db9a319104 fix: typerror on TDS payable monthly report (backport #37707) 2024-12-20 11:02:33 +05:30
mergify[bot]
cdeec8d24c fix: closing stock balance permissions (backport #44791) (#44793)
* fix: closing stock balance permissions (#44791)

(cherry picked from commit 3662a6a41d)

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

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-20 09:35:51 +05:30
mergify[bot]
b706a8274f perf: SABB (backport #44764) (#44789)
perf: SABB (#44764)

(cherry picked from commit 90baa38f64)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-19 13:31:28 +05:30
mergify[bot]
20324224d3 fix: POS Closing entry issue (backport #44772) (#44781)
fix: POS Closing entry issue (#44772)

(cherry picked from commit 779dd2d798)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-18 20:38:56 +05:30
ruthra kumar
418ef81dbc Merge pull request #44778 from frappe/mergify/bp/version-15-hotfix/pr-44776
fix: added docs.frappe.io in documentation_url (backport #44776)
2024-12-18 17:53:31 +05:30
Nabin Hait
0fd7792f49 fix: added docs.frappe.io in documentation_url (#44776)
(cherry picked from commit febdf4c61e)
2024-12-18 11:59:50 +00:00
ruthra kumar
7350aa299e Merge pull request #44770 from frappe/mergify/bp/version-15-hotfix/pr-44765
fix: 'str' object has no attribute 'get_sql' (backport #44765)
2024-12-18 14:34:09 +05:30
ljain112
8b810f5fb8 fix: 'str' object has no attribute 'get_sql'
(cherry picked from commit 9a43acb65c)
2024-12-18 08:44:27 +00:00
ruthra kumar
3ed7f761ba Merge pull request #44760 from frappe/mergify/bp/version-15-hotfix/pr-44758
fix: use utility method to generate url (backport #44758)
2024-12-18 11:17:09 +05:30
ruthra kumar
75aee42635 fix: use utility method to generate url
(cherry picked from commit b970eb8b15)
2024-12-18 05:33:31 +00:00
rohitwaghchaure
3ac801c884 fix: duplicate Use Multi-Level BOM checkbox (#44757) 2024-12-18 10:41:24 +05:30
ruthra kumar
2c0468e784 Merge pull request #44753 from frappe/mergify/bp/version-15-hotfix/pr-44695
fix: User permissions in financial statements (backport #44695)
2024-12-17 21:19:11 +05:30
ruthra kumar
cb03fed5d8 Merge pull request #44755 from frappe/mergify/bp/version-15-hotfix/pr-44708
fix: update discount when pricing rule is changed (backport #44708)
2024-12-17 21:10:27 +05:30
venkat102
f1a5000872 fix: update discount when pricing rule is changed
(cherry picked from commit 8338d1d5b4)
2024-12-17 15:13:22 +00:00
ljain112
40a8ed8571 fix: using query.walk() for escaping
(cherry picked from commit 5ea131c763)
2024-12-17 15:09:25 +00:00
ljain112
83aeb2e475 fix: User permissions in financial statements
(cherry picked from commit a626372d66)
2024-12-17 15:09:25 +00:00
ruthra kumar
2b27892fc2 Merge pull request #44750 from ruthra-kumar/backport_v15_pr_44581
fix: allow all dispatch address for drop ship invoice (backport #44581)
2024-12-17 17:52:14 +05:30
ruthra kumar
db3a87c837 fix: allow all dispatch address for drop ship invoice 2024-12-17 17:43:31 +05:30
ruthra kumar
09b28e89a9 Merge pull request #44748 from frappe/mergify/bp/version-15-hotfix/pr-44685
fix: set company bank account if default account not set in mode of p… (backport #44685)
2024-12-17 17:29:37 +05:30
ruthra kumar
96691bfdce Merge pull request #44731 from frappe/mergify/bp/version-15-hotfix/pr-44650
feat: Multiselect cc in process statement of accounts (backport #44650)
2024-12-17 17:28:51 +05:30
venkat102
a8f7393706 fix: set company bank account if default account not set in mode of payment
(cherry picked from commit 91c7e3d5f3)
2024-12-17 11:50:10 +00:00
mergify[bot]
8ba7424996 fix: purchase return entry issue (backport #44721) (#44737)
fix: purchase return entry issue (#44721)

(cherry picked from commit 1f5d7072e7)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-17 14:48:18 +05:30
mergify[bot]
8aec13115c fix: pos invoice return reference missing (backport #44720) (#44729)
fix: pos invoice return reference missing (#44720)

(cherry picked from commit 852596dbe6)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-17 12:29:42 +05:30
Khushi Rawat
6176411bcf Merge pull request #44732 from khushi8112/bp-version-15-hotfix-pr-44690
fix: handle zero salvage value case backport-pr-44690
2024-12-17 12:27:53 +05:30
Smit Vora
218e777423 fix: better indicator base amount for Tax Witholding in Journal Entry
(cherry picked from commit 56a0a0db18)
2024-12-17 06:20:31 +00:00
Khushi Rawat
96dac012b6 Merge pull request #44710 from khushi8112/backport-pr-44647
fix: switched asset terminology from cost to value backport
2024-12-17 11:44:30 +05:30
Khushi Rawat
ed42ed04d2 fix: make rate of depreciation mandatory 2024-12-17 11:39:36 +05:30
ruthra kumar
f9a904c584 chore: resolve conflict 2024-12-17 11:38:45 +05:30
Khushi Rawat
632a45d82e fix: handle zero salvage value case 2024-12-17 11:37:05 +05:30
rs-rethik
5b4eb5ea9a chore: remove irrelevant import
(cherry picked from commit 5401cf9647)
2024-12-17 06:06:30 +00:00
rs-rethik
082fd27938 refactor: convert sql query to query builder
(cherry picked from commit 494ac04f8e)
2024-12-17 06:06:30 +00:00
rs-rethik
df9bc33f34 fix: update cc_to multiselect in process statement of accounts
(cherry picked from commit 2a6be127ef)

# Conflicts:
#	erpnext/patches.txt
2024-12-17 06:06:30 +00:00
rs-rethik
7665eac277 feat: change type link to multiselect
(cherry picked from commit 4de180feee)
2024-12-17 06:06:29 +00:00
Khushi Rawat
02c5f7e9d1 chore: Merge branch 'version-15-hotfix' 2024-12-17 11:20:39 +05:30
mergify[bot]
8940747161 fix: delink SABB from cancelled SLEs (backport #44691) (#44719)
fix: delink SABB from cancelled SLEs (#44691)

(cherry picked from commit 5f539619bc)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-17 11:04:54 +05:30
mergify[bot]
158a4803ca fix: unsupported operand type (backport #44722) (#44723)
fix: unsupported operand type (#44722)

(cherry picked from commit 95da0913f6)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-17 11:04:40 +05:30
ruthra kumar
06c3eaecc5 Merge pull request #44724 from frappe/mergify/bp/version-15-hotfix/pr-44713
fix: broken CI (backport #44713)
2024-12-17 10:02:45 +05:30
ruthra kumar
78d7d7148f fix: broken CI
- always install wkhtmltopdf
- remove specific version on mariadb-client

(cherry picked from commit eb1e36ca22)
2024-12-17 04:12:58 +00:00
Khushi Rawat
47c7356b38 fix: switched asset terminology from cost to value 2024-12-16 11:58:38 +05:30
ruthra kumar
440e0aa521 Merge pull request #44698 from ruthra-kumar/backport_v15_pr_44676
fix: remove invalid filter in Account Receivable report (backport #44676)
2024-12-13 17:45:19 +05:30
ljain112
fdfbb57779 fix: remove invalid filter in Account Receivable report 2024-12-13 17:27:14 +05:30
ruthra kumar
1c5178f202 Merge pull request #44686 from ruthra-kumar/backport_v15_pr_42989
fix: Wrong allocated_amount for sales_team in gross_profit report (backport 42989)
2024-12-13 12:39:38 +05:30
Diógenes Souza
328b9e7d9e fix: Wrong allocated_amount for sales_team in gross_profit report (#42989)
* fix: Wrong allocated_amount for sales_team in gross_profit report

* style: Removes whitespaces

---------

Co-authored-by: ruthra kumar <ruthra@erpnext.com>
2024-12-13 11:58:37 +05:30
ruthra kumar
eebb1a24bc Merge pull request #44684 from frappe/backport_v15_pr_44621
fix: add doc.status to translation from POS (backport #44621)
2024-12-13 10:33:49 +05:30
mahsem
0ba6e60608 fix: add doc.status to translation from POS 2024-12-13 10:31:47 +05:30
mergify[bot]
33273faccb fix: validate returned serial nos and batches (backport #44669) (#44674)
fix: validate returned serial nos and batches (#44669)

(cherry picked from commit 4385349e36)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-12 15:44:28 +05:30
mergify[bot]
bd9c84d3b7 fix: make projected qty editable after submit (backport #44670) (#44671)
* fix: make projected qty editable after submit (#44670)

(cherry picked from commit 9ef9ff3de8)

# Conflicts:
#	erpnext/selling/doctype/quotation_item/quotation_item.json

* chore: fix conflicts

---------

Co-authored-by: Venkatesh <47534423+venkat102@users.noreply.github.com>
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-12 15:24:32 +05:30
mergify[bot]
2466e4c2fd fix: valuation rate for batch in stock reconciliation (backport #44657) (#44664)
fix: valuation rate for batch in stock reconciliation  (#44657)

fix: valuation rate for batch in stock reco
(cherry picked from commit 15c7d26378)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-11 21:33:36 +05:30
rohitwaghchaure
44f798c3e1 Merge branch 'version-15' into version-15-hotfix 2024-12-11 16:34:48 +05:30
ruthra kumar
20186fb8fa Merge pull request #44656 from aerele/free-item-row
fix: update free item qty while adding same item in seperate row
2024-12-11 16:26:16 +05:30
ruthra kumar
282f133500 Merge pull request #44655 from ruthra-kumar/manual_backport_pr_44533
refactor: consider against_voucher_no when voucher_no is filtered (backport 44533)
2024-12-11 16:03:37 +05:30
venkat102
f88dc263d5 fix: update free item qty while adding same item in seperate row 2024-12-11 15:55:22 +05:30
ruthra kumar
7e0ff851ab refactor: consider against voucher when not filtered on voucher_no 2024-12-11 15:40:56 +05:30
Khushi Rawat
f3cf28a4f4 Merge pull request #44642 from khushi8112/backport-v15-pr-44631
fix: precision check for salvage value (backport #44631)
2024-12-10 16:23:13 +05:30
Khushi Rawat
ef5a5643dc fix: precision check for salvage value 2024-12-10 15:17:04 +05:30
Deepesh Garg
925eb4449e Merge pull request #44637 from frappe/mergify/bp/version-15/pr-44554
chore: Ignore stock validation for non-stock invoices (#44549)
2024-12-10 14:47:29 +05:30
mergify[bot]
815c6b4234 chore: Ignore stock validation for non stock invoices (backport #44549) (#44554)
chore: Ignore stock validation for non stock invoices (#44549)

* chore: Ignore stock validation for non stock invoices

* chore: Ignore stock validation for non stock invoices

(cherry picked from commit 1ac292285e)

Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
(cherry picked from commit 06ac21dd85)
2024-12-10 09:16:37 +00:00
mergify[bot]
5cd39941ee fix: 'Use Multi-Level BOM' checkbox default value (backport #44618) (#44620)
fix: 'Use Multi-Level BOM' checkbox default value (#44618)

(cherry picked from commit f5c038cd1b)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-10 10:57:20 +05:30
ruthra kumar
eae5996c4c Merge pull request #44622 from ruthra-kumar/backport_v15_pr_44545
fix: only show advance payment entries where "book_advance_payments_in_separate_party_account" is true (backport #44545)
2024-12-10 07:28:53 +05:30
ljain112
98bd5f20c4 fix: restrict advance payment entries with flag
where "book_advance_payments_in_separate_party_account" is true
2024-12-09 20:57:24 +05:30
mergify[bot]
bdb60a51c3 fix: do not allow to inward same serial nos multiple times (backport #44617) (#44619)
* fix: do not allow to inward same serial nos multiple times (#44617)

(cherry picked from commit 616bb383c5)

# Conflicts:
#	erpnext/patches.txt

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-09 20:30:45 +05:30
mergify[bot]
04b07a9e1c fix: not able to make sales return entry (backport #44605) (#44613)
fix: not able to make sales return entry (#44605)

(cherry picked from commit 314c7b8d2a)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-09 19:11:49 +05:30
mergify[bot]
243bf542c4 fix: description overwrite on qty change (backport #44606) (#44609)
fix: description overwrite on qty change (#44606)

(cherry picked from commit 9ad79625e0)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-09 14:56:10 +05:30
ruthra kumar
0bb7c889ae Merge pull request #44612 from frappe/mergify/bp/version-15-hotfix/pr-44513
fix: correct color for draft in list view (backport #44513)
2024-12-09 14:08:04 +05:30
ljain112
cce1cc6674 fix: correct color for draft in list view
(cherry picked from commit 143acf2330)
2024-12-09 08:04:53 +00:00
ruthra kumar
c6c5587cc6 Merge pull request #44610 from ruthra-kumar/backport_v15_44495
fix: prevent set_payment_schedule on return documents
2024-12-09 13:34:07 +05:30
ruthra kumar
2560beb695 fix: prevent set_payment_schedule on return documents 2024-12-09 12:58:20 +05:30
ruthra kumar
80f2fc8e64 Merge pull request #44603 from frappe/mergify/bp/version-15-hotfix/pr-44582
fix: add doc.status for translation (backport #44582)
2024-12-09 12:09:13 +05:30
mahsem
47e1ed1eff fix: add docstatus for translation
(cherry picked from commit dda272220b)
2024-12-09 05:52:16 +00:00
Frappe PR Bot
3c8abe41e7 chore(release): Bumped to Version 15.45.4
## [15.45.4](https://github.com/frappe/erpnext/compare/v15.45.3...v15.45.4) (2024-12-08)

### Bug Fixes

* BOM has not attr required items (backport [#44598](https://github.com/frappe/erpnext/issues/44598)) ([#44600](https://github.com/frappe/erpnext/issues/44600)) ([971e474](971e474640))
2024-12-08 11:01:12 +00:00
rohitwaghchaure
70e44a4df1 Merge pull request #44601 from frappe/mergify/bp/version-15/pr-44600
fix: BOM has not attr required items (backport #44598) (backport #44600)
2024-12-08 16:29:57 +05:30
mergify[bot]
971e474640 fix: BOM has not attr required items (backport #44598) (#44600)
fix: BOM has not attr required items (#44598)

(cherry picked from commit 42d238da14)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 608eaaa482)
2024-12-08 10:37:46 +00:00
mergify[bot]
2a17ecdc39 fix: currency symbol in SCO and SCR (backport #44577) (#44594)
* fix: currency symbol in SCO and SCR (#44577)

(cherry picked from commit 8806d17ef1)

# Conflicts:
#	erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.json
#	erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json
#	erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.json
#	erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json

* chore: fix conflicts

* chore: fix conflicts

* chore: fix conflicts

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-08 16:07:06 +05:30
mergify[bot]
608eaaa482 fix: BOM has not attr required items (backport #44598) (#44600)
fix: BOM has not attr required items (#44598)

(cherry picked from commit 42d238da14)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-08 16:06:41 +05:30
Frappe PR Bot
6f80af0355 chore(release): Bumped to Version 15.45.3
## [15.45.3](https://github.com/frappe/erpnext/compare/v15.45.2...v15.45.3) (2024-12-08)

### Bug Fixes

* duplicate buttons ([11fc560](11fc560a88))
2024-12-08 09:23:09 +00:00
rohitwaghchaure
0c3bf2daf1 Merge pull request #44597 from rohitwaghchaure/fixed-duplicate-buttons
fix: duplicate buttons
2024-12-08 14:51:46 +05:30
Rohit Waghchaure
11fc560a88 fix: duplicate buttons 2024-12-08 14:44:19 +05:30
Frappe PR Bot
0cd495a128 chore(release): Bumped to Version 15.45.2
## [15.45.2](https://github.com/frappe/erpnext/compare/v15.45.1...v15.45.2) (2024-12-07)

### Bug Fixes

* BOM name issue (backport [#44586](https://github.com/frappe/erpnext/issues/44586)) ([#44589](https://github.com/frappe/erpnext/issues/44589)) ([408a092](408a09233b))
2024-12-07 08:18:12 +00:00
rohitwaghchaure
3a98660739 Merge pull request #44593 from frappe/mergify/bp/version-15/pr-44589
fix: BOM name issue (backport #44586) (backport #44589)
2024-12-07 13:46:44 +05:30
rohitwaghchaure
97c91c2217 Merge branch 'version-15' into mergify/bp/version-15/pr-44589 2024-12-07 13:12:59 +05:30
rohitwaghchaure
a204abcaa5 chore: fix conflicts 2024-12-07 13:10:40 +05:30
Frappe PR Bot
3b57767d36 chore(release): Bumped to Version 15.45.1
## [15.45.1](https://github.com/frappe/erpnext/compare/v15.45.0...v15.45.1) (2024-12-07)

### Bug Fixes

* BOM for variant items (backport [#44580](https://github.com/frappe/erpnext/issues/44580)) ([#44584](https://github.com/frappe/erpnext/issues/44584)) ([2a2d8da](2a2d8da628))
* BOM name issue (backport [#44575](https://github.com/frappe/erpnext/issues/44575)) ([#44579](https://github.com/frappe/erpnext/issues/44579)) ([27b63be](27b63beb18))
* variant qty while making work order from BOM (backport [#44548](https://github.com/frappe/erpnext/issues/44548)) ([#44551](https://github.com/frappe/erpnext/issues/44551)) ([3c50cfe](3c50cfef4e))
2024-12-07 07:35:56 +00:00
rohitwaghchaure
dc74912f5d Merge pull request #44592 from frappe/mergify/bp/version-15/pr-44584
fix: BOM for variant items (backport #44580) (backport #44584)
2024-12-07 13:04:33 +05:30
rohitwaghchaure
d860a5b35d Merge pull request #44591 from frappe/mergify/bp/version-15/pr-44579
fix: BOM name issue (backport #44575) (backport #44579)
2024-12-07 13:04:03 +05:30
rohitwaghchaure
b00cc83ae6 Merge pull request #44590 from frappe/mergify/bp/version-15/pr-44551
fix: variant qty while making work order from BOM (backport #44548) (backport #44551)
2024-12-07 13:03:47 +05:30
mergify[bot]
408a09233b fix: BOM name issue (backport #44586) (#44589)
fix: BOM name issue (#44586)

(cherry picked from commit d871e21a40)

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

# Conflicts:
#	erpnext/manufacturing/doctype/bom/bom.py
2024-12-07 07:29:44 +00:00
mergify[bot]
a5cc307417 fix: BOM name issue (backport #44586) (#44589)
fix: BOM name issue (#44586)

(cherry picked from commit d871e21a40)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-07 12:58:34 +05:30
mergify[bot]
2a2d8da628 fix: BOM for variant items (backport #44580) (#44584)
fix: BOM for variant items (#44580)

(cherry picked from commit 93e9517f5d)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 0b268279cf)
2024-12-07 06:57:37 +00:00
mergify[bot]
27b63beb18 fix: BOM name issue (backport #44575) (#44579)
fix: BOM name issue (#44575)

fix: bom name issue
(cherry picked from commit b7a3c6b6ca)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 03ae9e27be)
2024-12-07 06:56:36 +00:00
mergify[bot]
3c50cfef4e fix: variant qty while making work order from BOM (backport #44548) (#44551)
fix: variant qty while making work order from BOM (#44548)

(cherry picked from commit 1571dff3ef)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 63b1df38a8)
2024-12-07 06:56:31 +00:00
mergify[bot]
0b268279cf fix: BOM for variant items (backport #44580) (#44584)
fix: BOM for variant items (#44580)

(cherry picked from commit 93e9517f5d)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-06 22:35:37 +05:30
mergify[bot]
03ae9e27be fix: BOM name issue (backport #44575) (#44579)
fix: BOM name issue (#44575)

fix: bom name issue
(cherry picked from commit b7a3c6b6ca)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-06 21:50:49 +05:30
mergify[bot]
31c2b818bd fix(Bank Transaction): error in party matching should not block submitting (backport #44416) (#44574)
fix(Bank Transaction): error in party matching should not block submitting (#44416)

(cherry picked from commit 72256565bb)

Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2024-12-06 11:57:48 +01:00
ruthra kumar
f4cdf02e85 Merge pull request #44572 from frappe/mergify/bp/version-15-hotfix/pr-44538
fix: add labels for translation in purchase_order_analysis.py (backport #44538)
2024-12-06 12:21:17 +05:30
mahsem
f06827c6fb fix: add labels for translation in purchase_order_analysis.py
(cherry picked from commit 342a398bec)
2024-12-06 06:49:55 +00:00
ruthra kumar
672aa42d03 Merge pull request #44570 from frappe/mergify/bp/version-15-hotfix/pr-44539
fix: add labels for translation in production_analytics.py (backport #44539)
2024-12-06 12:17:11 +05:30
mahsem
7a6cb0f157 fix: add labels for translation in production_analytics.py
(cherry picked from commit 9b09116576)
2024-12-06 06:46:29 +00:00
ruthra kumar
7940feaa1c Merge pull request #44568 from frappe/mergify/bp/version-15-hotfix/pr-44541
fix: add labels for translation in quality_inspection_summary.py (backport #44541)
2024-12-06 12:16:21 +05:30
ruthra kumar
3bfb271ddc Merge pull request #44566 from frappe/mergify/bp/version-15-hotfix/pr-44558
fix: add string for translation in delayed_tasks_summary.py (backport #44558)
2024-12-06 12:15:57 +05:30
mahsem
dd3a747af4 fix: add labels for translation in quality_inspection_summary.py
(cherry picked from commit 6ff4704345)
2024-12-06 06:45:26 +00:00
mahsem
43fc8bf74e fix: add string for translation in delayed_tasks_summary.py
(cherry picked from commit 84b54f549a)
2024-12-06 06:44:55 +00:00
ruthra kumar
33d69222ca Merge pull request #44564 from frappe/mergify/bp/version-15-hotfix/pr-44559
fix: add strings for translation payment_terms_status_for_sales_order.py (backport #44559)
2024-12-06 12:13:12 +05:30
mahsem
773e03f84f fix: add strings for translation payment_terms_status_for_sales_order.py
(cherry picked from commit 7d244051c8)
2024-12-06 06:38:31 +00:00
ruthra kumar
e6d1f1af91 Merge pull request #44562 from frappe/mergify/bp/version-15-hotfix/pr-44560
fix: add labels for translation in sales_order_analysis.py (backport #44560)
2024-12-06 12:07:15 +05:30
mahsem
6980d1e142 fix: add labels for translation in sales_order_analysis.py
(cherry picked from commit 8a554a5538)
2024-12-06 06:09:36 +00:00
mergify[bot]
06ac21dd85 chore: Ignore stock validation for non stock invoices (backport #44549) (#44554)
chore: Ignore stock validation for non stock invoices (#44549)

* chore: Ignore stock validation for non stock invoices

* chore: Ignore stock validation for non stock invoices

(cherry picked from commit 1ac292285e)

Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
2024-12-05 22:57:09 +05:30
mergify[bot]
63b1df38a8 fix: variant qty while making work order from BOM (backport #44548) (#44551)
fix: variant qty while making work order from BOM (#44548)

(cherry picked from commit 1571dff3ef)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-05 16:01:04 +05:30
mergify[bot]
5ef063c634 fix: not able to make PO for returned qty from material request (backport #44540) (#44547)
fix: not able to make PO for returned qty from material request (#44540)

(cherry picked from commit 024c442087)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-05 15:52:04 +05:30
mergify[bot]
99a327155e fix: update qty in SABB if qty changed in stock reco (backport #44542) (#44546)
fix: update qty in SABB if qty changed in stock reco (#44542)

(cherry picked from commit 7249cf0001)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-05 15:51:44 +05:30
Khushi Rawat
59c7b80a2f Merge pull request #44544 from frappe/mergify/bp/version-15-hotfix/pr-44537
fix: add title for translation in  asset.js (backport #44537)
2024-12-05 15:42:22 +05:30
mahsem
843ff18cf9 fix: add title for translation in asset.js
(cherry picked from commit 61439132a4)
2024-12-05 09:47:58 +00:00
mergify[bot]
3771c6eeae fix: consider zero valuation rate for serial nos (backport #44532) (#44534)
fix: consider zero valuation rate for serial nos (#44532)

(cherry picked from commit 14f2b0ab0e)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-05 13:46:23 +05:30
mergify[bot]
f4aa4c9466 fix: incorrect stock UOM for BOM raw materials (backport #44528) (#44531)
fix: incorrect stock UOM for BOM raw materials (#44528)

fix: incorrect stock uom for BOM raw materials
(cherry picked from commit 5413cf9f1f)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-05 12:51:25 +05:30
ruthra kumar
4f05e45698 Merge pull request #44529 from frappe/mergify/bp/version-15-hotfix/pr-44503
fix: add strings for translation in pos_item_cart.js (backport #44503)
2024-12-05 10:25:23 +05:30
ruthra kumar
d540c99934 chore: linter fix
(cherry picked from commit 31efaf6dbf)
2024-12-05 04:49:18 +00:00
mahsem
71d8dfb401 fix: add strings for translation in pos_item_cart.js
(cherry picked from commit 4b72b60f1a)
2024-12-05 04:49:18 +00:00
ruthra kumar
71d53dd5ef Merge pull request #44526 from frappe/mergify/bp/version-15-hotfix/pr-44512
fix: add label strings for translation in pos_controller.js (backport #44512)
2024-12-05 10:19:15 +05:30
mahsem
ffdd7cfa86 fix: add label strings for translation in pos_controller.js
(cherry picked from commit bd77a5557d)
2024-12-05 04:43:16 +00:00
ruthra kumar
3d6d560777 Merge pull request #44524 from frappe/mergify/bp/version-15-hotfix/pr-44501
fix: strings for translation in pos_past_order_summary.js (backport #44501)
2024-12-05 10:12:55 +05:30
ruthra kumar
2139e6fba2 Merge pull request #44522 from frappe/mergify/bp/version-15-hotfix/pr-42081
Use better description in pos_payment.js (backport #42081)
2024-12-05 10:12:27 +05:30
ruthra kumar
6c0949e6dd Merge pull request #44520 from frappe/mergify/bp/version-15-hotfix/pr-44500
fix: add labels for translation in sales_order.js (backport #44500)
2024-12-05 10:11:59 +05:30
mahsem
ceec5fdb6c fix: strings for translation in pos_past_order_summary.js
(cherry picked from commit 23c846d4b9)
2024-12-05 04:32:03 +00:00
mahsem
af97d3e341 refactor: translatable label on pos payments (#42081)
* Use better description in pos_payment.js

Use Change Amount instead of Change and To Be Paid in pos_payment.js and be consistent with other strings

* change_amount_pos_payment.js

(cherry picked from commit 138ffc4e93)
2024-12-05 04:31:01 +00:00
mahsem
283043eba7 fix: add labels for translation in sales_order.js
(cherry picked from commit d544328ffe)
2024-12-05 04:29:43 +00:00
mergify[bot]
8733eda576 fix: inv dimensions fields not creating for standard doctype (backport #44504) (#44515)
fix: inv dimensions fields not creating for standard doctype (#44504)

(cherry picked from commit 353610ce61)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-05 09:45:17 +05:30
mergify[bot]
07df87ab69 fix: required by date in the reorder material request (backport #44497) (#44509)
fix: required by date in the reorder material request (#44497)

(cherry picked from commit 4001166ecc)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-04 19:02:45 +05:30
mergify[bot]
539c5b7974 fix: duplicate required items in the CSV (backport #44498) (#44507)
* fix: duplicate required items in the CSV (#44498)

(cherry picked from commit b4534e56e4)

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

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-04 19:02:26 +05:30
ruthra kumar
94a0725917 Merge pull request #44499 from frappe/mergify/bp/version-15-hotfix/pr-44496
fix: add strings for translation in timesheet.js (backport #44496)
2024-12-04 16:21:10 +05:30
mahsem
106671a414 fix: add strings for translation in timesheet.js (#44496)
(cherry picked from commit 6585fabdb1)
2024-12-04 07:36:49 +00:00
Frappe PR Bot
1d158d58f6 chore(release): Bumped to Version 15.45.0
# [15.45.0](https://github.com/frappe/erpnext/compare/v15.44.0...v15.45.0) (2024-12-04)

### Bug Fixes

* Add filter for `outstanding_amount` to fetch open PRs ([5999a8e](5999a8e24f))
* Add translation for showing mandatory fields in error msg ([0e1f5ff](0e1f5ff391))
* added fieldname to avoid fieldname to translate ([17c2734](17c2734042))
* Added translation for `Account` column ([eb4a485](eb4a485df6))
* adjusted incoming rate for zero rated item in purchase receipt ([435280d](435280d626))
* always set sales incoming rate for internal transfers ([05795af](05795af471))
* calculate submitted payment entry as paid amount ([ebdacc0](ebdacc094c))
* correct buying amount for product bundel ([f165e17](f165e1732b))
* Dashboard for `Payment Request` ([0d67c62](0d67c62f43))
* Data Should be Computed in Backend to Maintain Consistent Behaviour ([#44195](https://github.com/frappe/erpnext/issues/44195)) ([8ab9fc7](8ab9fc7f55))
* do not validate stock during inward (backport [#44417](https://github.com/frappe/erpnext/issues/44417)) ([#44427](https://github.com/frappe/erpnext/issues/44427)) ([e607795](e607795bae))
* handle multi currency in common party journal entry ([c8e2c9a](c8e2c9aa25))
* incorrect Gross Margin on project (backport [#44461](https://github.com/frappe/erpnext/issues/44461)) ([#44468](https://github.com/frappe/erpnext/issues/44468)) ([0a9c92f](0a9c92fce9))
* IndexError in Asset Depreciation Ledger when query result is empty ([c3bc724](c3bc724523))
* link cash flow rows and fix summary linking ([633be8d](633be8d06b))
* move validate_total_debit_and_credit from validate to on_submit in Journal Entry ([63de576](63de576be6))
* number format in the message (backport [#44435](https://github.com/frappe/erpnext/issues/44435)) ([#44438](https://github.com/frappe/erpnext/issues/44438)) ([579d8e2](579d8e293e))
* precision calculation causing 0.1 discrepancy (backport [#44431](https://github.com/frappe/erpnext/issues/44431)) ([#44436](https://github.com/frappe/erpnext/issues/44436)) ([0d41c23](0d41c23383))
* remove queries ([ea57f2b](ea57f2b292))
* SABB print for packed items (backport [#44413](https://github.com/frappe/erpnext/issues/44413)) ([#44428](https://github.com/frappe/erpnext/issues/44428)) ([0e39aa3](0e39aa349e))
* set correct unallocated amount in Payment Entry ([#43958](https://github.com/frappe/erpnext/issues/43958)) ([ae93f7f](ae93f7f967))
* show "Send SMS" only when enabled (backport [#43941](https://github.com/frappe/erpnext/issues/43941)) ([#43970](https://github.com/frappe/erpnext/issues/43970)) ([0fbc60a](0fbc60a20e))
* source warehouse not set in required items of WO (backport [#44426](https://github.com/frappe/erpnext/issues/44426)) ([#44434](https://github.com/frappe/erpnext/issues/44434)) ([c81b5e3](c81b5e3d9c))
* Translate `Party Account` column label ([fdda864](fdda86455a))
* typeerror on transaction.js ([173d60f](173d60fb7d))

### Features

* add Company Contact Person in selling transactions (backport [#44362](https://github.com/frappe/erpnext/issues/44362)) ([#44398](https://github.com/frappe/erpnext/issues/44398)) ([70b5b08](70b5b08d58))
* **Dunning:** separate tab "Address & Contact" ([#44363](https://github.com/frappe/erpnext/issues/44363)) ([e0cb5f9](e0cb5f9ba8))

### Performance Improvements

* cache product bundle items at document level ([#44440](https://github.com/frappe/erpnext/issues/44440)) ([1f97979](1f97979059))
* reduce queries during transaction save ([48059a7](48059a7c74))

### Reverts

* remove default `Payment Request` indicator color ([9c4b581](9c4b5814a6))
2024-12-04 04:38:06 +00:00
ruthra kumar
cd57f5cd0a Merge pull request #44483 from frappe/version-15-hotfix
chore: release v15
2024-12-04 10:06:46 +05:30
ruthra kumar
3e2bc139ab Merge pull request #44491 from frappe/mergify/bp/version-15-hotfix/pr-44339
fix: move `validate_total_debit_and_credit` from`validate` to`on_submit` in Journal Entry (backport #44339)
2024-12-03 19:52:30 +05:30
ruthra kumar
16d0d42afe refactor: validate debit and credit on before_submit
(cherry picked from commit c3ace82db8)
2024-12-03 13:47:27 +00:00
vishakhdesai
63de576be6 fix: move validate_total_debit_and_credit from validate to on_submit in Journal Entry
(cherry picked from commit 8b5d4c0236)
2024-12-03 13:47:27 +00:00
ruthra kumar
d5a544ca69 Merge pull request #44485 from frappe/mergify/bp/version-15-hotfix/pr-44467
fix: Multiple Fixes in Gross Profit Report (backport #44467)
2024-12-03 19:15:15 +05:30
ruthra kumar
4a713f6b5e chore: fix typo
(cherry picked from commit fc0122ce76)
2024-12-03 12:01:07 +00:00
ljain112
f165e1732b fix: correct buying amount for product bundel
(cherry picked from commit 4e6a5893e7)
2024-12-03 12:01:07 +00:00
ljain112
ea57f2b292 fix: remove queries
(cherry picked from commit a86b223aed)
2024-12-03 12:01:07 +00:00
ruthra kumar
c880476cbe Merge pull request #44481 from frappe/mergify/bp/version-15-hotfix/pr-44450
fix: calculate submitted payment entry amount for grand total (backport #44450)
2024-12-03 15:15:40 +05:30
mergify[bot]
0a9c92fce9 fix: incorrect Gross Margin on project (backport #44461) (#44468)
* fix: incorrect Gross Margin on project (#44461)

(cherry picked from commit 7de9c14a2c)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py

* chore: resolve conflict

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
Co-authored-by: ruthra kumar <ruthra@erpnext.com>
2024-12-03 15:09:09 +05:30
Sugesh393
aa090beae0 test: add new unit test to validate paid amount in payment request
(cherry picked from commit 9bee2d430c)
2024-12-03 09:22:23 +00:00
Sugesh393
ebdacc094c fix: calculate submitted payment entry as paid amount
(cherry picked from commit 561a159aec)
2024-12-03 09:22:23 +00:00
ruthra kumar
0c28726ce2 Merge pull request #44480 from frappe/mergify/bp/version-15-hotfix/pr-44415
fix: adjusted incoming rate for zero rated item in purchase receipt (backport #44415)
2024-12-03 14:48:51 +05:30
ruthra kumar
be0604f7cf Merge pull request #44478 from frappe/mergify/bp/version-15-hotfix/pr-44373
fix: Always Calculate `sales_incoming_rate` for Internal Transfers (backport #44373)
2024-12-03 14:48:14 +05:30
ljain112
435280d626 fix: adjusted incoming rate for zero rated item in purchase receipt
(cherry picked from commit 3182c6981c)
2024-12-03 08:56:10 +00:00
Ninad1306
558d49b3d3 test: validate buying workflow
(cherry picked from commit 94d3fc9fde)
2024-12-03 08:48:52 +00:00
Ninad1306
05795af471 fix: always set sales incoming rate for internal transfers
(cherry picked from commit d049c97884)
2024-12-03 08:48:51 +00:00
ruthra kumar
38aa3769bb Merge pull request #44477 from frappe/mergify/bp/version-15-hotfix/pr-44470
refactor(UI): Rearranging fields under new sections (backport #44470)
2024-12-03 11:13:37 +05:30
ruthra kumar
5c6d9c9812 refactor(UI): Rearranging fields under new sections
(cherry picked from commit 7244754d28)
2024-12-03 05:00:17 +00:00
ruthra kumar
85fda71835 Merge pull request #44368 from frappe/mergify/bp/version-15-hotfix/pr-44363
feat(Dunning): separate tab "Address & Contact" (backport #44363)
2024-12-03 10:21:22 +05:30
ruthra kumar
7150aff520 Merge pull request #44466 from frappe/mergify/bp/version-15-hotfix/pr-43958
fix: set correct unallocated amount in Payment Entry (backport #43958)
2024-12-02 16:15:53 +05:30
ruthra kumar
c157978912 chore: resolve conflicts 2024-12-02 15:24:32 +05:30
Sagar Vora
ae93f7f967 fix: set correct unallocated amount in Payment Entry (#43958)
* fix: set correct unallocated amount in Payment Entry

* fix: add checkbox and other logic fix

* fix: patch to set is_exchange_gain_loss in Payment Entry deductions

* fix: consider deductions except exch. gain/loss

* fix: set exchange gain loss in payment entry

* fix: separate function to set exchange gain loss

* fix: failing test cases

* fix: add cash disc. row first

* fix: review changes

* fix: changes as per review

* fix: failing test cases

* fix: review

* fix: wait for request to complete before updating exchange gain loss

* fix: review

---------

Co-authored-by: vishakhdesai <vishakhdesai@gmail.com>
Co-authored-by: ruthra kumar <ruthra@erpnext.com>
(cherry picked from commit 7cc111f790)

# Conflicts:
#	erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.json
#	erpnext/patches.txt
2024-12-02 09:25:55 +00:00
ruthra kumar
f5ddc9a543 Merge pull request #44465 from frappe/mergify/bp/version-15-hotfix/pr-44412
fix: handle multi currency in common party journal entry (backport #44412)
2024-12-02 14:35:44 +05:30
ruthra kumar
4c5570ae7d chore: resolve conflict 2024-12-02 13:46:39 +05:30
ruthra kumar
d0356f81ba Merge pull request #44463 from frappe/mergify/bp/version-15-hotfix/pr-44437
fix: Added translation for `Account` column (backport #44437)
2024-12-02 13:39:50 +05:30
ljain112
c8e2c9aa25 fix: handle multi currency in common party journal entry
(cherry picked from commit e371f68d66)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
2024-12-02 07:10:11 +00:00
Abdeali Chharchhoda
fdda86455a fix: Translate Party Account column label
(cherry picked from commit a4f8315602)
2024-12-02 06:53:42 +00:00
Abdeali Chharchhoda
eb4a485df6 fix: Added translation for Account column
(cherry picked from commit de6cbd382f)
2024-12-02 06:53:41 +00:00
mergify[bot]
579d8e293e fix: number format in the message (backport #44435) (#44438)
fix: number format in the message (#44435)

(cherry picked from commit 810c72a30c)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-30 13:42:54 +05:30
Sagar Vora
a807776f83 Merge pull request #44447 from frappe/mergify/bp/version-15-hotfix/pr-44443
perf: reduce queries during transaction save (backport #44443)
2024-11-30 00:48:36 +05:30
Sagar Vora
48059a7c74 perf: reduce queries during transaction save
(cherry picked from commit b6b8a06fda)
2024-11-29 19:17:31 +00:00
Sagar Vora
0199bc127a Merge pull request #44445 from frappe/mergify/bp/version-15-hotfix/pr-44439
fix: added fieldname to avoid fieldname to translate (backport #44439)
2024-11-30 00:30:01 +05:30
Abdeali Chharchhoda
17c2734042 fix: added fieldname to avoid fieldname to translate
(cherry picked from commit b80022133c)
2024-11-29 18:56:45 +00:00
Sagar Vora
a1643ad292 Merge pull request #44442 from frappe/mergify/bp/version-15-hotfix/pr-44440
perf: cache product bundle items at document level (backport #44440)
2024-11-29 23:04:14 +05:30
Sagar Vora
1f97979059 perf: cache product bundle items at document level (#44440)
(cherry picked from commit 6de7320ef4)
2024-11-29 17:23:36 +00:00
mergify[bot]
c81b5e3d9c fix: source warehouse not set in required items of WO (backport #44426) (#44434)
fix: source warehouse not set in required items of WO (#44426)

fix: source warehouse not set in required items of WO on data import
(cherry picked from commit 4050ea07eb)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-29 18:13:05 +05:30
mergify[bot]
0d41c23383 fix: precision calculation causing 0.1 discrepancy (backport #44431) (#44436)
fix: precision calculation causing 0.1 discrepancy (#44431)

(cherry picked from commit 7f7564b581)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-29 18:12:24 +05:30
mergify[bot]
0e39aa349e fix: SABB print for packed items (backport #44413) (#44428)
fix: SABB print for packed items (#44413)

(cherry picked from commit 5266f236b7)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-29 17:00:59 +05:30
mergify[bot]
e607795bae fix: do not validate stock during inward (backport #44417) (#44427)
fix: do not validate stock during inward (#44417)

(cherry picked from commit d37d7b9811)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-29 15:49:18 +05:30
ruthra kumar
821f39203c Merge pull request #44391 from frappe/mergify/bp/version-15-hotfix/pr-44386
fix: Add translation for showing mandatory fields in error msg (backport #44386)
2024-11-29 15:38:35 +05:30
ruthra kumar
35e365c263 Merge pull request #44425 from frappe/mergify/bp/version-15-hotfix/pr-44302
fix: Minor Updates in `Payment Request` and `Payment Entry`  (backport #44302)
2024-11-29 15:38:01 +05:30
ruthra kumar
1c50111371 chore: resolve conflict 2024-11-29 14:50:41 +05:30
Abdeali Chharchhoda
5999a8e24f fix: Add filter for outstanding_amount to fetch open PRs
(cherry picked from commit 214dfab269)
2024-11-29 09:11:11 +00:00
Abdeali Chharchhoda
4b046160f8 refactor: Move PR link filters to client side
(cherry picked from commit 2db2c8bce1)
2024-11-29 09:11:11 +00:00
Abdeali Chharchhoda
9c4b5814a6 revert: remove default Payment Request indicator color
(cherry picked from commit 37ceb09955)

# Conflicts:
#	erpnext/accounts/doctype/payment_request/payment_request_list.js
2024-11-29 09:11:11 +00:00
Abdeali Chharchhoda
0d67c62f43 fix: Dashboard for Payment Request
(cherry picked from commit 91955e27c3)
2024-11-29 09:11:10 +00:00
Abdeali Chharchhoda
5f785ede16 refactor: Used object to get payment request status indicator
(cherry picked from commit e1c4d6e1e6)

# Conflicts:
#	erpnext/accounts/doctype/payment_request/payment_request_list.js
2024-11-29 09:11:10 +00:00
ruthra kumar
5b2fce2df7 Merge pull request #44419 from frappe/mergify/bp/version-15-hotfix/pr-42524
fix: link cash flow rows and fix summary linking (backport #42524)
2024-11-29 12:22:51 +05:30
ruthra kumar
ae81bb3c1b chore: revert 'stub' 2024-11-29 10:52:38 +05:30
ruthra kumar
48d6fcaab8 chore: resolve conflict 2024-11-29 10:43:36 +05:30
David
633be8d06b fix: link cash flow rows and fix summary linking
(cherry picked from commit b94af28587)

# Conflicts:
#	erpnext/public/js/financial_statements.js
2024-11-29 05:00:48 +00:00
Khushi Rawat
651d7e4cfc Merge pull request #44402 from frappe/mergify/bp/version-15-hotfix/pr-44400
fix: IndexError in Asset Depreciation Ledger when query result is empty (backport #44400)
2024-11-28 18:59:11 +05:30
Smit Vora
0084f45629 Merge pull request #44410 from frappe/mergify/bp/version-15-hotfix/pr-44195
fix: Data Should be Computed in Backend to Maintain Consistent Behaviour (backport #44195)
2024-11-28 16:27:05 +05:30
Ninad Parikh
8ab9fc7f55 fix: Data Should be Computed in Backend to Maintain Consistent Behaviour (#44195)
(cherry picked from commit 69bd90b038)
2024-11-28 10:31:27 +00:00
ruthra kumar
11c54d27f2 Merge pull request #44407 from frappe/mergify/bp/version-15-hotfix/pr-44405
fix: typeerror on transaction.js (backport #44405)
2024-11-28 15:02:04 +05:30
ruthra kumar
173d60fb7d fix: typeerror on transaction.js
(cherry picked from commit 46ce8780f2)
2024-11-28 09:20:38 +00:00
Khushi Rawat
5bbef90f08 chore: removed print statement
(cherry picked from commit 1737de7c10)
2024-11-28 07:27:42 +00:00
Khushi Rawat
c3bc724523 fix: IndexError in Asset Depreciation Ledger when query result is empty
(cherry picked from commit 7c393e5aa0)
2024-11-28 07:27:42 +00:00
mergify[bot]
0fbc60a20e fix: show "Send SMS" only when enabled (backport #43941) (#43970)
fix: show "Send SMS" only when enabled (#43941)

(cherry picked from commit 65088cbb1b)

Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2024-11-27 23:52:16 +01:00
mergify[bot]
70b5b08d58 feat: add Company Contact Person in selling transactions (backport #44362) (#44398)
* feat: add Company Contact Person in selling transactions (#44362)

(cherry picked from commit f6776c7d6b)

* chore: resolve merge conflicts

---------

Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2024-11-27 18:55:43 +01:00
Frappe PR Bot
294ded2030 chore(release): Bumped to Version 15.44.0
# [15.44.0](https://github.com/frappe/erpnext/compare/v15.43.3...v15.44.0) (2024-11-27)

### Bug Fixes

*  correct placeholder index in message ([a523c14](a523c14fd5))
* add company dynamic filters in number cards ([db21def](db21def58b))
* added Stock UOM field for RM in work order (backport [#44185](https://github.com/frappe/erpnext/issues/44185)) ([#44237](https://github.com/frappe/erpnext/issues/44237)) ([d4f0512](d4f0512a10))
* added validation for quality inspection (backport [#44351](https://github.com/frappe/erpnext/issues/44351)) ([#44357](https://github.com/frappe/erpnext/issues/44357)) ([89bd4eb](89bd4eba46))
* billed qty and received amount in PO analysis report (backport [#44349](https://github.com/frappe/erpnext/issues/44349)) ([#44354](https://github.com/frappe/erpnext/issues/44354)) ([ea0f24a](ea0f24aa57))
* check difference with company currency ([d6ef438](d6ef43858c))
* filter item with search fields ([d073b00](d073b005a8))
* filter with item group only if it is mentioned in pos profile ([a439862](a4398626f6))
* Get submitted documents in validate_for_closed_fiscal_year ([af74a3c](af74a3c32f))
* gp for return invoice ([f4518ca](f4518cac9a))
* include current invoice amount when tax_on_excess_amount is checked ([0ffeb9f](0ffeb9f6ad))
* Increase quantity by `1 UOM` when adding an item from the selector in POS ([0d38028](0d3802873b))
* initially closing amt should be equal to expected amt ([3f57777](3f577779be))
* make free qty round on large transaction qty ([4856a96](4856a9633e))
* no permission to read Doctype (backport [#44256](https://github.com/frappe/erpnext/issues/44256)) ([#44258](https://github.com/frappe/erpnext/issues/44258)) ([8b15a96](8b15a965dd))
* not able to fetch batch item price ([97f2341](97f2341b98))
* patch ([#44191](https://github.com/frappe/erpnext/issues/44191)) ([8b02402](8b02402f62))
* reduce paid amount from grand total ([d0d97c2](d0d97c26a0))
* remove field precision in SO and PO for percentage fields ([860350a](860350a5b3))
* remove irrelavent filters ([7423d7d](7423d7d337))
* set debit transaction currency in gl entry ([a2612d5](a2612d5f36))
* set outstanding amount while creating payment request for invoices ([8d8027d](8d8027d423))
* set price_list_currency only if it exists ([8cd455b](8cd455b050))
* Show available stock qty in `stock_uom` instead of `uom` ([49dad1a](49dad1a456))
* show cc on the email ([67809c7](67809c781a))
* test case ([66af7f4](66af7f4a14))
* toggle debit credit amounts for transaction currency too; minor refactor ([7f8334f](7f8334f29a))
* unify company address query in sales transactions (backport [#44361](https://github.com/frappe/erpnext/issues/44361)) ([#44365](https://github.com/frappe/erpnext/issues/44365)) ([7e61aca](7e61aca512))
* update gross profit for returned invoices ([ca56709](ca56709295))
* use field precision instead of hardcoded precision in so and po ([cde1906](cde19066fe))

### Features

* available qty at company in sales transactions (backport [#44260](https://github.com/frappe/erpnext/issues/44260)) ([#44325](https://github.com/frappe/erpnext/issues/44325)) ([20d0e95](20d0e95d7c))
* provision to disable item attribute (backport [#44358](https://github.com/frappe/erpnext/issues/44358)) ([#44370](https://github.com/frappe/erpnext/issues/44370)) ([ef882de](ef882de509))
* Show Aggregate Value from Subsidiary Companies ([0469b0d](0469b0d1ec))

### Reverts

* use `+ flt(value)` instead of direct increment ([b65e16a](b65e16a91b))
2024-11-27 16:01:32 +00:00
ruthra kumar
9f3ae08e3b Merge pull request #44341 from frappe/version-15-hotfix
chore: release v15
2024-11-27 21:30:10 +05:30
ruthra kumar
1f683afa43 Merge pull request #44396 from frappe/mergify/bp/version-15-hotfix/pr-44346
fix: reduce paid amount from grand total (backport #44346)
2024-11-27 21:12:51 +05:30
ruthra kumar
0ab0b4f716 chore: resolve conflict 2024-11-27 20:52:14 +05:30
ruthra kumar
4be6a78691 Merge pull request #44394 from frappe/mergify/bp/version-15-hotfix/pr-44392
chore: Fix typo "Purchase Reecipt" (backport #44392)
2024-11-27 20:24:46 +05:30
Sugesh393
d0d97c26a0 fix: reduce paid amount from grand total
(cherry picked from commit 82907672d9)
2024-11-27 14:41:46 +00:00
Sugesh393
81b9832917 test: add unit test to validate outstanding amount in payment request
(cherry picked from commit bbe3bc95d0)

# Conflicts:
#	erpnext/accounts/doctype/payment_request/test_payment_request.py
2024-11-27 14:41:46 +00:00
Sugesh393
8d8027d423 fix: set outstanding amount while creating payment request for invoices
(cherry picked from commit 38e7d0a41e)
2024-11-27 14:41:44 +00:00
ruthra kumar
9a374ddbd4 Merge pull request #44395 from frappe/mergify/bp/version-15-hotfix/pr-44316
fix: Initially Closing Amount Should be Equal to Expected Amount (backport #44316)
2024-11-27 20:08:33 +05:30
Ninad1306
3f577779be fix: initially closing amt should be equal to expected amt
(cherry picked from commit af9524920b)
2024-11-27 14:28:47 +00:00
vimalraj27
fd1cbf4b6f chore: Fix typo "Purchase Reecipt"
(cherry picked from commit 21049bae91)
2024-11-27 14:28:00 +00:00
ruthra kumar
5e7cfeb514 Merge pull request #44388 from frappe/mergify/bp/version-15-hotfix/pr-44378
fix: filter item with search fields (backport #44378)
2024-11-27 17:53:51 +05:30
ruthra kumar
223d30ecd8 Merge pull request #44389 from frappe/mergify/bp/version-15-hotfix/pr-44327
fix: set debit transaction currency in gl entry (backport #44327)
2024-11-27 17:53:37 +05:30
Abdeali Chharchhoda
0e1f5ff391 fix: Add translation for showing mandatory fields in error msg
(cherry picked from commit f42ec6a124)
2024-11-27 12:01:10 +00:00
venkat102
a2612d5f36 fix: set debit transaction currency in gl entry
(cherry picked from commit 6e19c06e58)
2024-11-27 11:59:09 +00:00
ruthra kumar
632412bd72 Merge pull request #44383 from frappe/mergify/bp/version-15-hotfix/pr-44376
fix: remove field precision in Sales and Purchase Order for percentage fields (backport #44376)
2024-11-27 17:27:06 +05:30
ruthra kumar
09c28760e4 Merge pull request #44385 from frappe/mergify/bp/version-15-hotfix/pr-44323
fix: update gross profit for returned invoices (backport #44323)
2024-11-27 17:21:26 +05:30
ruthra kumar
7c85e4056f Merge pull request #44387 from frappe/mergify/bp/version-15-hotfix/pr-44359
fix: check difference with company currency (backport #44359)
2024-11-27 17:21:00 +05:30
venkat102
d073b005a8 fix: filter item with search fields
(cherry picked from commit ebfbee3da5)
2024-11-27 11:50:51 +00:00
ruthra kumar
45e41827c7 chore: resolve conflict 2024-11-27 17:20:36 +05:30
venkat102
d6ef43858c fix: check difference with company currency
(cherry picked from commit e2bae4cf07)
2024-11-27 11:26:58 +00:00
ljain112
66af7f4a14 fix: test case
(cherry picked from commit af5a3e5a48)
2024-11-27 11:20:34 +00:00
ljain112
f4518cac9a fix: gp for return invoice
(cherry picked from commit 00403515a8)
2024-11-27 11:20:34 +00:00
ljain112
ca56709295 fix: update gross profit for returned invoices
(cherry picked from commit 8a42601e99)
2024-11-27 11:20:34 +00:00
vishakhdesai
860350a5b3 fix: remove field precision in SO and PO for percentage fields
(cherry picked from commit eff9cd10cd)

# Conflicts:
#	erpnext/selling/doctype/sales_order/sales_order_list.js
2024-11-27 11:19:13 +00:00
ruthra kumar
6a34abefba Merge pull request #44379 from frappe/mergify/bp/version-15-hotfix/pr-44377
fix:  correct placeholder index in message (backport #44377)
2024-11-27 15:38:48 +05:30
ljain112
a523c14fd5 fix: correct placeholder index in message
(cherry picked from commit d61cb9a4bf)
2024-11-27 09:26:09 +00:00
ruthra kumar
6f798ab288 Merge pull request #44372 from frappe/mergify/bp/version-15-hotfix/pr-44343
fix: show cc on the process statement of accounts email (backport #44343)
2024-11-27 10:47:15 +05:30
mergify[bot]
ef882de509 feat: provision to disable item attribute (backport #44358) (#44370)
* feat: provision to disable item attribute (#44358)

(cherry picked from commit 123e3ef263)

# Conflicts:
#	erpnext/stock/doctype/item_attribute/item_attribute.json
#	erpnext/stock/doctype/item_variant_attribute/item_variant_attribute.json

* chore: fix conflicts

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-27 10:31:30 +05:30
venkat102
67809c781a fix: show cc on the email
(cherry picked from commit 2dd5699f6d)
2024-11-27 04:53:16 +00:00
Raffael Meyer
c20def5d59 chore: resolve conflicts 2024-11-26 21:12:39 +01:00
Raffael Meyer
e0cb5f9ba8 feat(Dunning): separate tab "Address & Contact" (#44363)
(cherry picked from commit e094473c65)

# Conflicts:
#	erpnext/accounts/doctype/dunning/dunning.json
2024-11-26 20:11:37 +00:00
mergify[bot]
7e61aca512 fix: unify company address query in sales transactions (backport #44361) (#44365)
fix: unify company address query in sales transactions (#44361)

* fix: unify company address query in sales transactions

* refactor: get the correct field label

(cherry picked from commit 3f92a57d63)

Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2024-11-26 20:16:24 +01:00
mergify[bot]
89bd4eba46 fix: added validation for quality inspection (backport #44351) (#44357)
fix: added validation for quality inspection (#44351)

(cherry picked from commit 0fd50b5048)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-26 21:18:26 +05:30
mergify[bot]
ea0f24aa57 fix: billed qty and received amount in PO analysis report (backport #44349) (#44354)
fix: billed qty and received amount in PO analysis report (#44349)

(cherry picked from commit 2ab7ec5437)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-26 19:43:51 +05:30
ruthra kumar
069c763010 Merge pull request #44338 from frappe/mergify/bp/version-15-hotfix/pr-44319
fix: use field precision in Sales and Purchase Order (backport #44319)
2024-11-26 14:02:33 +05:30
ruthra kumar
bc93de682b chore: resolve conflict 2024-11-26 13:48:00 +05:30
ruthra kumar
8aa4779191 Merge pull request #44335 from frappe/mergify/bp/version-15-hotfix/pr-44304
chore: Add translations to QI validations in Update stock_controller.py (backport #44304)
2024-11-26 12:09:56 +05:30
vishakhdesai
cde19066fe fix: use field precision instead of hardcoded precision in so and po
(cherry picked from commit 1a1e2c7e01)

# Conflicts:
#	erpnext/buying/doctype/purchase_order/purchase_order.js
2024-11-26 06:18:33 +00:00
Ernesto Ruiz
465a26f714 chore: Add translations to QI validations in Update stock_controller.py
chore: Add translations to QI validations in Update stock_controller.py
(cherry picked from commit 6754f15487)
2024-11-26 06:07:15 +00:00
ruthra kumar
ca8e7e9891 Merge pull request #44332 from frappe/mergify/bp/version-15-hotfix/pr-44257
fix: add company dynamic filters in number cards (backport #44257)
2024-11-26 11:19:43 +05:30
Sugesh393
7423d7d337 fix: remove irrelavent filters
(cherry picked from commit 29762c4826)
2024-11-26 05:24:57 +00:00
Sugesh393
db21def58b fix: add company dynamic filters in number cards
(cherry picked from commit 4e7725de66)
2024-11-26 05:24:57 +00:00
ruthra kumar
6a4058052b Merge pull request #44331 from frappe/mergify/bp/version-15-hotfix/pr-44320
fix: Increase quantity by `1 UOM` when adding an item from the selector in `POS` (backport #44320)
2024-11-26 10:40:45 +05:30
Abdeali Chharchhoda
b65e16a91b revert: use + flt(value) instead of direct increment
(cherry picked from commit 112b4c705b)
2024-11-26 05:00:41 +00:00
Abdeali Chharchhoda
49dad1a456 fix: Show available stock qty in stock_uom instead of uom
(cherry picked from commit 84dcbe6639)
2024-11-26 05:00:40 +00:00
Abdeali Chharchhoda
0d3802873b fix: Increase quantity by 1 UOM when adding an item from the selector in POS
(cherry picked from commit bbab850135)
2024-11-26 05:00:40 +00:00
mergify[bot]
20d0e95d7c feat: available qty at company in sales transactions (backport #44260) (#44325)
* feat: available qty at company in sales transactions

(cherry picked from commit d8b9aef14f)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
#	erpnext/selling/doctype/quotation_item/quotation_item.json
#	erpnext/selling/doctype/sales_order_item/sales_order_item.json
#	erpnext/stock/doctype/delivery_note_item/delivery_note_item.json

* chore: fix conflicts

* chore: fix conflicts

* chore: fix conflicts

* chore: fix conflicts

---------

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2024-11-25 20:29:13 +05:30
ruthra kumar
d77a880a62 Merge pull request #44318 from frappe/mergify/bp/version-15-hotfix/pr-44274
fix: set price_list_currency only if it exists (backport #44274)
2024-11-25 12:57:02 +05:30
ruthra kumar
7ccb2ead09 Merge pull request #44317 from frappe/mergify/bp/version-15-hotfix/pr-44163
feat: Show Aggregate Value from Subsidiary Companies (backport #44163)
2024-11-25 12:56:37 +05:30
Sugesh393
8cd455b050 fix: set price_list_currency only if it exists
(cherry picked from commit f0b9cb4019)
2024-11-25 07:10:04 +00:00
ruthra kumar
072c5b7753 chore: resolve conflict 2024-11-25 12:28:02 +05:30
l0gesh29
0469b0d1ec feat: Show Aggregate Value from Subsidiary Companies
(cherry picked from commit c23af6af41)

# Conflicts:
#	erpnext/selling/report/sales_analytics/sales_analytics.js
2024-11-25 06:40:00 +00:00
rohitwaghchaure
74af7d01a2 Merge pull request #44312 from rohitwaghchaure/fixed-support-25969
fix: not able to fetch batch item price
2024-11-25 11:22:43 +05:30
ruthra kumar
c545de7bc6 Merge pull request #44315 from frappe/mergify/bp/version-15-hotfix/pr-44297
refactor: added translate function for some columns of report (backport #44297)
2024-11-25 10:28:02 +05:30
Abdeali Chharchhoda
8928e062b1 refactor: added translate function for some columns of report
(cherry picked from commit e545c913b5)
2024-11-25 04:39:36 +00:00
Rohit Waghchaure
97f2341b98 fix: not able to fetch batch item price 2024-11-24 22:23:11 +05:30
Smit Vora
aa2ae5e408 Merge pull request #44279 from frappe/mergify/bp/version-15-hotfix/pr-44263
fix: toggle debit credit amounts for transaction currency too; minor refactor (backport #44263)
2024-11-22 18:38:26 +05:30
ruthra kumar
6d10ccfc15 Merge pull request #44287 from frappe/mergify/bp/version-15-hotfix/pr-44246
fix: Get submitted documents in validate_for_closed_fiscal_year (backport #44246)
2024-11-22 16:15:48 +05:30
ruthra kumar
dc99e74ae3 Merge pull request #44285 from frappe/mergify/bp/version-15-hotfix/pr-44266
fix: make free qty round on large transaction qty (backport #44266)
2024-11-22 16:15:35 +05:30
ruthra kumar
fd9aa288c4 Merge pull request #44283 from frappe/mergify/bp/version-15-hotfix/pr-44277
fix: filter with item group only if it is mentioned in pos profile (backport #44277)
2024-11-22 16:15:08 +05:30
vimalraj27
af74a3c32f fix: Get submitted documents in validate_for_closed_fiscal_year
(cherry picked from commit c607e5f940)
2024-11-22 10:23:11 +00:00
venkat102
db1bc8a3db test: add unit test to validate free qty round on large transaction qty
(cherry picked from commit 013a6fc6ec)
2024-11-22 10:20:57 +00:00
venkat102
4856a9633e fix: make free qty round on large transaction qty
(cherry picked from commit f9b8165385)
2024-11-22 10:20:56 +00:00
venkat102
a4398626f6 fix: filter with item group only if it is mentioned in pos profile
(cherry picked from commit 09641073e3)
2024-11-22 10:15:50 +00:00
Frappe PR Bot
17e00b397f chore(release): Bumped to Version 15.43.3
## [15.43.3](https://github.com/frappe/erpnext/compare/v15.43.2...v15.43.3) (2024-11-22)

### Bug Fixes

* patch ([#44191](https://github.com/frappe/erpnext/issues/44191)) ([5f752e2](5f752e29f9))
2024-11-22 09:19:30 +00:00
rohitwaghchaure
1261513ab2 Merge pull request #44280 from frappe/mergify/bp/version-15/pr-44275
fix: patch (backport #44191) (backport #44275)
2024-11-22 14:48:13 +05:30
rohitwaghchaure
5f752e29f9 fix: patch (#44191)
(cherry picked from commit 495528a758)
(cherry picked from commit 8b02402f62)
2024-11-22 06:48:01 +00:00
rohitwaghchaure
c0e6f3f4df Merge pull request #44275 from frappe/mergify/bp/version-15-hotfix/pr-44191
fix: patch (backport #44191)
2024-11-22 12:17:11 +05:30
Smit Vora
11deff98d9 test: test case for toggling debit and credit if negative
(cherry picked from commit a10e175bc9)
2024-11-22 06:39:56 +00:00
Smit Vora
7f8334f29a fix: toggle debit credit amounts for transaction currency too; minor refactor
(cherry picked from commit 8e759c32c4)
2024-11-22 06:39:56 +00:00
rohitwaghchaure
8b02402f62 fix: patch (#44191)
(cherry picked from commit 495528a758)
2024-11-22 06:23:24 +00:00
Frappe PR Bot
81f1f1f1bb chore(release): Bumped to Version 15.43.2
## [15.43.2](https://github.com/frappe/erpnext/compare/v15.43.1...v15.43.2) (2024-11-22)

### Bug Fixes

* include current invoice amount when tax_on_excess_amount is checked ([52e1551](52e1551c23))
2024-11-22 06:00:44 +00:00
ruthra kumar
16ffee9992 Merge pull request #44273 from frappe/mergify/bp/version-15/pr-44194
fix: include current invoice amount when tax_on_excess_amount is checked (backport #44194)
2024-11-22 11:29:29 +05:30
ruthra kumar
723d10241b Merge pull request #44272 from frappe/mergify/bp/version-15-hotfix/pr-44194
fix: include current invoice amount when tax_on_excess_amount is checked (backport #44194)
2024-11-22 11:25:35 +05:30
venkat102
2d284de426 test: add unit test for tax on excess amount
(cherry picked from commit 4820273595)
2024-11-22 05:38:25 +00:00
venkat102
52e1551c23 fix: include current invoice amount when tax_on_excess_amount is checked
(cherry picked from commit b74f2896cd)
2024-11-22 05:38:25 +00:00
venkat102
08b896fc2c test: add unit test for tax on excess amount
(cherry picked from commit 4820273595)
2024-11-22 05:37:50 +00:00
venkat102
0ffeb9f6ad fix: include current invoice amount when tax_on_excess_amount is checked
(cherry picked from commit b74f2896cd)
2024-11-22 05:37:50 +00:00
Frappe PR Bot
e0060f8ffe chore(release): Bumped to Version 15.43.1
## [15.43.1](https://github.com/frappe/erpnext/compare/v15.43.0...v15.43.1) (2024-11-21)

### Bug Fixes

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

(cherry picked from commit 57293aa18a)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 8b15a965dd)
2024-11-21 09:22:50 +00:00
mergify[bot]
d4f0512a10 fix: added Stock UOM field for RM in work order (backport #44185) (#44237)
* fix: added Stock UOM field for RM in work order (#44185)

fix: added UOM field for RM in work order
(cherry picked from commit cc571aca8f)

# Conflicts:
#	erpnext/manufacturing/doctype/work_order_item/work_order_item.json
#	erpnext/patches.txt

* chore: fix conflicts

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-21 14:52:37 +05:30
mergify[bot]
8b15a965dd fix: no permission to read Doctype (backport #44256) (#44258)
fix: no permission to read Doctype (#44256)

(cherry picked from commit 57293aa18a)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-11-21 14:51:33 +05:30
Frappe PR Bot
ccf99cf985 chore(release): Bumped to Version 15.43.0
# [15.43.0](https://github.com/frappe/erpnext/compare/v15.42.0...v15.43.0) (2024-11-20)

### Bug Fixes

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

### Features

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

(cherry picked from commit b21fb8f8b6)

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

* fix: correct linting error

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

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

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

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

(cherry picked from commit 9bf16df41e)

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

(cherry picked from commit 93c8b4c39a)

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

* chore: fix conflicts

---------

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

(cherry picked from commit e8bbf6492f)

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

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

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

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

### Bug Fixes

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

### Features

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

(cherry picked from commit 13834014b5)

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

(cherry picked from commit 0828c74fe3)

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

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

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

(cherry picked from commit c0ffaa444c)

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

(cherry picked from commit e8882718c9)

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

(cherry picked from commit c330a292d2)

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

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

(cherry picked from commit c81eb6c824)

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

(cherry picked from commit 8c99acb1b9)

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

(cherry picked from commit 9a758ea826)

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

(cherry picked from commit 5f5a514d6f)

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

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

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

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

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

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

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

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

* test: fix test `test_single_threshold_tds` for newer implementation

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

* fix: duplicate items and outdated item price in POS

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

(cherry picked from commit 4ea2071265)

Co-authored-by: Nihantra C. Patel <141945075+Nihantra-Patel@users.noreply.github.com>
2024-11-08 13:05:48 +05:30
mergify[bot]
56f25ae065 fix: sort by ascending to get the first period closing voucher (backport #44029) (#44035)
fix: sort by ascending to get the first period closing voucher (#44029)

(cherry picked from commit 42dcdcde1a)

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

(cherry picked from commit adba1168c1)

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

(cherry picked from commit 0399ccc51e)

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

# Conflicts:
#	erpnext/patches.txt
2024-11-08 04:51:12 +00:00
ljain112
58ca4a2b99 fix: improved the conditions for determining voucher subtypes
(cherry picked from commit 00eee16190)
2024-11-08 04:51:11 +00:00
ruthra kumar
ff4751c9e8 refactor: handle PR's in advance stage
(cherry picked from commit 18c13a2cff)
2024-11-07 09:51:10 +00:00
ruthra kumar
eeff0a1252 refactor: cancel old PR and invalidate tokens
(cherry picked from commit cda7800777)
2024-11-07 09:51:10 +00:00
299 changed files with 13825 additions and 1933 deletions

View File

@@ -10,6 +10,7 @@ WEBSITE_REPOS = [
DOCUMENTATION_DOMAINS = [
"docs.erpnext.com",
"docs.frappe.io",
"frappeframework.com",
]

View File

@@ -6,7 +6,7 @@ cd ~ || exit
sudo apt update
sudo apt remove mysql-server mysql-client
sudo apt install libcups2-dev redis-server mariadb-client-10.6
sudo apt install libcups2-dev redis-server mariadb-client
pip install frappe-bench
@@ -44,13 +44,9 @@ fi
install_whktml() {
if [ "$(lsb_release -rs)" = "22.04" ]; then
wget -O /tmp/wkhtmltox.deb https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-2/wkhtmltox_0.12.6.1-2.jammy_amd64.deb
sudo apt install /tmp/wkhtmltox.deb
else
echo "Please update this script to support wkhtmltopdf for $(lsb_release -ds)"
exit 1
fi
wget -O /tmp/wkhtmltox.deb https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-2/wkhtmltox_0.12.6.1-2.jammy_amd64.deb
sudo apt install /tmp/wkhtmltox.deb
}
install_whktml &
wkpid=$!

View File

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

View File

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

View File

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

View File

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

View File

@@ -237,19 +237,22 @@ frappe.treeview_settings["Account"] = {
},
post_render: function (treeview) {
frappe.treeview_settings["Account"].treeview["tree"] = treeview.tree;
treeview.page.set_primary_action(
__("New"),
function () {
let root_company = treeview.page.fields_dict.root_company.get_value();
if (root_company) {
frappe.throw(__("Please add the account to root level Company - {0}"), [root_company]);
} else {
treeview.new_node();
}
},
"add"
);
if (treeview.can_create) {
treeview.page.set_primary_action(
__("New"),
function () {
let root_company = treeview.page.fields_dict.root_company.get_value();
if (root_company) {
frappe.throw(__("Please add the account to root level Company - {0}"), [
root_company,
]);
} else {
treeview.new_node();
}
},
"add"
);
}
},
toolbar: [
{

View File

@@ -101,7 +101,7 @@
"fieldname": "rate",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Rate",
"label": "Tax Rate",
"oldfieldname": "rate",
"oldfieldtype": "Currency"
},

View File

@@ -48,7 +48,7 @@ class BankAccount(Document):
self.name = self.account_name + " - " + self.bank
def on_trash(self):
delete_contact_and_address("BankAccount", self.name)
delete_contact_and_address("Bank Account", self.name)
def validate(self):
self.validate_company()

View File

@@ -117,9 +117,9 @@ class BankClearance(Document):
)
else:
frappe.db.set_value(
d.payment_document, d.payment_entry, "clearance_date", d.clearance_date
)
# using db_set to trigger notification
payment_entry = frappe.get_doc(d.payment_document, d.payment_entry)
payment_entry.db_set("clearance_date", d.clearance_date)
clearance_date_updated = True

View File

@@ -12,6 +12,7 @@ from frappe.utils import cint, flt
from erpnext import get_default_cost_center
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount
from erpnext.accounts.party import get_party_account
from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_statement import (
get_amounts_not_reflected_in_system,
get_entries,
@@ -304,54 +305,56 @@ def create_payment_entry_bts(
bank_transaction = frappe.db.get_values(
"Bank Transaction",
bank_transaction_name,
fieldname=["name", "unallocated_amount", "deposit", "bank_account"],
fieldname=["name", "unallocated_amount", "deposit", "bank_account", "currency"],
as_dict=True,
)[0]
paid_amount = bank_transaction.unallocated_amount
payment_type = "Receive" if bank_transaction.deposit > 0.0 else "Pay"
company_account = frappe.get_value("Bank Account", bank_transaction.bank_account, "account")
company = frappe.get_value("Account", company_account, "company")
payment_entry_dict = {
"company": company,
"payment_type": payment_type,
"reference_no": reference_number,
"reference_date": reference_date,
"party_type": party_type,
"party": party,
"posting_date": posting_date,
"paid_amount": paid_amount,
"received_amount": paid_amount,
}
payment_entry = frappe.new_doc("Payment Entry")
bank_account = frappe.get_cached_value("Bank Account", bank_transaction.bank_account, "account")
company = frappe.get_cached_value("Account", bank_account, "company")
party_account = get_party_account(party_type, party, company)
payment_entry.update(payment_entry_dict)
bank_currency = bank_transaction.currency
party_currency = frappe.get_cached_value("Account", party_account, "account_currency")
if mode_of_payment:
payment_entry.mode_of_payment = mode_of_payment
if project:
payment_entry.project = project
if cost_center:
payment_entry.cost_center = cost_center
if payment_type == "Receive":
payment_entry.paid_to = company_account
else:
payment_entry.paid_from = company_account
exc_rate = get_exchange_rate(bank_currency, party_currency, posting_date)
payment_entry.validate()
amt_in_bank_acc_currency = bank_transaction.unallocated_amount
amount_in_party_currency = bank_transaction.unallocated_amount * exc_rate
pe = frappe.new_doc("Payment Entry")
pe.payment_type = payment_type
pe.company = company
pe.reference_no = reference_number
pe.reference_date = reference_date
pe.party_type = party_type
pe.party = party
pe.posting_date = posting_date
pe.paid_from = party_account if payment_type == "Receive" else bank_account
pe.paid_to = party_account if payment_type == "Pay" else bank_account
pe.paid_from_account_currency = party_currency if payment_type == "Receive" else bank_currency
pe.paid_to_account_currency = party_currency if payment_type == "Pay" else bank_currency
pe.paid_amount = amount_in_party_currency if payment_type == "Receive" else amt_in_bank_acc_currency
pe.received_amount = amount_in_party_currency if payment_type == "Pay" else amt_in_bank_acc_currency
pe.mode_of_payment = mode_of_payment
pe.project = project
pe.cost_center = cost_center
pe.validate()
if allow_edit:
return payment_entry
return pe
payment_entry.insert()
pe.insert()
pe.submit()
payment_entry.submit()
vouchers = json.dumps(
[
{
"payment_doctype": "Payment Entry",
"payment_name": payment_entry.name,
"amount": paid_amount,
"payment_name": pe.name,
"amount": amt_in_bank_acc_currency,
}
]
)
@@ -480,8 +483,12 @@ def get_linked_payments(
def subtract_allocations(gl_account, vouchers):
"Look up & subtract any existing Bank Transaction allocations"
copied = []
voucher_docs = [(voucher.get("doctype"), voucher.get("name")) for voucher in vouchers]
voucher_allocated_amounts = get_total_allocated_amount(voucher_docs)
for voucher in vouchers:
rows = get_total_allocated_amount(voucher.get("doctype"), voucher.get("name"))
rows = voucher_allocated_amounts.get((voucher.get("doctype"), voucher.get("name"))) or []
filtered_row = list(filter(lambda row: row.get("gl_account") == gl_account, rows))
if amount := None if not filtered_row else filtered_row[0]["total"]:
@@ -719,7 +726,7 @@ def get_pe_matching_query(
(ref_rank + amount_rank + party_rank + 1).as_("rank"),
ConstantColumn("Payment Entry").as_("doctype"),
pe.name,
pe.paid_amount_after_tax.as_("paid_amount"),
pe.base_paid_amount_after_tax.as_("paid_amount"),
pe.reference_no,
pe.reference_date,
pe.party,

View File

@@ -49,41 +49,39 @@ class AutoMatchbyAccountIBAN:
return result
def match_account_in_party(self) -> tuple | None:
"""Check if there is a IBAN/Account No. match in Customer/Supplier/Employee"""
result = None
parties = get_parties_in_order(self.deposit)
or_filters = self.get_or_filters()
"""
Returns (Party Type, Party) if a matching account is found in Bank Account or Employee:
1. Get party from a matching (iban/account no) Bank Account
2. If not found, get party from Employee with matching bank account details (iban/account no)
"""
if not (self.bank_party_account_number or self.bank_party_iban):
# Nothing to match
return None
for party in parties:
party_result = frappe.db.get_all(
"Bank Account", or_filters=or_filters, pluck="party", limit_page_length=1
)
# Search for a matching Bank Account that has party set
party_result = frappe.db.get_all(
"Bank Account",
or_filters=self.get_or_filters(),
filters={"party_type": ("is", "set"), "party": ("is", "set")},
fields=["party", "party_type"],
limit_page_length=1,
)
if result := party_result[0] if party_result else None:
return (result["party_type"], result["party"])
if party == "Employee" and not party_result:
# Search in Bank Accounts first for Employee, and then Employee record
if "bank_account_no" in or_filters:
or_filters["bank_ac_no"] = or_filters.pop("bank_account_no")
# If no party is found, search in Employee (since it has bank account details)
employee_result = frappe.db.get_all(
"Employee", or_filters=self.get_or_filters("Employee"), pluck="name", limit_page_length=1
)
if employee_result:
return ("Employee", employee_result[0])
party_result = frappe.db.get_all(
party, or_filters=or_filters, pluck="name", limit_page_length=1
)
if "bank_ac_no" in or_filters:
or_filters["bank_account_no"] = or_filters.pop("bank_ac_no")
if party_result:
result = (
party,
party_result[0],
)
break
return result
def get_or_filters(self) -> dict:
def get_or_filters(self, party: str | None = None) -> dict:
"""Return OR filters for Bank Account and IBAN"""
or_filters = {}
if self.bank_party_account_number:
or_filters["bank_account_no"] = self.bank_party_account_number
bank_ac_field = "bank_ac_no" if party == "Employee" else "bank_account_no"
or_filters[bank_ac_field] = self.bank_party_account_number
if self.bank_party_iban:
or_filters["iban"] = self.bank_party_iban

View File

@@ -154,10 +154,16 @@ class BankTransaction(Document):
"""
remaining_amount = self.unallocated_amount
to_remove = []
payment_entry_docs = [(pe.payment_document, pe.payment_entry) for pe in self.payment_entries]
pe_bt_allocations = get_total_allocated_amount(payment_entry_docs)
for payment_entry in self.payment_entries:
if payment_entry.allocated_amount == 0.0:
unallocated_amount, should_clear, latest_transaction = get_clearance_details(
self, payment_entry
self,
payment_entry,
pe_bt_allocations.get((payment_entry.payment_document, payment_entry.payment_entry))
or [],
)
if 0.0 == unallocated_amount:
@@ -208,13 +214,17 @@ class BankTransaction(Document):
if self.party_type and self.party:
return
result = AutoMatchParty(
bank_party_account_number=self.bank_party_account_number,
bank_party_iban=self.bank_party_iban,
bank_party_name=self.bank_party_name,
description=self.description,
deposit=self.deposit,
).match()
result = None
try:
result = AutoMatchParty(
bank_party_account_number=self.bank_party_account_number,
bank_party_iban=self.bank_party_iban,
bank_party_name=self.bank_party_name,
description=self.description,
deposit=self.deposit,
).match()
except Exception:
frappe.log_error(title=_("Error in party matching for Bank Transaction {0}").format(self.name))
if not result:
return
@@ -228,7 +238,7 @@ def get_doctypes_for_bank_reconciliation():
return frappe.get_hooks("bank_reconciliation_doctypes")
def get_clearance_details(transaction, payment_entry):
def get_clearance_details(transaction, payment_entry, bt_allocations):
"""
There should only be one bank gle for a voucher.
Could be none for a Bank Transaction.
@@ -237,7 +247,6 @@ def get_clearance_details(transaction, payment_entry):
"""
gl_bank_account = frappe.db.get_value("Bank Account", transaction.bank_account, "account")
gles = get_related_bank_gl_entries(payment_entry.payment_document, payment_entry.payment_entry)
bt_allocations = get_total_allocated_amount(payment_entry.payment_document, payment_entry.payment_entry)
unallocated_amount = min(
transaction.unallocated_amount,
@@ -290,44 +299,52 @@ def get_related_bank_gl_entries(doctype, docname):
)
def get_total_allocated_amount(doctype, docname):
def get_total_allocated_amount(docs):
"""
Gets the sum of allocations for a voucher on each bank GL account
along with the latest bank transaction name & date
NOTE: query may also include just saved vouchers/payments but with zero allocated_amount
"""
if not docs:
return {}
# nosemgrep: frappe-semgrep-rules.rules.frappe-using-db-sql
result = frappe.db.sql(
"""
SELECT total, latest_name, latest_date, gl_account FROM (
SELECT total, latest_name, latest_date, gl_account, payment_document, payment_entry FROM (
SELECT
ROW_NUMBER() OVER w AS rownum,
SUM(btp.allocated_amount) OVER(PARTITION BY ba.account) AS total,
SUM(btp.allocated_amount) OVER(PARTITION BY ba.account, btp.payment_document, btp.payment_entry) AS total,
FIRST_VALUE(bt.name) OVER w AS latest_name,
FIRST_VALUE(bt.date) OVER w AS latest_date,
ba.account AS gl_account
ba.account AS gl_account,
btp.payment_document,
btp.payment_entry
FROM
`tabBank Transaction Payments` btp
LEFT JOIN `tabBank Transaction` bt ON bt.name=btp.parent
LEFT JOIN `tabBank Account` ba ON ba.name=bt.bank_account
WHERE
btp.payment_document = %(doctype)s
AND btp.payment_entry = %(docname)s
(btp.payment_document, btp.payment_entry) IN %(docs)s
AND bt.docstatus = 1
WINDOW w AS (PARTITION BY ba.account ORDER BY bt.date desc)
WINDOW w AS (PARTITION BY ba.account, btp.payment_document, btp.payment_entry ORDER BY bt.date DESC)
) temp
WHERE
rownum = 1
""",
dict(doctype=doctype, docname=docname),
dict(docs=docs),
as_dict=True,
)
payment_allocation_details = {}
for row in result:
# Why is this *sometimes* a byte string?
if isinstance(row["latest_name"], bytes):
row["latest_name"] = row["latest_name"].decode()
row["latest_date"] = frappe.utils.getdate(row["latest_date"])
return result
payment_allocation_details.setdefault((row["payment_document"], row["payment_entry"]), []).append(row)
return payment_allocation_details
def get_paid_amount(payment_entry, currency, gl_bank_account):

View File

@@ -490,13 +490,20 @@ def get_actual_expense(args):
def get_accumulated_monthly_budget(monthly_distribution, posting_date, fiscal_year, annual_budget):
distribution = {}
if monthly_distribution:
for d in frappe.db.sql(
"""select mdp.month, mdp.percentage_allocation
from `tabMonthly Distribution Percentage` mdp, `tabMonthly Distribution` md
where mdp.parent=md.name and md.fiscal_year=%s""",
fiscal_year,
as_dict=1,
):
mdp = frappe.qb.DocType("Monthly Distribution Percentage")
md = frappe.qb.DocType("Monthly Distribution")
res = (
frappe.qb.from_(mdp)
.join(md)
.on(mdp.parent == md.name)
.select(mdp.month, mdp.percentage_allocation)
.where(md.fiscal_year == fiscal_year)
.where(md.name == monthly_distribution)
.run(as_dict=True)
)
for d in res:
distribution.setdefault(d.month, d.percentage_allocation)
dt = frappe.get_cached_value("Fiscal Year", fiscal_year, "year_start_date")

View File

@@ -19,16 +19,6 @@
"currency",
"column_break_11",
"conversion_rate",
"address_and_contact_section",
"customer_address",
"address_display",
"contact_person",
"contact_display",
"column_break_16",
"company_address",
"company_address_display",
"contact_mobile",
"contact_email",
"section_break_6",
"dunning_type",
"column_break_8",
@@ -56,7 +46,21 @@
"income_account",
"column_break_48",
"cost_center",
"amended_from"
"amended_from",
"address_and_contact_tab",
"address_and_contact_section",
"customer_address",
"address_display",
"column_break_vodj",
"contact_person",
"contact_display",
"contact_mobile",
"contact_email",
"section_break_xban",
"column_break_16",
"company_address",
"company_address_display",
"column_break_lqmf"
],
"fields": [
{
@@ -178,10 +182,8 @@
"label": "Rate of Interest (%) Yearly"
},
{
"collapsible": 1,
"fieldname": "address_and_contact_section",
"fieldtype": "Section Break",
"label": "Address and Contact"
"fieldtype": "Section Break"
},
{
"fieldname": "address_display",
@@ -377,11 +379,28 @@
{
"fieldname": "column_break_48",
"fieldtype": "Column Break"
},
{
"fieldname": "address_and_contact_tab",
"fieldtype": "Tab Break",
"label": "Address & Contact"
},
{
"fieldname": "column_break_vodj",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_xban",
"fieldtype": "Section Break"
},
{
"fieldname": "column_break_lqmf",
"fieldtype": "Column Break"
}
],
"is_submittable": 1,
"links": [],
"modified": "2023-06-15 15:46:53.865712",
"modified": "2024-11-26 13:46:07.760867",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Dunning",
@@ -435,4 +454,4 @@
"states": [],
"title_field": "customer_name",
"track_changes": 1
}
}

View File

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

View File

@@ -188,7 +188,7 @@ class TestExchangeRateRevaluation(AccountsTestMixin, FrappeTestCase):
pe = get_payment_entry(si.doctype, si.name)
pe.paid_amount = 95
pe.source_exchange_rate = 84.211
pe.source_exchange_rate = 84.2105
pe.received_amount = 8000
pe.references = []
pe.save().submit()
@@ -229,7 +229,7 @@ class TestExchangeRateRevaluation(AccountsTestMixin, FrappeTestCase):
row = next(x for x in je.accounts if x.account == self.debtors_usd)
self.assertEqual(flt(row.credit_in_account_currency, precision), 5.0) # in USD
row = next(x for x in je.accounts if x.account != self.debtors_usd)
self.assertEqual(flt(row.debit_in_account_currency, precision), 421.06) # in INR
self.assertEqual(flt(row.debit_in_account_currency, precision), 421.05) # in INR
# total_debit and total_credit will be 0.0, as JV is posting only to account currency fields
self.assertEqual(flt(je.total_debit, precision), 0.0)

View File

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

View File

@@ -13,7 +13,11 @@ import erpnext
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_checks_for_pl_and_bs_accounts,
)
from erpnext.accounts.party import validate_party_frozen_disabled, validate_party_gle_currency
from erpnext.accounts.party import (
validate_account_party_type,
validate_party_frozen_disabled,
validate_party_gle_currency,
)
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
from erpnext.exceptions import InvalidAccountCurrency
@@ -268,8 +272,12 @@ class GLEntry(Document):
def validate_party(self):
validate_party_frozen_disabled(self.party_type, self.party)
validate_account_party_type(self)
def validate_currency(self):
if self.is_cancelled:
return
company_currency = erpnext.get_company_currency(self.company)
account_currency = get_account_currency(self.account)

View File

@@ -79,3 +79,48 @@ class TestGLEntry(unittest.TestCase):
"SELECT current from tabSeries where name = %s", naming_series
)[0][0]
self.assertEqual(old_naming_series_current_value + 2, new_naming_series_current_value)
def test_validate_account_party_type(self):
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC",
100,
"_Test Cost Center - _TC",
save=False,
submit=False,
)
for row in jv.accounts:
row.party_type = "Supplier"
break
jv.save()
try:
jv.submit()
except Exception as e:
self.assertEqual(
str(e),
"Party Type and Party can only be set for Receivable / Payable account_Test Account Cost for Goods Sold - _TC",
)
jv1 = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC",
100,
"_Test Cost Center - _TC",
save=False,
submit=False,
)
for row in jv.accounts:
row.party_type = "Customer"
break
jv1.save()
try:
jv1.submit()
except Exception as e:
self.assertEqual(
str(e),
"Party Type and Party can only be set for Receivable / Payable account_Test Account Cost for Goods Sold - _TC",
)

View File

@@ -127,9 +127,6 @@ class JournalEntry(AccountsController):
self.set_amounts_in_company_currency()
self.validate_debit_credit_amount()
self.set_total_debit_credit()
# Do not validate while importing via data import
if not frappe.flags.in_import:
self.validate_total_debit_and_credit()
if not frappe.flags.is_reverse_depr_entry:
self.validate_against_jv()
@@ -184,6 +181,11 @@ class JournalEntry(AccountsController):
else:
return self._cancel()
def before_submit(self):
# Do not validate while importing via data import
if not frappe.flags.in_import:
self.validate_total_debit_and_credit()
def on_submit(self):
self.validate_cheque_info()
self.check_credit_limit()

View File

@@ -515,6 +515,55 @@ class TestJournalEntry(unittest.TestCase):
self.assertEqual(row.debit_in_account_currency, 100)
self.assertEqual(row.credit_in_account_currency, 100)
def test_toggle_debit_credit_if_negative(self):
from erpnext.accounts.general_ledger import process_gl_map
# Create JV with defaut cost center - _Test Cost Center
frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0)
jv = frappe.new_doc("Journal Entry")
jv.posting_date = nowdate()
jv.company = "_Test Company"
jv.user_remark = "test"
jv.extend(
"accounts",
[
{
"account": "_Test Cash - _TC",
"debit": 100 * -1,
"debit_in_account_currency": 100 * -1,
"exchange_rate": 1,
},
{
"account": "_Test Bank - _TC",
"credit": 100 * -1,
"credit_in_account_currency": 100 * -1,
"exchange_rate": 1,
},
],
)
jv.flags.ignore_validate = True
jv.save()
self.assertEqual(len(jv.accounts), 2)
gl_map = jv.build_gl_map()
for row in gl_map:
if row.account == "_Test Cash - _TC":
self.assertEqual(row.debit, 100 * -1)
self.assertEqual(row.debit_in_account_currency, 100 * -1)
self.assertEqual(row.debit_in_transaction_currency, 100 * -1)
gl_map = process_gl_map(gl_map, False)
for row in gl_map:
if row.account == "_Test Cash - _TC":
self.assertEqual(row.credit, 100)
self.assertEqual(row.credit_in_account_currency, 100)
self.assertEqual(row.credit_in_transaction_currency, 100)
def test_transaction_exchange_rate_on_journals(self):
jv = make_journal_entry("_Test Bank - _TC", "_Test Receivable USD - _TC", 100, save=False)
jv.accounts[0].update({"debit_in_account_currency": 8500, "exchange_rate": 1})

View File

@@ -26,6 +26,22 @@ frappe.ui.form.on("Payment Entry", {
}
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
// project excluded in setup_dimension_filters
frm.set_query("project", function (doc) {
let filters = {
company: doc.company,
};
if (doc.party_type == "Customer") filters.customer = doc.party;
return {
query: "erpnext.controllers.queries.get_project_name",
filters,
};
});
if (frm.is_new()) {
set_default_party_type(frm);
}
},
setup: function (frm) {
@@ -181,6 +197,10 @@ frappe.ui.form.on("Payment Entry", {
filters: {
reference_doctype: row.reference_doctype,
reference_name: row.reference_name,
company: doc.company,
status: ["!=", "Paid"],
outstanding_amount: [">", 0], // for compatibility with old data
docstatus: 1,
},
};
});
@@ -316,11 +336,6 @@ frappe.ui.form.on("Payment Entry", {
"write_off_difference_amount",
frm.doc.difference_amount && frm.doc.party && frm.doc.total_allocated_amount > party_amount
);
frm.toggle_display(
"set_exchange_gain_loss",
frm.doc.paid_amount && frm.doc.received_amount && frm.doc.difference_amount
);
},
set_dynamic_labels: function (frm) {
@@ -403,6 +418,8 @@ frappe.ui.form.on("Payment Entry", {
},
payment_type: function (frm) {
set_default_party_type(frm);
if (frm.doc.payment_type == "Internal Transfer") {
$.each(
[
@@ -1109,36 +1126,34 @@ frappe.ui.form.on("Payment Entry", {
},
set_unallocated_amount: function (frm) {
var unallocated_amount = 0;
var total_deductions = frappe.utils.sum(
$.map(frm.doc.deductions || [], function (d) {
return flt(d.amount);
})
);
let unallocated_amount = 0;
let deductions_to_consider = 0;
for (const row of frm.doc.deductions || []) {
if (!row.is_exchange_gain_loss) deductions_to_consider += flt(row.amount);
}
const included_taxes = get_included_taxes(frm);
if (frm.doc.party) {
if (
frm.doc.payment_type == "Receive" &&
frm.doc.base_total_allocated_amount < frm.doc.base_received_amount + total_deductions &&
frm.doc.total_allocated_amount <
frm.doc.paid_amount + total_deductions / frm.doc.source_exchange_rate
) {
unallocated_amount =
(frm.doc.base_received_amount +
total_deductions -
flt(frm.doc.base_total_taxes_and_charges) -
frm.doc.base_total_allocated_amount) /
frm.doc.source_exchange_rate;
} else if (
frm.doc.payment_type == "Pay" &&
frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount - total_deductions &&
frm.doc.total_allocated_amount <
frm.doc.received_amount + total_deductions / frm.doc.target_exchange_rate
frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount + deductions_to_consider
) {
unallocated_amount =
(frm.doc.base_paid_amount +
flt(frm.doc.base_total_taxes_and_charges) -
(total_deductions + frm.doc.base_total_allocated_amount)) /
deductions_to_consider -
frm.doc.base_total_allocated_amount -
included_taxes) /
frm.doc.source_exchange_rate;
} else if (
frm.doc.payment_type == "Pay" &&
frm.doc.base_total_allocated_amount < frm.doc.base_received_amount - deductions_to_consider
) {
unallocated_amount =
(frm.doc.base_received_amount -
deductions_to_consider -
frm.doc.base_total_allocated_amount -
included_taxes) /
frm.doc.target_exchange_rate;
}
}
@@ -1232,77 +1247,85 @@ frappe.ui.form.on("Payment Entry", {
},
write_off_difference_amount: function (frm) {
frm.events.set_deductions_entry(frm, "write_off_account");
frm.events.set_write_off_deduction(frm);
},
set_exchange_gain_loss: function (frm) {
frm.events.set_deductions_entry(frm, "exchange_gain_loss_account");
base_paid_amount: function (frm) {
frm.events.set_exchange_gain_loss_deduction(frm);
},
set_deductions_entry: function (frm, account) {
if (frm.doc.difference_amount) {
frappe.call({
method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_company_defaults",
args: {
company: frm.doc.company,
},
callback: function (r, rt) {
if (r.message) {
const write_off_row = $.map(frm.doc["deductions"] || [], function (t) {
return t.account == r.message[account] ? t : null;
});
base_received_amount: function (frm) {
frm.events.set_exchange_gain_loss_deduction(frm);
},
const difference_amount = flt(
frm.doc.difference_amount,
precision("difference_amount")
);
set_exchange_gain_loss_deduction: async function (frm) {
// wait for allocate_party_amount_against_ref_docs to finish
await frappe.after_ajax();
const base_paid_amount = frm.doc.base_paid_amount || 0;
const base_received_amount = frm.doc.base_received_amount || 0;
const exchange_gain_loss = flt(
base_paid_amount - base_received_amount,
get_deduction_amount_precision()
);
const add_deductions = (details) => {
let row = null;
if (!write_off_row.length && difference_amount) {
row = frm.add_child("deductions");
row.account = details[account];
row.cost_center = details["cost_center"];
} else {
row = write_off_row[0];
}
if (row) {
row.amount = flt(row.amount) + difference_amount;
} else {
frappe.msgprint(__("No gain or loss in the exchange rate"));
}
refresh_field("deductions");
};
if (!r.message[account]) {
frappe.prompt(
{
label: __("Please Specify Account"),
fieldname: account,
fieldtype: "Link",
options: "Account",
get_query: () => ({
filters: {
company: frm.doc.company,
},
}),
},
(values) => {
const details = Object.assign({}, r.message, values);
add_deductions(details);
},
__(frappe.unscrub(account))
);
} else {
add_deductions(r.message);
}
frm.events.set_unallocated_amount(frm);
}
},
});
if (!exchange_gain_loss) {
frm.events.delete_exchange_gain_loss(frm);
return;
}
const account_fieldname = "exchange_gain_loss_account";
let row = (frm.doc.deductions || []).find((t) => t.is_exchange_gain_loss);
if (!row) {
const response = await get_company_defaults(frm.doc.company);
const account =
response.message?.[account_fieldname] ||
(await prompt_for_missing_account(frm, account_fieldname));
row = frm.add_child("deductions");
row.account = account;
row.cost_center = response.message?.cost_center;
row.is_exchange_gain_loss = 1;
}
row.amount = exchange_gain_loss;
frm.refresh_field("deductions");
frm.events.set_unallocated_amount(frm);
},
delete_exchange_gain_loss: function (frm) {
const exchange_gain_loss_row = (frm.doc.deductions || []).find((row) => row.is_exchange_gain_loss);
if (!exchange_gain_loss_row) return;
exchange_gain_loss_row.amount = 0;
frm.get_field("deductions").grid.grid_rows[exchange_gain_loss_row.idx - 1].remove();
frm.refresh_field("deductions");
},
set_write_off_deduction: async function (frm) {
const difference_amount = flt(frm.doc.difference_amount, get_deduction_amount_precision());
if (!difference_amount) return;
const account_fieldname = "write_off_account";
const response = await get_company_defaults(frm.doc.company);
const write_off_account =
response.message?.[account_fieldname] ||
(await prompt_for_missing_account(frm, account_fieldname));
if (!write_off_account) return;
let row = (frm.doc["deductions"] || []).find((t) => t.account == write_off_account);
if (!row) {
row = frm.add_child("deductions");
row.account = write_off_account;
row.cost_center = response.message?.cost_center;
}
row.amount = flt(row.amount) + difference_amount;
frm.refresh_field("deductions");
frm.events.set_unallocated_amount(frm);
},
bank_account: function (frm) {
@@ -1317,6 +1340,24 @@ frappe.ui.form.on("Payment Entry", {
if (r.message) {
if (!frm.doc.mode_of_payment) {
frm.set_value(field, r.message.account);
} else {
frappe.call({
method: "frappe.client.get_value",
args: {
doctype: "Mode of Payment Account",
filters: {
parent: frm.doc.mode_of_payment,
company: frm.doc.company,
},
fieldname: "default_account",
parent: "Mode of Payment",
},
callback: function (res) {
if (!res.message.default_account) {
frm.set_value(field, r.message.account);
}
},
});
}
frm.set_value("bank", r.message.bank);
frm.set_value("bank_account_no", r.message.bank_account_no);
@@ -1768,6 +1809,13 @@ frappe.ui.form.on("Advance Taxes and Charges", {
});
frappe.ui.form.on("Payment Entry Deduction", {
before_deductions_remove: function (doc, cdt, cdn) {
const row = frappe.get_doc(cdt, cdn);
if (row.is_exchange_gain_loss && row.amount) {
frappe.throw(__("Cannot delete Exchange Gain/Loss row"));
}
},
amount: function (frm) {
frm.events.set_unallocated_amount(frm);
},
@@ -1776,3 +1824,66 @@ frappe.ui.form.on("Payment Entry Deduction", {
frm.events.set_unallocated_amount(frm);
},
});
function set_default_party_type(frm) {
if (frm.doc.party) return;
let party_type;
if (frm.doc.payment_type == "Receive") {
party_type = "Customer";
} else if (frm.doc.payment_type == "Pay") {
party_type = "Supplier";
}
if (party_type) frm.set_value("party_type", party_type);
}
function get_included_taxes(frm) {
let included_taxes = 0;
for (const tax of frm.doc.taxes) {
if (!tax.included_in_paid_amount) continue;
if (tax.add_deduct_tax == "Add") {
included_taxes += tax.base_tax_amount;
} else {
included_taxes -= tax.base_tax_amount;
}
}
return included_taxes;
}
function get_company_defaults(company) {
return frappe.call({
method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_company_defaults",
args: {
company: company,
},
});
}
function prompt_for_missing_account(frm, account) {
return new Promise((resolve) => {
const dialog = frappe.prompt(
{
label: __(frappe.unscrub(account)),
fieldname: account,
fieldtype: "Link",
options: "Account",
get_query: () => ({
filters: {
company: frm.doc.company,
},
}),
},
(values) => resolve(values?.[account]),
__("Please Specify Account")
);
dialog.on_hide = () => resolve("");
});
}
function get_deduction_amount_precision() {
return frappe.meta.get_field_precision(frappe.meta.get_field("Payment Entry Deduction", "amount"));
}

View File

@@ -56,7 +56,6 @@
"section_break_34",
"total_allocated_amount",
"base_total_allocated_amount",
"set_exchange_gain_loss",
"column_break_36",
"unallocated_amount",
"difference_amount",
@@ -390,11 +389,6 @@
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "set_exchange_gain_loss",
"fieldtype": "Button",
"label": "Set Exchange Gain / Loss"
},
{
"fieldname": "column_break_36",
"fieldtype": "Column Break"
@@ -801,7 +795,7 @@
"table_fieldname": "payment_entries"
}
],
"modified": "2024-05-31 17:07:06.197249",
"modified": "2024-11-07 11:19:19.320883",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",

View File

@@ -893,6 +893,7 @@ class PaymentEntry(AccountsController):
self.set_amounts_in_company_currency()
self.set_total_allocated_amount()
self.set_unallocated_amount()
self.set_exchange_gain_loss()
self.set_difference_amount()
def validate_amounts(self):
@@ -988,10 +989,10 @@ class PaymentEntry(AccountsController):
if d.exchange_rate is None:
d.exchange_rate = 1
allocated_amount_in_pe_exchange_rate = flt(
allocated_amount_in_ref_exchange_rate = flt(
flt(d.allocated_amount) * flt(d.exchange_rate), self.precision("base_paid_amount")
)
d.exchange_gain_loss = base_allocated_amount - allocated_amount_in_pe_exchange_rate
d.exchange_gain_loss = base_allocated_amount - allocated_amount_in_ref_exchange_rate
return base_allocated_amount
def set_total_allocated_amount(self):
@@ -1009,29 +1010,80 @@ class PaymentEntry(AccountsController):
def set_unallocated_amount(self):
self.unallocated_amount = 0
if self.party:
total_deductions = sum(flt(d.amount) for d in self.get("deductions"))
included_taxes = self.get_included_taxes()
if (
self.payment_type == "Receive"
and self.base_total_allocated_amount < self.base_received_amount + total_deductions
and self.total_allocated_amount
< flt(self.paid_amount) + (total_deductions / self.source_exchange_rate)
):
self.unallocated_amount = (
self.base_received_amount + total_deductions - self.base_total_allocated_amount
) / self.source_exchange_rate
self.unallocated_amount -= included_taxes
elif (
self.payment_type == "Pay"
and self.base_total_allocated_amount < (self.base_paid_amount - total_deductions)
and self.total_allocated_amount
< flt(self.received_amount) + (total_deductions / self.target_exchange_rate)
):
self.unallocated_amount = (
self.base_paid_amount - (total_deductions + self.base_total_allocated_amount)
) / self.target_exchange_rate
self.unallocated_amount -= included_taxes
if not self.party:
return
deductions_to_consider = sum(
flt(d.amount) for d in self.get("deductions") if not d.is_exchange_gain_loss
)
included_taxes = self.get_included_taxes()
if self.payment_type == "Receive" and self.base_total_allocated_amount < (
self.base_paid_amount + deductions_to_consider
):
self.unallocated_amount = (
self.base_paid_amount
+ deductions_to_consider
- self.base_total_allocated_amount
- included_taxes
) / self.source_exchange_rate
elif self.payment_type == "Pay" and self.base_total_allocated_amount < (
self.base_received_amount - deductions_to_consider
):
self.unallocated_amount = (
self.base_received_amount
- deductions_to_consider
- self.base_total_allocated_amount
- included_taxes
) / self.target_exchange_rate
def set_exchange_gain_loss(self):
exchange_gain_loss = flt(
self.base_paid_amount - self.base_received_amount,
self.precision("amount", "deductions"),
)
exchange_gain_loss_rows = [row for row in self.get("deductions") if row.is_exchange_gain_loss]
exchange_gain_loss_row = exchange_gain_loss_rows.pop(0) if exchange_gain_loss_rows else None
for row in exchange_gain_loss_rows:
self.remove(row)
if not exchange_gain_loss:
if exchange_gain_loss_row:
self.remove(exchange_gain_loss_row)
return
if not exchange_gain_loss_row:
values = frappe.get_cached_value(
"Company", self.company, ("exchange_gain_loss_account", "cost_center"), as_dict=True
)
for fieldname, value in values.items():
if value:
continue
label = _(frappe.get_meta("Company").get_label(fieldname))
return frappe.msgprint(
_("Please set {0} in Company {1} to account for Exchange Gain / Loss").format(
label, get_link_to_form("Company", self.company)
),
title=_("Missing Default in Company"),
indicator="red" if self.docstatus.is_submitted() else "yellow",
raise_exception=self.docstatus.is_submitted(),
)
exchange_gain_loss_row = self.append(
"deductions",
{
"account": values.exchange_gain_loss_account,
"cost_center": values.cost_center,
"is_exchange_gain_loss": 1,
},
)
exchange_gain_loss_row.amount = exchange_gain_loss
def set_difference_amount(self):
base_unallocated_amount = flt(self.unallocated_amount) * (
@@ -1059,11 +1111,13 @@ class PaymentEntry(AccountsController):
def get_included_taxes(self):
included_taxes = 0
for tax in self.get("taxes"):
if tax.included_in_paid_amount:
if tax.add_deduct_tax == "Add":
included_taxes += tax.base_tax_amount
else:
included_taxes -= tax.base_tax_amount
if not tax.included_in_paid_amount:
continue
if tax.add_deduct_tax == "Add":
included_taxes += tax.base_tax_amount
else:
included_taxes -= tax.base_tax_amount
return included_taxes
@@ -1146,6 +1200,12 @@ class PaymentEntry(AccountsController):
if self.payment_type in ("Receive", "Pay") and not self.get("party_account_field"):
self.setup_party_account_field()
company_currency = erpnext.get_company_currency(self.company)
if self.paid_from_account_currency != company_currency:
self.currency = self.paid_from_account_currency
elif self.paid_to_account_currency != company_currency:
self.currency = self.paid_to_account_currency
gl_entries = []
self.add_party_gl_entries(gl_entries)
self.add_bank_gl_entries(gl_entries)
@@ -1213,11 +1273,19 @@ class PaymentEntry(AccountsController):
dr_or_cr = "debit" if dr_or_cr == "credit" else "credit"
gle.update(
{
dr_or_cr: allocated_amount_in_company_currency,
dr_or_cr + "_in_account_currency": d.allocated_amount,
"cost_center": cost_center,
}
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": cost_center,
dr_or_cr + "_in_account_currency": d.allocated_amount,
dr_or_cr: allocated_amount_in_company_currency,
},
item=self,
)
)
if self.book_advance_payments_in_separate_party_account:
@@ -1248,13 +1316,22 @@ class PaymentEntry(AccountsController):
base_unallocated_amount = self.unallocated_amount * exchange_rate
gle = party_gl_dict.copy()
gle.update(
{
dr_or_cr + "_in_account_currency": self.unallocated_amount,
dr_or_cr: base_unallocated_amount,
}
)
gle.update(
self.get_gl_dict(
{
"account": self.party_account,
"party_type": self.party_type,
"party": self.party,
"against": against_account,
"account_currency": self.party_account_currency,
"cost_center": self.cost_center,
dr_or_cr + "_in_account_currency": self.unallocated_amount,
dr_or_cr: base_unallocated_amount,
},
item=self,
)
)
if self.book_advance_payments_in_separate_party_account:
gle.update(
{
@@ -1731,7 +1808,7 @@ class PaymentEntry(AccountsController):
if paid_amount > total_negative_outstanding:
if total_negative_outstanding == 0:
frappe.msgprint(
_("Cannot {0} from {2} without any negative outstanding invoice").format(
_("Cannot {0} from {1} without any negative outstanding invoice").format(
self.payment_type,
self.party_type,
)
@@ -1889,8 +1966,8 @@ class PaymentEntry(AccountsController):
def get_matched_payment_request_of_references(references=None):
"""
Get those `Payment Requests` which are matched with `References`.\n
- Amount must be same.
- Only single `Payment Request` available for this amount.
- Amount must be same.
- Only single `Payment Request` available for this amount.
Example: [(reference_doctype, reference_name, allocated_amount, payment_request), ...]
"""
@@ -1992,7 +2069,7 @@ def get_outstanding_of_references_with_payment_term(references=None):
def get_outstanding_of_references_with_no_payment_term(references):
"""
Fetch outstanding amount of `References` which have no `Payment Term` set.\n
- Fetch outstanding amount from `References` it self.
- Fetch outstanding amount from `References` it self.
Note: `None` is used for allocation of `Payment Request`
Example: {(reference_doctype, reference_name, None): outstanding_amount, ...}
@@ -2806,9 +2883,6 @@ def get_payment_entry(
update_accounting_dimensions(pe, doc)
if party_account and bank:
pe.set_exchange_rate(ref_doc=doc)
pe.set_amounts()
if discount_amount:
base_total_discount_loss = 0
if frappe.db.get_single_value("Accounts Settings", "book_tax_discount_loss"):
@@ -2818,7 +2892,8 @@ def get_payment_entry(
pe, doc, discount_amount, base_total_discount_loss, party_account_currency
)
pe.set_difference_amount()
pe.set_exchange_rate(ref_doc=doc)
pe.set_amounts()
# If PE is created from PR directly, then no need to find open PRs for the references
if not created_from_payment_request:
@@ -2830,7 +2905,7 @@ def get_payment_entry(
def get_open_payment_requests_for_references(references=None):
"""
Fetch all unpaid Payment Requests for the references. \n
- Each reference can have multiple Payment Requests. \n
- Each reference can have multiple Payment Requests. \n
Example: {("Sales Invoice", "SINV-00001"): {"PREQ-00001": 1000, "PREQ-00002": 2000}}
"""
@@ -2854,6 +2929,7 @@ def get_open_payment_requests_for_references(references=None):
.where(Tuple(PR.reference_doctype, PR.reference_name).isin(list(refs)))
.where(PR.status != "Paid")
.where(PR.docstatus == 1)
.where(PR.outstanding_amount > 0) # to avoid old PRs with 0 outstanding amount
.orderby(Coalesce(PR.transaction_date, PR.creation), order=frappe.qb.asc)
).run(as_dict=True)
@@ -3164,13 +3240,14 @@ def set_pending_discount_loss(pe, doc, discount_amount, base_total_discount_loss
book_tax_loss = frappe.db.get_single_value("Accounts Settings", "book_tax_discount_loss")
account_type = "round_off_account" if book_tax_loss else "default_discount_account"
pe.set_gain_or_loss(
account_details={
pe.append(
"deductions",
{
"account": frappe.get_cached_value("Company", pe.company, account_type),
"cost_center": pe.cost_center
or frappe.get_cached_value("Company", pe.company, "cost_center"),
"amount": discount_amount * positive_negative,
}
},
)

View File

@@ -479,16 +479,9 @@ class TestPaymentEntry(FrappeTestCase):
self.assertEqual(pe.deductions[0].account, "Write Off - _TC")
# Exchange loss
self.assertEqual(pe.difference_amount, 300.0)
pe.append(
"deductions",
{
"account": "_Test Exchange Gain/Loss - _TC",
"cost_center": "_Test Cost Center - _TC",
"amount": 300.0,
},
)
self.assertEqual(pe.deductions[-1].amount, 300.0)
pe.deductions[-1].account = "_Test Exchange Gain/Loss - _TC"
pe.deductions[-1].cost_center = "_Test Cost Center - _TC"
pe.insert()
pe.submit()
@@ -552,16 +545,10 @@ class TestPaymentEntry(FrappeTestCase):
pe.reference_no = "1"
pe.reference_date = "2016-01-01"
self.assertEqual(pe.difference_amount, 100)
self.assertEqual(pe.deductions[0].amount, 100)
pe.deductions[0].account = "_Test Exchange Gain/Loss - _TC"
pe.deductions[0].cost_center = "_Test Cost Center - _TC"
pe.append(
"deductions",
{
"account": "_Test Exchange Gain/Loss - _TC",
"cost_center": "_Test Cost Center - _TC",
"amount": 100,
},
)
pe.insert()
pe.submit()
@@ -654,16 +641,9 @@ class TestPaymentEntry(FrappeTestCase):
pe.set_exchange_rate()
pe.set_amounts()
self.assertEqual(pe.difference_amount, 500)
pe.append(
"deductions",
{
"account": "_Test Exchange Gain/Loss - _TC",
"cost_center": "_Test Cost Center - _TC",
"amount": 500,
},
)
self.assertEqual(pe.deductions[0].amount, 500)
pe.deductions[0].account = "_Test Exchange Gain/Loss - _TC"
pe.deductions[0].cost_center = "_Test Cost Center - _TC"
pe.insert()
pe.submit()
@@ -956,6 +936,53 @@ class TestPaymentEntry(FrappeTestCase):
self.assertEqual(flt(expected_party_balance), party_balance)
self.assertEqual(flt(expected_party_account_balance, 2), flt(party_account_balance, 2))
def test_gl_of_multi_currency_payment_transaction(self):
from erpnext.setup.doctype.currency_exchange.test_currency_exchange import (
save_new_records,
test_records,
)
save_new_records(test_records)
paid_from = create_account(
parent_account="Current Liabilities - _TC",
account_name="_Test Cash USD",
company="_Test Company",
account_type="Cash",
account_currency="USD",
)
payment_entry = create_payment_entry(
party="_Test Supplier USD",
paid_from=paid_from,
paid_to="_Test Payable USD - _TC",
paid_amount=100,
save=True,
)
payment_entry.source_exchange_rate = 84.4
payment_entry.target_exchange_rate = 84.4
payment_entry.save()
payment_entry = payment_entry.submit()
gle = qb.DocType("GL Entry")
gl_entries = (
qb.from_(gle)
.select(
gle.account,
gle.debit,
gle.credit,
gle.debit_in_account_currency,
gle.credit_in_account_currency,
gle.debit_in_transaction_currency,
gle.credit_in_transaction_currency,
)
.orderby(gle.account)
.where(gle.voucher_no == payment_entry.name)
.run()
)
expected_gl_entries = (
(paid_from, 0.0, 8440.0, 0.0, 100.0, 0.0, 100.0),
("_Test Payable USD - _TC", 8440.0, 0.0, 100.0, 0.0, 100.0, 0.0),
)
self.assertEqual(gl_entries, expected_gl_entries)
def test_multi_currency_payment_entry_with_taxes(self):
payment_entry = create_payment_entry(
party="_Test Supplier USD", paid_to="_Test Payable USD - _TC", save=True
@@ -1452,7 +1479,7 @@ class TestPaymentEntry(FrappeTestCase):
parent_account="Current Liabilities - _TC",
account_name="Advances Paid",
company=company,
account_type="Liability",
account_type="Payable",
)
frappe.db.set_value(

View File

@@ -9,6 +9,7 @@
"cost_center",
"amount",
"column_break_2",
"is_exchange_gain_loss",
"description"
],
"fields": [
@@ -45,12 +46,20 @@
"fieldname": "description",
"fieldtype": "Small Text",
"label": "Description"
},
{
"default": "0",
"depends_on": "eval:doc.is_exchange_gain_loss",
"fieldname": "is_exchange_gain_loss",
"fieldtype": "Check",
"label": "Is Exchange Gain / Loss?",
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-03-06 07:11:57.739619",
"modified": "2024-11-05 16:07:47.307971",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry Deduction",

View File

@@ -18,6 +18,7 @@ class PaymentEntryDeduction(Document):
amount: DF.Currency
cost_center: DF.Link
description: DF.SmallText | None
is_exchange_gain_loss: DF.Check
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data

View File

@@ -153,10 +153,7 @@ class PaymentReconciliation(Document):
self.add_payment_entries(non_reconciled_payments)
def get_payment_entries(self):
if self.default_advance_account:
party_account = [self.receivable_payable_account, self.default_advance_account]
else:
party_account = [self.receivable_payable_account]
party_account = [self.receivable_payable_account]
order_doctype = "Sales Order" if self.party_type == "Customer" else "Purchase Order"
condition = frappe._dict(
@@ -187,6 +184,7 @@ class PaymentReconciliation(Document):
self.party,
party_account,
order_doctype,
default_advance_account=self.default_advance_account,
against_all_orders=True,
limit=self.payment_limit,
condition=condition,
@@ -211,12 +209,14 @@ class PaymentReconciliation(Document):
if self.get("cost_center"):
conditions.append(jea.cost_center == self.cost_center)
dr_or_cr = (
"credit_in_account_currency"
if erpnext.get_party_account_type(self.party_type) == "Receivable"
else "debit_in_account_currency"
)
conditions.append(jea[dr_or_cr].gt(0))
account_type = erpnext.get_party_account_type(self.party_type)
if account_type == "Receivable":
dr_or_cr = jea.credit_in_account_currency - jea.debit_in_account_currency
elif account_type == "Payable":
dr_or_cr = jea.debit_in_account_currency - jea.credit_in_account_currency
conditions.append(dr_or_cr.gt(0))
if self.bank_cash_account:
conditions.append(jea.against_account.like(f"%%{self.bank_cash_account}%%"))
@@ -231,7 +231,7 @@ class PaymentReconciliation(Document):
je.posting_date,
je.remark.as_("remarks"),
jea.name.as_("reference_row"),
jea[dr_or_cr].as_("amount"),
dr_or_cr.as_("amount"),
jea.is_advance,
jea.exchange_rate,
jea.account_currency.as_("currency"),
@@ -371,6 +371,10 @@ class PaymentReconciliation(Document):
if self.invoice_limit:
non_reconciled_invoices = non_reconciled_invoices[: self.invoice_limit]
non_reconciled_invoices = sorted(
non_reconciled_invoices, key=lambda k: k["posting_date"] or getdate(nowdate())
)
self.add_invoice_entries(non_reconciled_invoices)
def add_invoice_entries(self, non_reconciled_invoices):

View File

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

View File

@@ -58,7 +58,9 @@
"payment_account",
"payment_channel",
"payment_order",
"amended_from"
"amended_from",
"column_break_iiuv",
"phone_number"
],
"fields": [
{
@@ -376,6 +378,7 @@
"read_only": 1
},
{
"depends_on": "eval: doc.payment_channel==\"Phone\"",
"fetch_from": "payment_gateway_account.payment_channel",
"fieldname": "payment_channel",
"fieldtype": "Select",
@@ -429,13 +432,22 @@
"fieldtype": "Data",
"label": "Party Name",
"read_only": 1
},
{
"fieldname": "column_break_iiuv",
"fieldtype": "Column Break"
},
{
"fieldname": "phone_number",
"fieldtype": "Data",
"label": "Phone Number"
}
],
"in_create": 1,
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2024-10-23 12:23:40.117336",
"modified": "2024-12-27 21:29:10.361894",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Request",

View File

@@ -1,9 +1,9 @@
import json
import frappe
from frappe import _
from frappe import _, qb
from frappe.model.document import Document
from frappe.query_builder.functions import Sum
from frappe.query_builder.functions import Abs, Sum
from frappe.utils import flt, nowdate
from frappe.utils.background_jobs import enqueue
@@ -224,6 +224,7 @@ class PaymentRequest(Document):
sender=self.email_to,
currency=self.currency,
payment_gateway=self.payment_gateway,
phone_number=self.phone_number,
)
controller.validate_transaction_currency(self.currency)
@@ -564,11 +565,35 @@ def make_payment_request(**args):
# fetches existing payment request `grand_total` amount
existing_payment_request_amount = get_existing_payment_request_amount(ref_doc.doctype, ref_doc.name)
if existing_payment_request_amount:
grand_total -= existing_payment_request_amount
existing_paid_amount = get_existing_paid_amount(ref_doc.doctype, ref_doc.name)
def validate_and_calculate_grand_total(grand_total, existing_payment_request_amount):
grand_total -= existing_payment_request_amount
if not grand_total:
frappe.throw(_("Payment Request is already created"))
return grand_total
if existing_payment_request_amount:
if args.order_type == "Shopping Cart":
# If Payment Request is in an advanced stage, then create for remaining amount.
if get_existing_payment_request_amount(
ref_doc.doctype, ref_doc.name, ["Initiated", "Partially Paid", "Payment Ordered", "Paid"]
):
grand_total = validate_and_calculate_grand_total(grand_total, existing_payment_request_amount)
else:
# If PR's are processed, cancel all of them.
cancel_old_payment_requests(ref_doc.doctype, ref_doc.name)
else:
grand_total = validate_and_calculate_grand_total(grand_total, existing_payment_request_amount)
if existing_paid_amount:
if ref_doc.party_account_currency == ref_doc.currency:
if ref_doc.conversion_rate:
grand_total -= flt(existing_paid_amount / ref_doc.conversion_rate)
else:
grand_total -= flt(existing_paid_amount)
else:
grand_total -= flt(existing_paid_amount / ref_doc.conversion_rate)
if draft_payment_request:
frappe.db.set_value(
@@ -611,6 +636,7 @@ def make_payment_request(**args):
"party": args.get("party") or ref_doc.get("customer"),
"bank_account": bank_account,
"party_name": args.get("party_name") or ref_doc.get("customer_name"),
"phone_number": args.get("phone_number") if args.get("phone_number") else None,
}
)
@@ -678,21 +704,88 @@ def get_amount(ref_doc, payment_account=None):
frappe.throw(_("Payment Entry is already created"))
def get_existing_payment_request_amount(ref_dt, ref_dn):
def get_irequest_status(payment_requests: None | list = None) -> list:
IR = frappe.qb.DocType("Integration Request")
res = []
if payment_requests:
res = (
frappe.qb.from_(IR)
.select(IR.name)
.where(IR.reference_doctype.eq("Payment Request"))
.where(IR.reference_docname.isin(payment_requests))
.where(IR.status.isin(["Authorized", "Completed"]))
.run(as_dict=True)
)
return res
def cancel_old_payment_requests(ref_dt, ref_dn):
PR = frappe.qb.DocType("Payment Request")
if res := (
frappe.qb.from_(PR)
.select(PR.name)
.where(PR.reference_doctype == ref_dt)
.where(PR.reference_name == ref_dn)
.where(PR.docstatus == 1)
.where(PR.status.isin(["Draft", "Requested"]))
.run(as_dict=True)
):
if get_irequest_status([x.name for x in res]):
frappe.throw(_("Another Payment Request is already processed"))
else:
for x in res:
doc = frappe.get_doc("Payment Request", x.name)
doc.flags.ignore_permissions = True
doc.cancel()
if ireqs := get_irequests_of_payment_request(doc.name):
for ireq in ireqs:
frappe.db.set_value("Integration Request", ireq.name, "status", "Cancelled")
def get_existing_payment_request_amount(ref_dt, ref_dn, statuses: list | None = None) -> list:
"""
Return the total amount of Payment Requests against a reference document.
"""
PR = frappe.qb.DocType("Payment Request")
response = (
query = (
frappe.qb.from_(PR)
.select(Sum(PR.grand_total))
.where(PR.reference_doctype == ref_dt)
.where(PR.reference_name == ref_dn)
.where(PR.docstatus == 1)
.run()
)
if statuses:
query = query.where(PR.status.isin(statuses))
response = query.run()
return response[0][0] if response[0] else 0
def get_existing_paid_amount(doctype, name):
PL = frappe.qb.DocType("Payment Ledger Entry")
PER = frappe.qb.DocType("Payment Entry Reference")
query = (
frappe.qb.from_(PL)
.left_join(PER)
.on(
(PER.reference_doctype == PL.against_voucher_type) & (PER.reference_name == PL.against_voucher_no)
)
.select(Abs(Sum(PL.amount)).as_("total_paid_amount"))
.where(PL.against_voucher_type.eq(doctype))
.where(PL.against_voucher_no.eq(name))
.where(PL.amount < 0)
.where(PL.delinked == 0)
.where(PER.docstatus == 1)
.where(PER.payment_request.isnull())
)
response = query.run()
return response[0][0] if response[0] else 0
@@ -888,21 +981,17 @@ def validate_payment(doc, method=None):
@frappe.whitelist()
def get_open_payment_requests_query(doctype, txt, searchfield, start, page_len, filters):
# permission checks in `get_list()`
reference_doctype = filters.get("reference_doctype")
reference_name = filters.get("reference_doctype")
filters = frappe._dict(filters)
if not reference_doctype or not reference_name:
if not filters.reference_doctype or not filters.reference_name:
return []
if txt:
filters.name = ["like", f"%{txt}%"]
open_payment_requests = frappe.get_list(
"Payment Request",
filters={
"reference_doctype": filters["reference_doctype"],
"reference_name": filters["reference_name"],
"status": ["!=", "Paid"],
"outstanding_amount": ["!=", 0], # for compatibility with old data
"docstatus": 1,
},
filters=filters,
fields=["name", "grand_total", "outstanding_amount"],
order_by="transaction_date ASC,creation ASC",
)
@@ -915,3 +1004,17 @@ def get_open_payment_requests_query(doctype, txt, searchfield, start, page_len,
)
for pr in open_payment_requests
]
def get_irequests_of_payment_request(doc: str | None = None) -> list:
res = []
if doc:
res = frappe.db.get_all(
"Integration Request",
{
"reference_doctype": "Payment Request",
"reference_docname": doc,
"status": "Queued",
},
)
return res

View File

@@ -0,0 +1,14 @@
from frappe import _
def get_data():
return {
"fieldname": "payment_request",
"internal_links": {
"Payment Entry": ["references", "payment_request"],
"Payment Order": ["references", "payment_order"],
},
"transactions": [
{"label": _("Payment"), "items": ["Payment Entry", "Payment Order"]},
],
}

View File

@@ -1,19 +1,18 @@
const INDICATORS = {
"Partially Paid": "orange",
Cancelled: "red",
Draft: "red",
Failed: "red",
Initiated: "green",
Paid: "blue",
Requested: "green",
};
frappe.listview_settings["Payment Request"] = {
add_fields: ["status"],
get_indicator: function (doc) {
if (doc.status == "Draft") {
return [__("Draft"), "gray", "status,=,Draft"];
}
if (doc.status == "Requested") {
return [__("Requested"), "green", "status,=,Requested"];
} else if (doc.status == "Initiated") {
return [__("Initiated"), "green", "status,=,Initiated"];
} else if (doc.status == "Partially Paid") {
return [__("Partially Paid"), "orange", "status,=,Partially Paid"];
} else if (doc.status == "Paid") {
return [__("Paid"), "blue", "status,=,Paid"];
} else if (doc.status == "Cancelled") {
return [__("Cancelled"), "red", "status,=,Cancelled"];
}
if (!doc.status || !INDICATORS[doc.status]) return;
return [__(doc.status), INDICATORS[doc.status], `status,=,${doc.status}`];
},
};

View File

@@ -7,6 +7,7 @@ import unittest
import frappe
from frappe.tests.utils import FrappeTestCase, change_settings
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_terms_template
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
@@ -524,3 +525,48 @@ class TestPaymentRequest(FrappeTestCase):
self.assertEqual(pr.grand_total, 1000)
so.load_from_db()
def test_partial_paid_invoice_with_payment_request(self):
si = create_sales_invoice(currency="INR", qty=1, rate=5000)
si.save()
si.submit()
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
pe.reference_no = "PAYEE0002"
pe.reference_date = frappe.utils.nowdate()
pe.paid_amount = 2500
pe.references[0].allocated_amount = 2500
pe.save()
pe.submit()
si.load_from_db()
pr = make_payment_request(dt="Sales Invoice", dn=si.name, mute_email=1)
self.assertEqual(pr.grand_total, si.outstanding_amount)
def test_partial_paid_invoice_with_submitted_payment_entry(self):
pi = make_purchase_invoice(currency="INR", qty=1, rate=5000)
pi.save()
pi.submit()
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
pe.reference_no = "PURINV0001"
pe.reference_date = frappe.utils.nowdate()
pe.paid_amount = 2500
pe.references[0].allocated_amount = 2500
pe.save()
pe.submit()
pe.cancel()
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
pe.reference_no = "PURINV0002"
pe.reference_date = frappe.utils.nowdate()
pe.paid_amount = 2500
pe.references[0].allocated_amount = 2500
pe.save()
pe.submit()
pi.load_from_db()
pr = make_payment_request(dt="Purchase Invoice", dn=pi.name, mute_email=1)
self.assertEqual(pr.grand_total, pi.outstanding_amount)

View File

@@ -171,9 +171,7 @@ class PeriodClosingVoucher(AccountsController):
pl_account_balances = self.get_account_balances_based_on_dimensions(report_type="Profit and Loss")
for dimensions, account_balances in pl_account_balances.items():
for acc, balances in account_balances.items():
balance_in_company_currency = flt(balances.debit_in_account_currency) - flt(
balances.credit_in_account_currency
)
balance_in_company_currency = flt(balances.debit) - flt(balances.credit)
if balance_in_company_currency and acc != "balances":
self.pl_accounts_reverse_gle.append(
self.get_gle_for_pl_account(acc, balances, dimensions)

View File

@@ -12,15 +12,15 @@
</thead>
<tbody>
<tr>
<td class="text-left font-bold">{{ _('Grand Total') }}</td>
<td class="text-left font-bold">{{ _("Grand Total") }}</td>
<td class='text-right'> {{ frappe.utils.fmt_money(data.grand_total or '', currency=currency) }}</td>
</tr>
<tr>
<td class="text-left font-bold">{{ _('Net Total') }}</td>
<td class="text-left font-bold">{{ _("Net Total") }}</td>
<td class='text-right'> {{ frappe.utils.fmt_money(data.net_total or '', currency=currency) }}</td>
</tr>
<tr>
<td class="text-left font-bold">{{ _('Total Quantity') }}</td>
<td class="text-left font-bold">{{ _("Total Quantity") }}</td>
<td class='text-right'>{{ data.total_quantity or '' }}</td>
</tr>
@@ -44,7 +44,7 @@
<tbody>
{% for d in data.payment_reconciliation %}
<tr>
<td class="text-left">{{ d.mode_of_payment }}</td>
<td class="text-left">{{ _(d.mode_of_payment) }}</td>
<td class='text-right'> {{ frappe.utils.fmt_money(d.expected_amount - d.opening_amount, currency=currency) }}</td>
</tr>
{% endfor %}
@@ -63,7 +63,7 @@
<thead>
<tr>
<th class="text-left">{{ _("Account") }}</th>
<th class="text-left">{{ _("Rate") }}</th>
<th class="text-left">{{ _("Tax Rate") }}</th>
<th class="text-right">{{ _("Amount") }}</th>
</tr>
</thead>

View File

@@ -147,7 +147,7 @@ frappe.ui.form.on("POS Closing Entry", {
frm.doc.grand_total += flt(doc.grand_total);
frm.doc.net_total += flt(doc.net_total);
frm.doc.total_quantity += flt(doc.total_qty);
refresh_payments(doc, frm);
refresh_payments(doc, frm, false);
refresh_taxes(doc, frm);
refresh_fields(frm);
set_html_data(frm);
@@ -172,7 +172,7 @@ function set_form_data(data, frm) {
frm.doc.grand_total += flt(d.grand_total);
frm.doc.net_total += flt(d.net_total);
frm.doc.total_quantity += flt(d.total_qty);
refresh_payments(d, frm);
refresh_payments(d, frm, true);
refresh_taxes(d, frm);
});
}
@@ -186,7 +186,7 @@ function add_to_pos_transaction(d, frm) {
});
}
function refresh_payments(d, frm) {
function refresh_payments(d, frm, is_new) {
d.payments.forEach((p) => {
const payment = frm.doc.payment_reconciliation.find(
(pay) => pay.mode_of_payment === p.mode_of_payment
@@ -196,9 +196,7 @@ function refresh_payments(d, frm) {
}
if (payment) {
payment.expected_amount += flt(p.amount);
if (payment.closing_amount === 0) {
payment.closing_amount = payment.expected_amount;
}
if (is_new) payment.closing_amount = payment.expected_amount;
payment.difference = payment.closing_amount - payment.expected_amount;
} else {
frm.add_child("payment_reconciliation", {

View File

@@ -14,7 +14,7 @@
"fieldname": "rate",
"fieldtype": "Percent",
"in_list_view": 1,
"label": "Rate",
"label": "Tax Rate",
"read_only": 1
},
{

View File

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

View File

@@ -48,6 +48,7 @@
"shipping_address",
"company_address",
"company_address_display",
"company_contact_person",
"currency_and_price_list",
"currency",
"conversion_rate",
@@ -1558,12 +1559,19 @@
"fieldname": "update_billed_amount_in_delivery_note",
"fieldtype": "Check",
"label": "Update Billed Amount in Delivery Note"
},
{
"fieldname": "company_contact_person",
"fieldtype": "Link",
"label": "Company Contact Person",
"options": "Contact",
"print_hide": 1
}
],
"icon": "fa fa-file-text",
"is_submittable": 1,
"links": [],
"modified": "2024-03-20 16:00:34.268756",
"modified": "2024-11-26 13:10:50.309570",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Invoice",

View File

@@ -32,12 +32,8 @@ class POSInvoice(SalesInvoice):
from erpnext.accounts.doctype.payment_schedule.payment_schedule import PaymentSchedule
from erpnext.accounts.doctype.pos_invoice_item.pos_invoice_item import POSInvoiceItem
from erpnext.accounts.doctype.pricing_rule_detail.pricing_rule_detail import PricingRuleDetail
from erpnext.accounts.doctype.sales_invoice_advance.sales_invoice_advance import (
SalesInvoiceAdvance,
)
from erpnext.accounts.doctype.sales_invoice_payment.sales_invoice_payment import (
SalesInvoicePayment,
)
from erpnext.accounts.doctype.sales_invoice_advance.sales_invoice_advance import SalesInvoiceAdvance
from erpnext.accounts.doctype.sales_invoice_payment.sales_invoice_payment import SalesInvoicePayment
from erpnext.accounts.doctype.sales_invoice_timesheet.sales_invoice_timesheet import (
SalesInvoiceTimesheet,
)
@@ -75,6 +71,7 @@ class POSInvoice(SalesInvoice):
company: DF.Link
company_address: DF.Link | None
company_address_display: DF.SmallText | None
company_contact_person: DF.Link | None
consolidated_invoice: DF.Link | None
contact_display: DF.SmallText | None
contact_email: DF.Data | None

View File

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

View File

@@ -117,11 +117,13 @@ class POSInvoiceMergeLog(Document):
sales = [d for d in pos_invoice_docs if d.get("is_return") == 0]
sales_invoice, credit_note = "", ""
if returns:
credit_note = self.process_merging_into_credit_note(returns)
sales_invoice_doc = None
if sales:
sales_invoice = self.process_merging_into_sales_invoice(sales)
sales_invoice_doc = self.process_merging_into_sales_invoice(sales)
sales_invoice = sales_invoice_doc.name
if returns:
credit_note = self.process_merging_into_credit_note(returns, sales_invoice_doc)
self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log
self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note)
@@ -132,6 +134,7 @@ class POSInvoiceMergeLog(Document):
self.update_pos_invoices(pos_invoice_docs)
self.serial_and_batch_bundle_reference_for_pos_invoice()
self.cancel_linked_invoices()
self.delink_serial_and_batch_bundle()
def process_merging_into_sales_invoice(self, data):
sales_invoice = self.get_new_sales_invoice()
@@ -139,20 +142,35 @@ class POSInvoiceMergeLog(Document):
sales_invoice.is_consolidated = 1
sales_invoice.set_posting_time = 1
sales_invoice.posting_date = getdate(self.posting_date)
sales_invoice.posting_time = get_time(self.posting_time)
if not sales_invoice.posting_date:
sales_invoice.posting_date = getdate(self.posting_date)
if not sales_invoice.posting_time:
sales_invoice.posting_time = get_time(self.posting_time)
sales_invoice.save()
sales_invoice.submit()
self.consolidated_invoice = sales_invoice.name
return sales_invoice.name
return sales_invoice
def process_merging_into_credit_note(self, data):
def process_merging_into_credit_note(self, data, sales_invoice_doc=None):
credit_note = self.get_new_sales_invoice()
credit_note.is_return = 1
credit_note = self.merge_pos_invoice_into(credit_note, data)
referenes = {}
if sales_invoice_doc:
credit_note.return_against = sales_invoice_doc.name
for d in sales_invoice_doc.items:
referenes[d.item_code] = d.name
for d in credit_note.items:
d.sales_invoice_item = referenes.get(d.item_code)
credit_note.is_consolidated = 1
credit_note.set_posting_time = 1
@@ -180,6 +198,10 @@ class POSInvoiceMergeLog(Document):
for doc in data:
map_doc(doc, invoice, table_map={"doctype": invoice.doctype})
if doc.get("posting_date"):
invoice.posting_date = getdate(doc.posting_date)
invoice.posting_time = get_time(doc.posting_time)
if doc.redeem_loyalty_points:
invoice.loyalty_redemption_account = doc.loyalty_redemption_account
invoice.loyalty_redemption_cost_center = doc.loyalty_redemption_cost_center
@@ -297,6 +319,8 @@ class POSInvoiceMergeLog(Document):
sales_invoice = frappe.new_doc("Sales Invoice")
sales_invoice.customer = self.customer
sales_invoice.is_pos = 1
sales_invoice.posting_date = None
sales_invoice.posting_time = None
return sales_invoice
@@ -319,8 +343,45 @@ class POSInvoiceMergeLog(Document):
for table_name in ["items", "packed_items"]:
pos_invoice.set_serial_and_batch_bundle(table_name)
def delink_serial_and_batch_bundle(self):
bundles = self.get_serial_and_batch_bundles()
if not bundles:
return
sle_table = frappe.qb.DocType("Stock Ledger Entry")
query = (
frappe.qb.update(sle_table)
.set(sle_table.serial_and_batch_bundle, None)
.where(sle_table.serial_and_batch_bundle.isin(bundles) & sle_table.is_cancelled == 1)
)
query.run()
def get_serial_and_batch_bundles(self):
pos_invoices = []
for d in self.pos_invoices:
pos_invoices.append(d.pos_invoice)
if pos_invoices:
return frappe.get_all(
"POS Invoice Item",
filters={
"docstatus": 1,
"parent": ["in", pos_invoices],
"serial_and_batch_bundle": ["is", "set"],
},
pluck="serial_and_batch_bundle",
)
return []
def cancel_linked_invoices(self):
for si_name in [self.consolidated_invoice, self.consolidated_credit_note]:
invoices = [self.consolidated_invoice, self.consolidated_credit_note]
if not invoices:
return
invoices.reverse()
for si_name in invoices:
if not si_name:
continue
si = frappe.get_doc("Sales Invoice", si_name)
@@ -503,6 +564,9 @@ def cancel_merge_logs(merge_logs, closing_entry=None):
try:
for log in merge_logs:
merge_log = frappe.get_doc("POS Invoice Merge Log", log)
if merge_log.docstatus == 2:
continue
merge_log.flags.ignore_permissions = True
merge_log.cancel()

View File

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

View File

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

View File

@@ -1137,6 +1137,45 @@ class TestPricingRule(FrappeTestCase):
so.save()
self.assertEqual(len(so.items), 1)
def test_pricing_rule_for_product_free_item_round_free_qty(self):
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule")
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule",
"apply_on": "Item Code",
"currency": "USD",
"items": [
{
"item_code": "_Test Item",
}
],
"selling": 1,
"rate": 0,
"min_qty": 100,
"max_qty": 0,
"price_or_product_discount": "Product",
"same_item": 1,
"free_qty": 10,
"round_free_qty": 1,
"is_recursive": 1,
"recurse_for": 100,
"company": "_Test Company",
}
frappe.get_doc(test_record.copy()).insert()
# With pricing rule
so = make_sales_order(item_code="_Test Item", qty=100)
so.load_from_db()
self.assertEqual(so.items[1].is_free_item, 1)
self.assertEqual(so.items[1].item_code, "_Test Item")
self.assertEqual(so.items[1].qty, 10)
so = make_sales_order(item_code="_Test Item", qty=150)
so.load_from_db()
self.assertEqual(so.items[1].is_free_item, 1)
self.assertEqual(so.items[1].item_code, "_Test Item")
self.assertEqual(so.items[1].qty, 10)
def test_apply_multiple_pricing_rules_for_discount_percentage_and_amount(self):
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 1")
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 2")

View File

@@ -651,11 +651,20 @@ def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None):
qty = pricing_rule.free_qty or 1
if pricing_rule.is_recursive:
transaction_qty = (args.get("qty") if args else doc.total_qty) - pricing_rule.apply_recursion_over
if transaction_qty:
transaction_qty = sum(
[
row.qty
for row in doc.items
if not row.is_free_item
and row.item_code == args.item_code
and row.pricing_rules == args.pricing_rules
]
)
transaction_qty = transaction_qty - pricing_rule.apply_recursion_over
if transaction_qty and transaction_qty > 0:
qty = flt(transaction_qty) * qty / pricing_rule.recurse_for
if pricing_rule.round_free_qty:
qty = math.floor(qty)
qty = (flt(transaction_qty) // pricing_rule.recurse_for) * (pricing_rule.free_qty or 1)
if not qty:
return

View File

@@ -244,9 +244,9 @@
},
{
"fieldname": "cc_to",
"fieldtype": "Link",
"fieldtype": "Table MultiSelect",
"label": "CC To",
"options": "User"
"options": "Process Statement Of Accounts CC"
},
{
"default": "1",
@@ -400,7 +400,7 @@
}
],
"links": [],
"modified": "2024-10-18 17:51:39.108481",
"modified": "2024-12-11 12:11:13.543134",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Process Statement Of Accounts",

View File

@@ -31,6 +31,9 @@ class ProcessStatementOfAccounts(Document):
if TYPE_CHECKING:
from frappe.types import DF
from erpnext.accounts.doctype.process_statement_of_accounts_cc.process_statement_of_accounts_cc import (
ProcessStatementOfAccountsCC,
)
from erpnext.accounts.doctype.process_statement_of_accounts_customer.process_statement_of_accounts_customer import (
ProcessStatementOfAccountsCustomer,
)
@@ -41,7 +44,7 @@ class ProcessStatementOfAccounts(Document):
ageing_based_on: DF.Literal["Due Date", "Posting Date"]
based_on_payment_terms: DF.Check
body: DF.TextEditor | None
cc_to: DF.Link | None
cc_to: DF.TableMultiSelect[ProcessStatementOfAccountsCC]
collection_name: DF.DynamicLink | None
company: DF.Link
cost_center: DF.TableMultiSelect[PSOACostCenter]
@@ -324,7 +327,7 @@ def get_recipients_and_cc(customer, doc):
cc = []
if doc.cc_to != "":
try:
cc = [frappe.get_value("User", doc.cc_to, "email")]
cc = [frappe.get_value("User", user.cc, "email") for user in doc.cc_to]
except Exception:
pass
@@ -474,6 +477,7 @@ def send_emails(document_name, from_scheduler=False, posting_date=None):
reference_doctype="Process Statement Of Accounts",
reference_name=document_name,
attachments=attachments,
expose_recipients="header",
)
if doc.enable_auto_email and from_scheduler:

View File

@@ -0,0 +1,32 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2024-12-11 12:10:04.654593",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"cc"
],
"fields": [
{
"fieldname": "cc",
"fieldtype": "Link",
"in_list_view": 1,
"label": "CC",
"options": "User"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2024-12-11 12:10:39.772598",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Process Statement Of Accounts CC",
"owner": "Administrator",
"permissions": [],
"sort_field": "creation",
"sort_order": "DESC",
"states": []
}

View File

@@ -0,0 +1,23 @@
# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ProcessStatementOfAccountsCC(Document):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from frappe.types import DF
cc: DF.Link | None
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data
# end: auto-generated types
pass

View File

@@ -399,6 +399,8 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
hide_fields(this.frm.doc);
if (cint(this.frm.doc.is_paid)) {
this.frm.set_value("allocate_advances_automatically", 0);
this.frm.set_value("payment_terms_template", "");
this.frm.set_value("payment_schedule", []);
if (!this.frm.doc.company) {
this.frm.set_value("is_paid", 0);
frappe.msgprint(__("Please specify Company to proceed"));

View File

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

View File

@@ -1544,6 +1544,61 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
payment_entry.load_from_db()
self.assertEqual(payment_entry.taxes[0].allocated_amount, 0)
def test_purchase_gl_with_tax_withholding_tax(self):
company = "_Test Company"
tds_account_args = {
"doctype": "Account",
"account_name": "TDS Payable",
"account_type": "Tax",
"parent_account": frappe.db.get_value(
"Account", {"account_name": "Duties and Taxes", "company": company}
),
"company": company,
}
tds_account = create_account(**tds_account_args)
tax_withholding_category = "Test TDS - 194 - Dividends - Individual"
# Update tax withholding category with current fiscal year and rate details
create_tax_witholding_category(tax_withholding_category, company, tds_account)
# create a new supplier to test
supplier = create_supplier(
supplier_name="_Test TDS Advance Supplier",
tax_withholding_category=tax_withholding_category,
)
pi = make_purchase_invoice(
supplier=supplier.name,
rate=3000,
qty=1,
item="_Test Non Stock Item",
do_not_submit=1,
)
pi.apply_tds = 1
pi.tax_withholding_category = tax_withholding_category
pi.save()
pi.submit()
self.assertEqual(pi.taxes[0].tax_amount, 300)
self.assertEqual(pi.taxes[0].account_head, tds_account)
gl_entries = frappe.get_all(
"GL Entry",
filters={"voucher_no": pi.name, "voucher_type": "Purchase Invoice", "account": "Creditors - _TC"},
fields=["account", "against", "debit", "credit"],
)
for gle in gl_entries:
if gle.debit:
# GL Entry with TDS Amount
self.assertEqual(gle.against, tds_account)
self.assertEqual(gle.debit, 300)
else:
# GL Entry with Purchase Invoice Amount
self.assertEqual(gle.credit, 3000)
def test_provisional_accounting_entry(self):
setup_provisional_accounting()
@@ -1680,6 +1735,30 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
frappe.db.set_single_value("Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 1)
# Cost of Item is zero in Purchase Receipt
pr = make_purchase_receipt(qty=1, rate=0)
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, 0)
pi = create_purchase_invoice_from_receipt(pr.name)
for row in pi.items:
row.rate = 150
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, 150)
# Increase the cost of the item
pr = make_purchase_receipt(qty=1, rate=100)
@@ -1759,6 +1838,52 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 1)
def test_adjust_incoming_rate_for_rejected_item(self):
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)
# Cost of Item is zero in Purchase Receipt
pr = make_purchase_receipt(qty=1, rejected_qty=1, rate=0)
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, 0)
pi = create_purchase_invoice_from_receipt(pr.name)
for row in pi.items:
row.qty = 1
row.rate = 150
pi.save()
pi.submit()
stock_value_difference = frappe.db.get_value(
"Stock Ledger Entry",
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name, "warehouse": pi.items[0].warehouse},
"stock_value_difference",
)
self.assertEqual(stock_value_difference, 150)
stock_value_difference = frappe.db.get_value(
"Stock Ledger Entry",
{
"voucher_type": "Purchase Receipt",
"voucher_no": pr.name,
"warehouse": pi.items[0].rejected_warehouse,
},
"stock_value_difference",
)
self.assertFalse(stock_value_difference)
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 test_item_less_defaults(self):
pi = frappe.new_doc("Purchase Invoice")
pi.supplier = "_Test Supplier"
@@ -2310,6 +2435,93 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
item.reload()
self.assertEqual(item.last_purchase_rate, 0)
def test_opening_invoice_rounding_adjustment_validation(self):
pi = make_purchase_invoice(do_not_save=1)
pi.items[0].rate = 99.98
pi.items[0].qty = 1
pi.items[0].expense_account = "Temporary Opening - _TC"
pi.is_opening = "Yes"
pi.save()
self.assertRaises(frappe.ValidationError, pi.submit)
def _create_opening_roundoff_account(self, company_name):
liability_root = frappe.db.get_all(
"Account",
filters={"company": company_name, "root_type": "Liability", "disabled": 0},
order_by="lft",
limit=1,
)[0]
# setup round off account
if acc := frappe.db.exists(
"Account",
{
"account_name": "Round Off for Opening",
"account_type": "Round Off for Opening",
"company": company_name,
},
):
frappe.db.set_value("Company", company_name, "round_off_for_opening", acc)
else:
acc = frappe.new_doc("Account")
acc.company = company_name
acc.parent_account = liability_root.name
acc.account_name = "Round Off for Opening"
acc.account_type = "Round Off for Opening"
acc.save()
frappe.db.set_value("Company", company_name, "round_off_for_opening", acc.name)
def test_ledger_entries_of_opening_invoice_with_rounding_adjustment(self):
pi = make_purchase_invoice(do_not_save=1)
pi.items[0].rate = 99.98
pi.items[0].qty = 1
pi.items[0].expense_account = "Temporary Opening - _TC"
pi.is_opening = "Yes"
pi.save()
self._create_opening_roundoff_account(pi.company)
pi.submit()
actual = frappe.db.get_all(
"GL Entry",
filters={"voucher_no": pi.name, "is_opening": "Yes", "is_cancelled": False},
fields=["account", "debit", "credit", "is_opening"],
order_by="account,debit",
)
expected = [
{"account": "Creditors - _TC", "debit": 0.0, "credit": 100.0, "is_opening": "Yes"},
{"account": "Round Off for Opening - _TC", "debit": 0.02, "credit": 0.0, "is_opening": "Yes"},
{"account": "Temporary Opening - _TC", "debit": 99.98, "credit": 0.0, "is_opening": "Yes"},
]
self.assertEqual(len(actual), 3)
self.assertEqual(expected, actual)
def test_invoice_against_returned_pr(self):
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import (
make_purchase_invoice as make_purchase_invoice_from_pr,
)
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import (
make_purchase_return_against_rejected_warehouse,
)
item = make_item("_Test Item For Invoice Against Returned PR", properties={"is_stock_item": 1}).name
original_value = frappe.db.get_single_value(
"Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice"
)
frappe.db.set_single_value("Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice", 0)
pr = make_purchase_receipt(item_code=item, qty=5, rejected_qty=5, rate=100)
pr_return = make_purchase_return_against_rejected_warehouse(pr.name)
pr_return.submit()
pi = make_purchase_invoice_from_pr(pr.name)
pi.save()
self.assertEqual(pi.items[0].qty, 5.0)
frappe.db.set_single_value(
"Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice", original_value
)
def set_advance_flag(company, flag, default_account):
frappe.db.set_value(

View File

@@ -14,7 +14,8 @@
"advance_amount",
"allocated_amount",
"exchange_gain_loss",
"ref_exchange_rate"
"ref_exchange_rate",
"difference_posting_date"
],
"fields": [
{
@@ -30,7 +31,7 @@
"width": "180px"
},
{
"columns": 3,
"columns": 2,
"fieldname": "reference_name",
"fieldtype": "Dynamic Link",
"in_list_view": 1,
@@ -40,7 +41,7 @@
"read_only": 1
},
{
"columns": 3,
"columns": 2,
"fieldname": "remarks",
"fieldtype": "Text",
"in_list_view": 1,
@@ -111,13 +112,20 @@
"label": "Reference Exchange Rate",
"non_negative": 1,
"read_only": 1
},
{
"columns": 2,
"fieldname": "difference_posting_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Difference Posting Date"
}
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-06-23 21:13:18.013816",
"modified": "2024-12-20 12:04:46.729972",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Advance",

View File

@@ -16,6 +16,7 @@ class PurchaseInvoiceAdvance(Document):
advance_amount: DF.Currency
allocated_amount: DF.Currency
difference_posting_date: DF.Date | None
exchange_gain_loss: DF.Currency
parent: DF.Data
parentfield: DF.Data

View File

@@ -1,6 +1,8 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
import inspect
import frappe
from frappe import _, qb
from frappe.model.document import Document
@@ -45,7 +47,7 @@ class RepostAccountingLedger(Document):
latest_pcv = (
frappe.db.get_all(
"Period Closing Voucher",
filters={"company": self.company},
filters={"company": self.company, "docstatus": 1},
order_by="period_end_date desc",
pluck="period_end_date",
limit=1,
@@ -142,6 +144,8 @@ class RepostAccountingLedger(Document):
@frappe.whitelist()
def start_repost(account_repost_doc=str) -> None:
from erpnext.accounts.general_ledger import make_reverse_gl_entries
frappe.flags.through_repost_accounting_ledger = True
if account_repost_doc:
repost_doc = frappe.get_doc("Repost Accounting Ledger", account_repost_doc)
@@ -177,6 +181,14 @@ def start_repost(account_repost_doc=str) -> None:
if not repost_doc.delete_cancelled_entries:
doc.make_gl_entries(1)
doc.make_gl_entries()
elif doc.doctype in frappe.get_hooks("repost_allowed_doctypes"):
if hasattr(doc, "make_gl_entries") and callable(doc.make_gl_entries):
if not repost_doc.delete_cancelled_entries:
if "cancel" in inspect.getfullargspec(doc.make_gl_entries):
doc.make_gl_entries(cancel=1)
else:
make_reverse_gl_entries(voucher_type=doc.doctype, voucher_no=doc.name)
doc.make_gl_entries()
def get_allowed_types_from_settings():

View File

@@ -741,20 +741,6 @@ frappe.ui.form.on("Sales Invoice", {
};
};
frm.set_query("company_address", function (doc) {
if (!doc.company) {
frappe.throw(__("Please set Company"));
}
return {
query: "frappe.contacts.doctype.address.address.address_query",
filters: {
link_doctype: "Company",
link_name: doc.company,
},
};
});
frm.set_query("pos_profile", function (doc) {
if (!doc.company) {
frappe.throw(__("Please set Company"));

View File

@@ -159,8 +159,9 @@
"dispatch_address",
"company_address_section",
"company_address",
"company_addr_col_break",
"company_address_display",
"company_addr_col_break",
"company_contact_person",
"terms_tab",
"payment_schedule_section",
"ignore_default_payment_terms_template",
@@ -2166,6 +2167,13 @@
"label": "Update Outstanding for Self",
"no_copy": 1,
"print_hide": 1
},
{
"fieldname": "company_contact_person",
"fieldtype": "Link",
"label": "Company Contact Person",
"options": "Contact",
"print_hide": 1
}
],
"icon": "fa fa-file-text",
@@ -2178,7 +2186,7 @@
"link_fieldname": "consolidated_invoice"
}
],
"modified": "2024-07-18 15:30:39.428519",
"modified": "2024-11-26 12:34:09.110690",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
@@ -2233,4 +2241,4 @@
"title_field": "title",
"track_changes": 1,
"track_seen": 1
}
}

View File

@@ -96,6 +96,7 @@ class SalesInvoice(SellingController):
company: DF.Link
company_address: DF.Link | None
company_address_display: DF.SmallText | None
company_contact_person: DF.Link | None
company_tax_id: DF.Data | None
contact_display: DF.SmallText | None
contact_email: DF.Data | None
@@ -506,7 +507,7 @@ class SalesInvoice(SellingController):
frappe.throw(_("Total payments amount can't be greater than {}").format(-invoice_total))
def validate_pos_paid_amount(self):
if len(self.payments) == 0 and self.is_pos:
if len(self.payments) == 0 and self.is_pos and flt(self.grand_total) > 0:
frappe.throw(_("At least one mode of payment is required for POS invoice."))
def check_if_consolidated_invoice(self):
@@ -1001,9 +1002,9 @@ class SalesInvoice(SellingController):
def validate_pos(self):
if self.is_return:
invoice_total = self.rounded_total or self.grand_total
if flt(self.paid_amount) + flt(self.write_off_amount) - flt(invoice_total) > 1.0 / (
10.0 ** (self.precision("grand_total") + 1.0)
):
if abs(flt(self.paid_amount)) + abs(flt(self.write_off_amount)) - abs(
flt(invoice_total)
) > 1.0 / (10.0 ** (self.precision("grand_total") + 1.0)):
frappe.throw(_("Paid amount + Write Off Amount can not be greater than Grand Total"))
def validate_warehouse(self):
@@ -1633,10 +1634,29 @@ class SalesInvoice(SellingController):
and self.base_rounding_adjustment
and not self.is_internal_transfer()
):
round_off_account, round_off_cost_center = get_round_off_account_and_cost_center(
(
round_off_account,
round_off_cost_center,
round_off_for_opening,
) = get_round_off_account_and_cost_center(
self.company, "Sales Invoice", self.name, self.use_company_roundoff_cost_center
)
if self.is_opening == "Yes" and self.rounding_adjustment:
if not round_off_for_opening:
frappe.throw(
_(
"Opening Invoice has rounding adjustment of {0}.<br><br> '{1}' account is required to post these values. Please set it in Company: {2}.<br><br> Or, '{3}' can be enabled to not post any rounding adjustment."
).format(
frappe.bold(self.rounding_adjustment),
frappe.bold("Round Off for Opening"),
get_link_to_form("Company", self.company),
frappe.bold("Disable Rounded Total"),
)
)
else:
round_off_account = round_off_for_opening
gl_entries.append(
self.get_gl_dict(
{
@@ -1735,6 +1755,9 @@ class SalesInvoice(SellingController):
def update_project(self):
unique_projects = list(set([d.project for d in self.get("items") if d.project]))
if self.project and self.project not in unique_projects:
unique_projects.append(self.project)
for p in unique_projects:
project = frappe.get_doc("Project", p)
project.update_billed_amount()

View File

@@ -15,7 +15,7 @@ frappe.listview_settings["Sales Invoice"] = {
],
get_indicator: function (doc) {
const status_colors = {
Draft: "grey",
Draft: "red",
Unpaid: "orange",
Paid: "green",
Return: "gray",

View File

@@ -43,6 +43,7 @@ from erpnext.stock.doctype.stock_entry.test_stock_entry import (
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
create_stock_reconciliation,
)
from erpnext.stock.get_item_details import get_item_tax_map
from erpnext.stock.utils import get_incoming_rate, get_stock_balance
@@ -314,7 +315,8 @@ class TestSalesInvoice(FrappeTestCase):
si.insert()
# with inclusive tax
self.assertEqual(si.items[0].net_amount, 3947.368421052631)
self.assertEqual(si.items[0].net_amount, 3947.37)
self.assertEqual(si.net_total, si.base_net_total)
self.assertEqual(si.net_total, 3947.37)
self.assertEqual(si.grand_total, 5000)
@@ -658,7 +660,7 @@ class TestSalesInvoice(FrappeTestCase):
62.5,
625.0,
50,
499.97600115194473,
499.98,
],
"_Test Item Home Desktop 200": [
190.66,
@@ -669,7 +671,7 @@ class TestSalesInvoice(FrappeTestCase):
190.66,
953.3,
150,
749.9968530500239,
750,
],
}
@@ -682,20 +684,21 @@ class TestSalesInvoice(FrappeTestCase):
self.assertEqual(d.get(k), expected_values[d.item_code][i])
# check net total
self.assertEqual(si.net_total, 1249.97)
self.assertEqual(si.base_net_total, si.net_total)
self.assertEqual(si.net_total, 1249.98)
self.assertEqual(si.total, 1578.3)
# check tax calculation
expected_values = {
"keys": ["tax_amount", "total"],
"_Test Account Excise Duty - _TC": [140, 1389.97],
"_Test Account Education Cess - _TC": [2.8, 1392.77],
"_Test Account S&H Education Cess - _TC": [1.4, 1394.17],
"_Test Account CST - _TC": [27.88, 1422.05],
"_Test Account VAT - _TC": [156.25, 1578.30],
"_Test Account Customs Duty - _TC": [125, 1703.30],
"_Test Account Shipping Charges - _TC": [100, 1803.30],
"_Test Account Discount - _TC": [-180.33, 1622.97],
"_Test Account Excise Duty - _TC": [140, 1389.98],
"_Test Account Education Cess - _TC": [2.8, 1392.78],
"_Test Account S&H Education Cess - _TC": [1.4, 1394.18],
"_Test Account CST - _TC": [27.88, 1422.06],
"_Test Account VAT - _TC": [156.25, 1578.31],
"_Test Account Customs Duty - _TC": [125, 1703.31],
"_Test Account Shipping Charges - _TC": [100, 1803.31],
"_Test Account Discount - _TC": [-180.33, 1622.98],
}
for d in si.get("taxes"):
@@ -731,7 +734,7 @@ class TestSalesInvoice(FrappeTestCase):
"base_rate": 2500,
"base_amount": 25000,
"net_rate": 40,
"net_amount": 399.9808009215558,
"net_amount": 399.98,
"base_net_rate": 2000,
"base_net_amount": 19999,
},
@@ -745,7 +748,7 @@ class TestSalesInvoice(FrappeTestCase):
"base_rate": 7500,
"base_amount": 37500,
"net_rate": 118.01,
"net_amount": 590.0531205155963,
"net_amount": 590.05,
"base_net_rate": 5900.5,
"base_net_amount": 29502.5,
},
@@ -783,8 +786,13 @@ class TestSalesInvoice(FrappeTestCase):
self.assertEqual(si.base_grand_total, 60795)
self.assertEqual(si.grand_total, 1215.90)
self.assertEqual(si.rounding_adjustment, 0.01)
self.assertEqual(si.base_rounding_adjustment, 0.50)
# no rounding adjustment as the Smallest Currency Fraction Value of USD is 0.01
if frappe.db.get_value("Currency", "USD", "smallest_currency_fraction_value") < 0.01:
self.assertEqual(si.rounding_adjustment, 0.10)
self.assertEqual(si.base_rounding_adjustment, 5.0)
else:
self.assertEqual(si.rounding_adjustment, 0.0)
self.assertEqual(si.base_rounding_adjustment, 0.0)
def test_outstanding(self):
w = self.make()
@@ -2172,7 +2180,7 @@ class TestSalesInvoice(FrappeTestCase):
def test_rounding_adjustment_2(self):
si = create_sales_invoice(rate=400, do_not_save=True)
for rate in [400, 600, 100]:
for rate in [400.25, 600.30, 100.65]:
si.append(
"items",
{
@@ -2198,18 +2206,19 @@ class TestSalesInvoice(FrappeTestCase):
)
si.save()
si.submit()
self.assertEqual(si.net_total, 1271.19)
self.assertEqual(si.grand_total, 1500)
self.assertEqual(si.total_taxes_and_charges, 228.82)
self.assertEqual(si.rounding_adjustment, -0.01)
self.assertEqual(si.net_total, si.base_net_total)
self.assertEqual(si.net_total, 1272.20)
self.assertEqual(si.grand_total, 1501.20)
self.assertEqual(si.total_taxes_and_charges, 229)
self.assertEqual(si.rounding_adjustment, -0.20)
round_off_account = frappe.get_cached_value("Company", "_Test Company", "round_off_account")
expected_values = {
"_Test Account Service Tax - _TC": [0.0, 114.41],
"_Test Account VAT - _TC": [0.0, 114.41],
si.debit_to: [1500, 0.0],
round_off_account: [0.01, 0.01],
"Sales - _TC": [0.0, 1271.18],
"_Test Account Service Tax - _TC": [0.0, 114.50],
"_Test Account VAT - _TC": [0.0, 114.50],
si.debit_to: [1501, 0.0],
round_off_account: [0.20, 0.0],
"Sales - _TC": [0.0, 1272.20],
}
gl_entries = frappe.db.sql(
@@ -2267,7 +2276,8 @@ class TestSalesInvoice(FrappeTestCase):
si.save()
si.submit()
self.assertEqual(si.net_total, 4007.16)
self.assertEqual(si.net_total, si.base_net_total)
self.assertEqual(si.net_total, 4007.15)
self.assertEqual(si.grand_total, 4488.02)
self.assertEqual(si.total_taxes_and_charges, 480.86)
self.assertEqual(si.rounding_adjustment, -0.02)
@@ -2280,7 +2290,7 @@ class TestSalesInvoice(FrappeTestCase):
["_Test Account Service Tax - _TC", 0.0, 240.43],
["_Test Account VAT - _TC", 0.0, 240.43],
["Sales - _TC", 0.0, 4007.15],
[round_off_account, 0.02, 0.01],
[round_off_account, 0.01, 0.0],
]
)
@@ -2864,13 +2874,26 @@ class TestSalesInvoice(FrappeTestCase):
item.save()
sales_invoice = create_sales_invoice(item="T Shirt", rate=700, do_not_submit=True)
item_tax_map = get_item_tax_map(
company=sales_invoice.company,
item_tax_template=sales_invoice.items[0].item_tax_template,
)
self.assertEqual(sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 12 - _TC")
self.assertEqual(sales_invoice.items[0].item_tax_rate, item_tax_map)
# Apply discount
sales_invoice.apply_discount_on = "Net Total"
sales_invoice.discount_amount = 300
sales_invoice.save()
item_tax_map = get_item_tax_map(
company=sales_invoice.company,
item_tax_template=sales_invoice.items[0].item_tax_template,
)
self.assertEqual(sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 10 - _TC")
self.assertEqual(sales_invoice.items[0].item_tax_rate, item_tax_map)
@change_settings("Selling Settings", {"enable_discount_accounting": 1})
def test_sales_invoice_with_discount_accounting_enabled(self):
@@ -4024,6 +4047,204 @@ class TestSalesInvoice(FrappeTestCase):
self.assertTrue(all([x == "Credit Note" for x in gl_entries]))
def test_validation_on_opening_invoice_with_rounding(self):
si = create_sales_invoice(qty=1, rate=99.98, do_not_submit=True)
si.is_opening = "Yes"
si.items[0].income_account = "Temporary Opening - _TC"
si.save()
self.assertRaises(frappe.ValidationError, si.submit)
def _create_opening_roundoff_account(self, company_name):
liability_root = frappe.db.get_all(
"Account",
filters={"company": company_name, "root_type": "Liability", "disabled": 0},
order_by="lft",
limit=1,
)[0]
# setup round off account
if acc := frappe.db.exists(
"Account",
{
"account_name": "Round Off for Opening",
"account_type": "Round Off for Opening",
"company": company_name,
},
):
frappe.db.set_value("Company", company_name, "round_off_for_opening", acc)
else:
acc = frappe.new_doc("Account")
acc.company = company_name
acc.parent_account = liability_root.name
acc.account_name = "Round Off for Opening"
acc.account_type = "Round Off for Opening"
acc.save()
frappe.db.set_value("Company", company_name, "round_off_for_opening", acc.name)
def test_opening_invoice_with_rounding_adjustment(self):
si = create_sales_invoice(qty=1, rate=99.98, do_not_submit=True)
si.is_opening = "Yes"
si.items[0].income_account = "Temporary Opening - _TC"
si.save()
self._create_opening_roundoff_account(si.company)
si.reload()
si.submit()
res = frappe.db.get_all(
"GL Entry",
filters={"voucher_no": si.name, "is_opening": "Yes"},
fields=["account", "debit", "credit", "is_opening"],
)
self.assertEqual(len(res), 3)
def _create_opening_invoice_with_inclusive_tax(self):
si = create_sales_invoice(qty=1, rate=90, do_not_submit=True)
si.is_opening = "Yes"
si.items[0].income_account = "Temporary Opening - _TC"
item_template = si.items[0].as_dict()
item_template.name = None
item_template.rate = 55
si.append("items", item_template)
si.append(
"taxes",
{
"charge_type": "On Net Total",
"account_head": "_Test Account Service Tax - _TC",
"cost_center": "_Test Cost Center - _TC",
"description": "Testing...",
"rate": 5,
"included_in_print_rate": True,
},
)
# there will be 0.01 precision loss between Dr and Cr
# caused by 'included_in_print_tax' option
si.save()
return si
def test_rounding_validation_for_opening_with_inclusive_tax(self):
si = self._create_opening_invoice_with_inclusive_tax()
# 'Round Off for Opening' not set in Company master
# Ledger level validation must be thrown
self.assertRaises(frappe.ValidationError, si.submit)
def test_ledger_entries_on_opening_invoice_with_rounding_loss_by_inclusive_tax(self):
si = self._create_opening_invoice_with_inclusive_tax()
# 'Round Off for Opening' is set in Company master
self._create_opening_roundoff_account(si.company)
si.submit()
actual = frappe.db.get_all(
"GL Entry",
filters={"voucher_no": si.name, "is_opening": "Yes", "is_cancelled": False},
fields=["account", "debit", "credit", "is_opening"],
order_by="account,debit",
)
expected = [
{"account": "_Test Account Service Tax - _TC", "debit": 0.0, "credit": 6.9, "is_opening": "Yes"},
{"account": "Debtors - _TC", "debit": 145.0, "credit": 0.0, "is_opening": "Yes"},
{"account": "Round Off for Opening - _TC", "debit": 0.0, "credit": 0.01, "is_opening": "Yes"},
{"account": "Temporary Opening - _TC", "debit": 0.0, "credit": 138.09, "is_opening": "Yes"},
]
self.assertEqual(len(actual), 4)
self.assertEqual(expected, actual)
@change_settings("Accounts Settings", {"enable_common_party_accounting": True})
def test_common_party_with_different_currency_in_debtor_and_creditor(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 INR",
parent_account="Accounts Payable - _TC",
company="_Test Company",
account_currency="INR",
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 INR").name
supp_doc = frappe.get_doc("Supplier", supplier)
supp_doc.default_currency = "INR"
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_total_billed_amount(self):
si = create_sales_invoice(do_not_submit=True)
project = frappe.new_doc("Project")
project.project_name = "Test Total Billed Amount"
project.save()
si.project = project.name
si.save()
si.submit()
doc = frappe.get_doc("Project", project.name)
self.assertEqual(doc.total_billed_amount, si.grand_total)
def set_advance_flag(company, flag, default_account):
frappe.db.set_value(

View File

@@ -14,7 +14,8 @@
"advance_amount",
"allocated_amount",
"exchange_gain_loss",
"ref_exchange_rate"
"ref_exchange_rate",
"difference_posting_date"
],
"fields": [
{
@@ -30,7 +31,7 @@
"width": "250px"
},
{
"columns": 3,
"columns": 2,
"fieldname": "reference_name",
"fieldtype": "Dynamic Link",
"in_list_view": 1,
@@ -41,7 +42,7 @@
"read_only": 1
},
{
"columns": 3,
"columns": 2,
"fieldname": "remarks",
"fieldtype": "Text",
"in_list_view": 1,
@@ -112,13 +113,20 @@
"label": "Reference Exchange Rate",
"non_negative": 1,
"read_only": 1
},
{
"columns": 2,
"fieldname": "difference_posting_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Difference Posting Date"
}
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-06-23 21:12:57.557731",
"modified": "2024-12-20 11:58:28.962370",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Advance",

View File

@@ -16,6 +16,7 @@ class SalesInvoiceAdvance(Document):
advance_amount: DF.Currency
allocated_amount: DF.Currency
difference_posting_date: DF.Date | None
exchange_gain_loss: DF.Currency
parent: DF.Data
parentfield: DF.Data

View File

@@ -89,11 +89,14 @@
"incoming_rate",
"item_tax_rate",
"actual_batch_qty",
"actual_qty",
"section_break_eoec",
"serial_no",
"column_break_ytgd",
"batch_no",
"available_quantity_section",
"actual_qty",
"column_break_ogff",
"company_total_stock",
"edit_references",
"sales_order",
"so_detail",
@@ -675,7 +678,8 @@
"allow_on_submit": 1,
"fieldname": "actual_qty",
"fieldtype": "Float",
"label": "Available Qty at Warehouse",
"label": "Qty (Warehouse)",
"no_copy": 1,
"oldfieldname": "actual_qty",
"oldfieldtype": "Currency",
"print_hide": 1,
@@ -923,12 +927,30 @@
{
"fieldname": "column_break_ytgd",
"fieldtype": "Column Break"
},
{
"fieldname": "available_quantity_section",
"fieldtype": "Section Break",
"label": "Available Quantity"
},
{
"fieldname": "column_break_ogff",
"fieldtype": "Column Break"
},
{
"allow_on_submit": 1,
"fieldname": "company_total_stock",
"fieldtype": "Float",
"label": "Qty (Company)",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-10-28 15:06:40.980995",
"modified": "2024-11-25 16:27:33.287341",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",

View File

@@ -28,6 +28,7 @@ class SalesInvoiceItem(Document):
base_rate_with_margin: DF.Currency
batch_no: DF.Link | None
brand: DF.Data | None
company_total_stock: DF.Float
conversion_factor: DF.Float
cost_center: DF.Link
customer_item_code: DF.Data | None

View File

@@ -247,14 +247,14 @@ def get_tax_row_for_tds(tax_details, tax_amount):
}
def get_lower_deduction_certificate(company, tax_details, pan_no):
def get_lower_deduction_certificate(company, posting_date, tax_details, pan_no):
ldc_name = frappe.db.get_value(
"Lower Deduction Certificate",
{
"pan_no": pan_no,
"tax_withholding_category": tax_details.tax_withholding_category,
"valid_from": (">=", tax_details.from_date),
"valid_upto": ("<=", tax_details.to_date),
"valid_from": ("<=", posting_date),
"valid_upto": (">=", posting_date),
"company": company,
},
"name",
@@ -302,7 +302,7 @@ def get_tax_amount(party_type, parties, inv, tax_details, posting_date, pan_no=N
tax_amount = 0
if party_type == "Supplier":
ldc = get_lower_deduction_certificate(inv.company, tax_details, pan_no)
ldc = get_lower_deduction_certificate(inv.company, posting_date, tax_details, pan_no)
if tax_deducted:
net_total = inv.tax_withholding_net_total
if ldc:
@@ -539,7 +539,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
)
supp_credit_amt = supp_jv_credit_amt
supp_credit_amt += inv.tax_withholding_net_total
supp_credit_amt += inv.get("tax_withholding_net_total", 0)
for type in payment_entry_amounts:
if type.payment_type == "Pay":
@@ -551,9 +551,9 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
cumulative_threshold = tax_details.get("cumulative_threshold", 0)
if inv.doctype != "Payment Entry":
tax_withholding_net_total = inv.base_tax_withholding_net_total
tax_withholding_net_total = inv.get("base_tax_withholding_net_total", 0)
else:
tax_withholding_net_total = inv.tax_withholding_net_total
tax_withholding_net_total = inv.get("tax_withholding_net_total", 0)
if (threshold and tax_withholding_net_total >= threshold) or (
cumulative_threshold and (supp_credit_amt + supp_inv_credit_amt) >= cumulative_threshold
@@ -568,7 +568,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
if (cumulative_threshold and supp_credit_amt >= cumulative_threshold) and cint(
tax_details.tax_on_excess_amount
):
supp_credit_amt = net_total - cumulative_threshold
supp_credit_amt = net_total + tax_withholding_net_total - cumulative_threshold
if ldc and is_valid_certificate(ldc, inv.get("posting_date") or inv.get("transaction_date"), 0):
tds_amount = get_lower_deduction_amount(

View File

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

View File

@@ -262,6 +262,7 @@ class TestUnreconcilePayment(AccountsTestMixin, FrappeTestCase):
pe1.paid_from = self.debtors_usd
pe1.paid_from_account_currency = "USD"
pe1.source_exchange_rate = 75
pe1.paid_amount = 100
pe1.received_amount = 75 * 100
pe1.save()
# Allocate payment against both invoices
@@ -279,6 +280,7 @@ class TestUnreconcilePayment(AccountsTestMixin, FrappeTestCase):
pe2.paid_from = self.debtors_usd
pe2.paid_from_account_currency = "USD"
pe2.source_exchange_rate = 75
pe2.paid_amount = 100
pe2.received_amount = 75 * 100
pe2.save()
# Allocate payment against both invoices

View File

@@ -7,7 +7,7 @@ import copy
import frappe
from frappe import _
from frappe.model.meta import get_field_precision
from frappe.utils import cint, flt, formatdate, getdate, now
from frappe.utils import cint, flt, formatdate, get_link_to_form, getdate, now
import erpnext
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
@@ -234,6 +234,10 @@ def merge_similar_entries(gl_map, precision=None):
merge_properties = get_merge_properties(accounting_dimensions)
for entry in gl_map:
if entry._skip_merge:
merged_gl_map.append(entry)
continue
entry.merge_key = get_merge_key(entry, merge_properties)
# if there is already an entry in this account then just add it
# to that entry
@@ -311,66 +315,48 @@ def check_if_in_list(gle, gl_map):
def toggle_debit_credit_if_negative(gl_map):
debit_credit_field_map = {
"debit": "credit",
"debit_in_account_currency": "credit_in_account_currency",
"debit_in_transaction_currency": "credit_in_transaction_currency",
}
for entry in gl_map:
# toggle debit, credit if negative entry
if flt(entry.debit) < 0 and flt(entry.credit) < 0 and flt(entry.debit) == flt(entry.credit):
entry.credit *= -1
entry.debit *= -1
for debit_field, credit_field in debit_credit_field_map.items():
debit = flt(entry.get(debit_field))
credit = flt(entry.get(credit_field))
if (
flt(entry.debit_in_account_currency) < 0
and flt(entry.credit_in_account_currency) < 0
and flt(entry.debit_in_account_currency) == flt(entry.credit_in_account_currency)
):
entry.credit_in_account_currency *= -1
entry.debit_in_account_currency *= -1
if debit < 0 and credit < 0 and debit == credit:
debit *= -1
credit *= -1
if flt(entry.debit) < 0:
entry.credit = flt(entry.credit) - flt(entry.debit)
entry.debit = 0.0
if debit < 0:
credit = credit - debit
debit = 0.0
if flt(entry.debit_in_account_currency) < 0:
entry.credit_in_account_currency = flt(entry.credit_in_account_currency) - flt(
entry.debit_in_account_currency
)
entry.debit_in_account_currency = 0.0
if credit < 0:
debit = debit - credit
credit = 0.0
if flt(entry.credit) < 0:
entry.debit = flt(entry.debit) - flt(entry.credit)
entry.credit = 0.0
# update net values
# In some scenarios net value needs to be shown in the ledger
# This method updates net values as debit or credit
if entry.post_net_value and debit and credit:
if debit > credit:
debit = debit - credit
credit = 0.0
if flt(entry.credit_in_account_currency) < 0:
entry.debit_in_account_currency = flt(entry.debit_in_account_currency) - flt(
entry.credit_in_account_currency
)
entry.credit_in_account_currency = 0.0
else:
credit = credit - debit
debit = 0.0
update_net_values(entry)
entry[debit_field] = debit
entry[credit_field] = credit
return gl_map
def update_net_values(entry):
# In some scenarios net value needs to be shown in the ledger
# This method updates net values as debit or credit
if entry.post_net_value and entry.debit and entry.credit:
if entry.debit > entry.credit:
entry.debit = entry.debit - entry.credit
entry.debit_in_account_currency = (
entry.debit_in_account_currency - entry.credit_in_account_currency
)
entry.credit = 0
entry.credit_in_account_currency = 0
else:
entry.credit = entry.credit - entry.debit
entry.credit_in_account_currency = (
entry.credit_in_account_currency - entry.debit_in_account_currency
)
entry.debit = 0
entry.debit_in_account_currency = 0
def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
if not from_repost:
validate_cwip_accounts(gl_map)
@@ -492,16 +478,36 @@ def raise_debit_credit_not_equal_error(debit_credit_diff, voucher_type, voucher_
)
def has_opening_entries(gl_map: list) -> bool:
for x in gl_map:
if x.is_opening == "Yes":
return True
return False
def make_round_off_gle(gl_map, debit_credit_diff, precision):
round_off_account, round_off_cost_center = get_round_off_account_and_cost_center(
round_off_account, round_off_cost_center, round_off_for_opening = get_round_off_account_and_cost_center(
gl_map[0].company, gl_map[0].voucher_type, gl_map[0].voucher_no
)
round_off_gle = frappe._dict()
round_off_account_exists = False
has_opening_entry = has_opening_entries(gl_map)
if has_opening_entry:
if not round_off_for_opening:
frappe.throw(
_("Please set '{0}' in Company: {1}").format(
frappe.bold("Round Off for Opening"), get_link_to_form("Company", gl_map[0].company)
)
)
account = round_off_for_opening
else:
account = round_off_account
if gl_map[0].voucher_type != "Period Closing Voucher":
for d in gl_map:
if d.account == round_off_account:
if d.account == account:
round_off_gle = d
if d.debit:
debit_credit_diff -= flt(d.debit) - flt(d.credit)
@@ -519,7 +525,7 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
round_off_gle.update(
{
"account": round_off_account,
"account": account,
"debit_in_account_currency": abs(debit_credit_diff) if debit_credit_diff < 0 else 0,
"credit_in_account_currency": debit_credit_diff if debit_credit_diff > 0 else 0,
"debit": abs(debit_credit_diff) if debit_credit_diff < 0 else 0,
@@ -533,6 +539,9 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
}
)
if has_opening_entry:
round_off_gle.update({"is_opening": "Yes"})
update_accounting_dimensions(round_off_gle)
if not round_off_account_exists:
gl_map.append(round_off_gle)
@@ -557,9 +566,9 @@ def update_accounting_dimensions(round_off_gle):
def get_round_off_account_and_cost_center(company, voucher_type, voucher_no, use_company_default=False):
round_off_account, round_off_cost_center = frappe.get_cached_value(
"Company", company, ["round_off_account", "round_off_cost_center"]
) or [None, None]
round_off_account, round_off_cost_center, round_off_for_opening = frappe.get_cached_value(
"Company", company, ["round_off_account", "round_off_cost_center", "round_off_for_opening"]
) or [None, None, None]
# Use expense account as fallback
if not round_off_account:
@@ -574,12 +583,20 @@ def get_round_off_account_and_cost_center(company, voucher_type, voucher_no, use
round_off_cost_center = parent_cost_center
if not round_off_account:
frappe.throw(_("Please mention Round Off Account in Company"))
frappe.throw(
_("Please mention '{0}' in Company: {1}").format(
frappe.bold("Round Off Account"), get_link_to_form("Company", company)
)
)
if not round_off_cost_center:
frappe.throw(_("Please mention Round Off Cost Center in Company"))
frappe.throw(
_("Please mention '{0}' in Company: {1}").format(
frappe.bold("Round Off Cost Center"), get_link_to_form("Company", company)
)
)
return round_off_account, round_off_cost_center
return round_off_account, round_off_cost_center, round_off_for_opening
def make_reverse_gl_entries(

View File

@@ -4,13 +4,14 @@
"docstatus": 0,
"doctype": "Number Card",
"document_type": "Purchase Invoice",
"dynamic_filters_json": "[[\"Purchase Invoice\",\"company\",\"=\",\" frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Purchase Invoice\",\"docstatus\",\"=\",\"1\",false],[\"Purchase Invoice\",\"posting_date\",\"Timespan\",\"this year\",false]]",
"function": "Sum",
"idx": 0,
"is_public": 1,
"is_standard": 1,
"label": "Total Incoming Bills",
"modified": "2020-07-22 13:06:46.045344",
"modified": "2024-11-20 19:08:37.043777",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Total Incoming Bills",

View File

@@ -4,6 +4,7 @@
"docstatus": 0,
"doctype": "Number Card",
"document_type": "Payment Entry",
"dynamic_filters_json": "[[\"Payment Entry\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Payment Entry\",\"docstatus\",\"=\",\"1\",false],[\"Payment Entry\",\"posting_date\",\"Timespan\",\"this year\",false],[\"Payment Entry\",\"payment_type\",\"=\",\"Receive\",false]]",
"function": "Sum",
"idx": 0,

View File

@@ -4,6 +4,7 @@
"docstatus": 0,
"doctype": "Number Card",
"document_type": "Sales Invoice",
"dynamic_filters_json": "[[\"Sales Invoice\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Sales Invoice\",\"docstatus\",\"=\",\"1\",false],[\"Sales Invoice\",\"posting_date\",\"Timespan\",\"this year\",false]]",
"function": "Sum",
"idx": 0,

View File

@@ -4,6 +4,7 @@
"docstatus": 0,
"doctype": "Number Card",
"document_type": "Payment Entry",
"dynamic_filters_json": "[[\"Payment Entry\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Payment Entry\",\"docstatus\",\"=\",\"1\",false],[\"Payment Entry\",\"posting_date\",\"Timespan\",\"this year\",false],[\"Payment Entry\",\"payment_type\",\"=\",\"Pay\",false]]",
"function": "Sum",
"idx": 0,

View File

@@ -29,6 +29,12 @@ from erpnext.accounts.utils import get_fiscal_year
from erpnext.exceptions import InvalidAccountCurrency, PartyDisabled, PartyFrozen
from erpnext.utilities.regional import temporary_flag
try:
from frappe.contacts.doctype.address.address import render_address as _render_address
except ImportError:
# Older frappe versions where this function is not available
from frappe.contacts.doctype.address.address import get_address_display as _render_address
PURCHASE_TRANSACTION_TYPES = {
"Supplier Quotation",
"Purchase Order",
@@ -753,6 +759,20 @@ def validate_party_frozen_disabled(party_type, party_name):
frappe.msgprint(_("{0} {1} is not active").format(party_type, party_name), alert=True)
def validate_account_party_type(self):
if self.is_cancelled:
return
if self.party_type and self.party:
account_type = frappe.get_cached_value("Account", self.account, "account_type")
if account_type and (account_type not in ["Receivable", "Payable"]):
frappe.throw(
_(
"Party Type and Party can only be set for Receivable / Payable account<br><br>" "{0}"
).format(self.account)
)
def get_dashboard_info(party_type, party, loyalty_program=None):
current_fiscal_year = get_fiscal_year(nowdate(), as_dict=True)
@@ -982,10 +1002,4 @@ def add_party_account(party_type, party, company, account):
def render_address(address, check_permissions=True):
try:
from frappe.contacts.doctype.address.address import render_address as _render
except ImportError:
# Older frappe versions where this function is not available
from frappe.contacts.doctype.address.address import get_address_display as _render
return frappe.call(_render, address, check_permissions=check_permissions)
return frappe.call(_render_address, address, check_permissions=check_permissions)

View File

@@ -134,7 +134,6 @@ class ReceivablePayableReport:
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):
@@ -150,6 +149,9 @@ class ReceivablePayableReport:
if key not in self.voucher_balance:
self.voucher_balance[key] = self.build_voucher_dict(ple)
if ple.voucher_type == ple.against_voucher_type and ple.voucher_no == ple.against_voucher_no:
self.voucher_balance[key].cost_center = ple.cost_center
self.get_invoices(ple)
if self.filters.get("group_by_party"):
@@ -275,9 +277,6 @@ class ReceivablePayableReport:
row.paid -= amount
row.paid_in_account_currency -= amount_in_account_currency
if not row.cost_center and ple.cost_center:
row.cost_center = str(ple.cost_center)
def update_sub_total_row(self, row, party):
total_row = self.total_row_map.get(party)
@@ -551,9 +550,7 @@ class ReceivablePayableReport:
self.append_payment_term(row, d, term)
def append_payment_term(self, row, d, term):
if (
self.filters.get("customer") or self.filters.get("supplier")
) and d.currency == d.party_account_currency:
if d.currency == d.party_account_currency:
invoiced = d.payment_amount
else:
invoiced = d.base_payment_amount
@@ -1013,22 +1010,29 @@ class ReceivablePayableReport:
def get_columns(self):
self.columns = []
self.add_column("Posting Date", fieldtype="Date")
self.add_column(_("Posting Date"), fieldname="posting_date", fieldtype="Date")
self.add_column(
label="Party Type",
label=_("Party Type"),
fieldname="party_type",
fieldtype="Data",
width=100,
)
self.add_column(
label="Party",
label=_("Party"),
fieldname="party",
fieldtype="Dynamic Link",
options="party_type",
width=180,
)
if self.account_type == "Receivable":
label = _("Receivable Account")
elif self.account_type == "Payable":
label = _("Payable Account")
else:
label = _("Party Account")
self.add_column(
label=self.account_type + " Account",
label=label,
fieldname="party_account",
fieldtype="Link",
options="Account",
@@ -1037,10 +1041,10 @@ class ReceivablePayableReport:
if self.party_naming_by == "Naming Series":
if self.account_type == "Payable":
label = "Supplier Name"
label = _("Supplier Name")
fieldname = "supplier_name"
else:
label = "Customer Name"
label = _("Customer Name")
fieldname = "customer_name"
self.add_column(
label=label,
@@ -1066,7 +1070,7 @@ class ReceivablePayableReport:
width=180,
)
self.add_column(label="Due Date", fieldtype="Date")
self.add_column(label=_("Due Date"), fieldname="due_date", fieldtype="Date")
if self.account_type == "Payable":
self.add_column(label=_("Bill No"), fieldname="bill_no", fieldtype="Data")

View File

@@ -89,7 +89,9 @@ def get_data(filters):
& (DepreciationSchedule.schedule_date == d.posting_date)
)
).run(as_dict=True)
asset_data.accumulated_depreciation_amount = query[0]["accumulated_depreciation_amount"]
asset_data.accumulated_depreciation_amount = (
query[0]["accumulated_depreciation_amount"] if query else 0
)
else:
asset_data.accumulated_depreciation_amount += d.debit

View File

@@ -28,15 +28,14 @@ def get_group_by_asset_category_data(filters):
for asset_category in asset_categories:
row = frappe._dict()
# row.asset_category = asset_category
row.update(asset_category)
row.cost_as_on_to_date = (
flt(row.cost_as_on_from_date)
+ flt(row.cost_of_new_purchase)
- flt(row.cost_of_sold_asset)
- flt(row.cost_of_scrapped_asset)
- flt(row.cost_of_capitalized_asset)
row.value_as_on_to_date = (
flt(row.value_as_on_from_date)
+ flt(row.value_of_new_purchase)
- flt(row.value_of_sold_asset)
- flt(row.value_of_scrapped_asset)
- flt(row.value_of_capitalized_asset)
)
row.update(
@@ -53,11 +52,11 @@ def get_group_by_asset_category_data(filters):
- flt(row.depreciation_eliminated_during_the_period)
)
row.net_asset_value_as_on_from_date = flt(row.cost_as_on_from_date) - flt(
row.net_asset_value_as_on_from_date = flt(row.value_as_on_from_date) - flt(
row.accumulated_depreciation_as_on_from_date
)
row.net_asset_value_as_on_to_date = flt(row.cost_as_on_to_date) - flt(
row.net_asset_value_as_on_to_date = flt(row.value_as_on_to_date) - flt(
row.accumulated_depreciation_as_on_to_date
)
@@ -85,12 +84,12 @@ def get_asset_categories_for_grouped_by_category(filters):
end
else
0
end), 0) as cost_as_on_from_date,
end), 0) as value_as_on_from_date,
ifnull(sum(case when a.purchase_date >= %(from_date)s then
a.gross_purchase_amount
else
0
end), 0) as cost_of_new_purchase,
end), 0) as value_of_new_purchase,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0
and a.disposal_date >= %(from_date)s
and a.disposal_date <= %(to_date)s then
@@ -101,7 +100,7 @@ def get_asset_categories_for_grouped_by_category(filters):
end
else
0
end), 0) as cost_of_sold_asset,
end), 0) as value_of_sold_asset,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0
and a.disposal_date >= %(from_date)s
and a.disposal_date <= %(to_date)s then
@@ -112,7 +111,7 @@ def get_asset_categories_for_grouped_by_category(filters):
end
else
0
end), 0) as cost_of_scrapped_asset,
end), 0) as value_of_scrapped_asset,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0
and a.disposal_date >= %(from_date)s
and a.disposal_date <= %(to_date)s then
@@ -123,7 +122,7 @@ def get_asset_categories_for_grouped_by_category(filters):
end
else
0
end), 0) as cost_of_capitalized_asset
end), 0) as value_of_capitalized_asset
from `tabAsset` a
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s {condition}
and not exists(
@@ -164,12 +163,12 @@ def get_asset_details_for_grouped_by_category(filters):
end
else
0
end), 0) as cost_as_on_from_date,
end), 0) as value_as_on_from_date,
ifnull(sum(case when a.purchase_date >= %(from_date)s then
a.gross_purchase_amount
else
0
end), 0) as cost_of_new_purchase,
end), 0) as value_of_new_purchase,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0
and a.disposal_date >= %(from_date)s
and a.disposal_date <= %(to_date)s then
@@ -180,7 +179,7 @@ def get_asset_details_for_grouped_by_category(filters):
end
else
0
end), 0) as cost_of_sold_asset,
end), 0) as value_of_sold_asset,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0
and a.disposal_date >= %(from_date)s
and a.disposal_date <= %(to_date)s then
@@ -191,7 +190,7 @@ def get_asset_details_for_grouped_by_category(filters):
end
else
0
end), 0) as cost_of_scrapped_asset,
end), 0) as value_of_scrapped_asset,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0
and a.disposal_date >= %(from_date)s
and a.disposal_date <= %(to_date)s then
@@ -202,7 +201,7 @@ def get_asset_details_for_grouped_by_category(filters):
end
else
0
end), 0) as cost_of_capitalized_asset
end), 0) as value_of_capitalized_asset
from `tabAsset` a
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s {condition}
and not exists(
@@ -232,15 +231,14 @@ def get_group_by_asset_data(filters):
for asset_detail in asset_details:
row = frappe._dict()
# row.asset_category = asset_category
row.update(asset_detail)
row.cost_as_on_to_date = (
flt(row.cost_as_on_from_date)
+ flt(row.cost_of_new_purchase)
- flt(row.cost_of_sold_asset)
- flt(row.cost_of_scrapped_asset)
- flt(row.cost_of_capitalized_asset)
row.value_as_on_to_date = (
flt(row.value_as_on_from_date)
+ flt(row.value_of_new_purchase)
- flt(row.value_of_sold_asset)
- flt(row.value_of_scrapped_asset)
- flt(row.value_of_capitalized_asset)
)
row.update(next(asset for asset in assets if asset["asset"] == asset_detail.get("name", "")))
@@ -251,11 +249,11 @@ def get_group_by_asset_data(filters):
- flt(row.depreciation_eliminated_during_the_period)
)
row.net_asset_value_as_on_from_date = flt(row.cost_as_on_from_date) - flt(
row.net_asset_value_as_on_from_date = flt(row.value_as_on_from_date) - flt(
row.accumulated_depreciation_as_on_from_date
)
row.net_asset_value_as_on_to_date = flt(row.cost_as_on_to_date) - flt(
row.net_asset_value_as_on_to_date = flt(row.value_as_on_to_date) - flt(
row.accumulated_depreciation_as_on_to_date
)
@@ -446,38 +444,38 @@ def get_columns(filters):
columns += [
{
"label": _("Cost as on") + " " + formatdate(filters.day_before_from_date),
"fieldname": "cost_as_on_from_date",
"label": _("Value as on") + " " + formatdate(filters.day_before_from_date),
"fieldname": "value_as_on_from_date",
"fieldtype": "Currency",
"width": 140,
},
{
"label": _("Cost of New Purchase"),
"fieldname": "cost_of_new_purchase",
"label": _("Value of New Purchase"),
"fieldname": "value_of_new_purchase",
"fieldtype": "Currency",
"width": 140,
},
{
"label": _("Cost of Sold Asset"),
"fieldname": "cost_of_sold_asset",
"label": _("Value of Sold Asset"),
"fieldname": "value_of_sold_asset",
"fieldtype": "Currency",
"width": 140,
},
{
"label": _("Cost of Scrapped Asset"),
"fieldname": "cost_of_scrapped_asset",
"label": _("Value of Scrapped Asset"),
"fieldname": "value_of_scrapped_asset",
"fieldtype": "Currency",
"width": 140,
},
{
"label": _("Cost of New Capitalized Asset"),
"fieldname": "cost_of_capitalized_asset",
"label": _("Value of New Capitalized Asset"),
"fieldname": "value_of_capitalized_asset",
"fieldtype": "Currency",
"width": 140,
},
{
"label": _("Cost as on") + " " + formatdate(filters.to_date),
"fieldname": "cost_as_on_to_date",
"label": _("Value as on") + " " + formatdate(filters.to_date),
"fieldname": "value_as_on_to_date",
"fieldtype": "Currency",
"width": 140,
},

View File

@@ -7,6 +7,7 @@ from frappe import _
from frappe.utils import cint, flt
from erpnext.accounts.report.financial_statements import (
compute_growth_view_data,
get_columns,
get_data,
get_filtered_list_for_consolidated_report,
@@ -101,6 +102,9 @@ def execute(filters=None):
period_list, asset, liability, equity, provisional_profit_loss, currency, filters
)
if filters.get("selected_view") == "Growth":
compute_growth_view_data(data, period_list)
return columns, data, message, chart, report_summary, primitive_summary

View File

@@ -142,7 +142,8 @@ def get_journal_entries(filters):
where jvd.parent = jv.name and jv.docstatus=1
and jvd.account = %(account)s and jv.posting_date <= %(report_date)s
and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s
and ifnull(jv.is_opening, 'No') = 'No'""",
and ifnull(jv.is_opening, 'No') = 'No'
and jv.company = %(company)s """,
filters,
as_dict=1,
)
@@ -163,6 +164,7 @@ def get_payment_entries(filters):
(paid_from=%(account)s or paid_to=%(account)s) and docstatus=1
and posting_date <= %(report_date)s
and ifnull(clearance_date, '4000-01-01') > %(report_date)s
and company = %(company)s
""",
filters,
as_dict=1,
@@ -181,6 +183,7 @@ def get_pos_entries(filters):
sip.account=%(account)s and si.docstatus=1 and sip.parent = si.name
and account.name = sip.account and si.posting_date <= %(report_date)s and
ifnull(sip.clearance_date, '4000-01-01') > %(report_date)s
and si.company = %(company)s
order by
si.posting_date ASC, si.name DESC
""",

View File

@@ -1,7 +1,10 @@
// Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Cash Flow"] = $.extend({}, erpnext.financial_statements);
frappe.query_reports["Cash Flow"] = $.extend(erpnext.financial_statements, {
name_field: "section",
parent_field: "parent_section",
});
erpnext.utils.add_dimensions("Cash Flow", 10);

View File

@@ -30,7 +30,7 @@ def execute(filters=None):
company=filters.company,
)
cash_flow_accounts = get_cash_flow_accounts()
cash_flow_sections = get_cash_flow_accounts()
# compute net profit / loss
income = get_data(
@@ -60,14 +60,14 @@ def execute(filters=None):
summary_data = {}
company_currency = frappe.get_cached_value("Company", filters.company, "default_currency")
for cash_flow_account in cash_flow_accounts:
for cash_flow_section in cash_flow_sections:
section_data = []
data.append(
{
"account_name": cash_flow_account["section_header"],
"parent_account": None,
"section_name": "'" + cash_flow_section["section_header"] + "'",
"parent_section": None,
"indent": 0.0,
"account": cash_flow_account["section_header"],
"section": cash_flow_section["section_header"],
}
)
@@ -75,31 +75,40 @@ def execute(filters=None):
# add first net income in operations section
if net_profit_loss:
net_profit_loss.update(
{"indent": 1, "parent_account": cash_flow_accounts[0]["section_header"]}
{"indent": 1, "parent_section": cash_flow_sections[0]["section_header"]}
)
data.append(net_profit_loss)
section_data.append(net_profit_loss)
for account in cash_flow_account["account_types"]:
account_data = get_account_type_based_data(
filters.company, account["account_type"], period_list, filters.accumulated_values, filters
for row in cash_flow_section["account_types"]:
row_data = get_account_type_based_data(
filters.company, row["account_type"], period_list, filters.accumulated_values, filters
)
account_data.update(
accounts = frappe.get_all(
"Account",
filters={
"account_type": row["account_type"],
"is_group": 0,
},
pluck="name",
)
row_data.update(
{
"account_name": account["label"],
"account": account["label"],
"section_name": row["label"],
"section": row["label"],
"indent": 1,
"parent_account": cash_flow_account["section_header"],
"accounts": accounts,
"parent_section": cash_flow_section["section_header"],
"currency": company_currency,
}
)
data.append(account_data)
section_data.append(account_data)
data.append(row_data)
section_data.append(row_data)
add_total_row_account(
data,
section_data,
cash_flow_account["section_footer"],
cash_flow_section["section_footer"],
period_list,
company_currency,
summary_data,
@@ -109,7 +118,7 @@ def execute(filters=None):
add_total_row_account(
data, data, _("Net Change in Cash"), period_list, company_currency, summary_data, filters
)
columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company)
columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company, True)
chart = get_chart_data(columns, data, company_currency)
@@ -217,8 +226,8 @@ def get_start_date(period, accumulated_values, company):
def add_total_row_account(out, data, label, period_list, currency, summary_data, filters, consolidated=False):
total_row = {
"account_name": "'" + _("{0}").format(label) + "'",
"account": "'" + _("{0}").format(label) + "'",
"section_name": "'" + _("{0}").format(label) + "'",
"section": "'" + _("{0}").format(label) + "'",
"currency": currency,
}
@@ -229,7 +238,7 @@ def add_total_row_account(out, data, label, period_list, currency, summary_data,
period_list = get_filtered_list_for_consolidated_report(filters, period_list)
for row in data:
if row.get("parent_account"):
if row.get("parent_section"):
for period in period_list:
key = period if consolidated else period["key"]
total_row.setdefault(key, 0.0)
@@ -254,13 +263,14 @@ def get_report_summary(summary_data, currency):
def get_chart_data(columns, data, currency):
labels = [d.get("label") for d in columns[2:]]
print(data)
datasets = [
{
"name": account.get("account").replace("'", ""),
"values": [account.get(d.get("fieldname")) for d in columns[2:]],
"name": section.get("section").replace("'", ""),
"values": [section.get(d.get("fieldname")) for d in columns[2:]],
}
for account in data
if account.get("parent_account") is None and account.get("currency")
for section in data
if section.get("parent_section") is None and section.get("currency")
]
datasets = datasets[:-1]

View File

@@ -350,7 +350,7 @@ def get_data(companies, root_type, balance_must_be, fiscal_year, filters=None, i
gl_entries_by_account,
accounts_by_name,
accounts,
ignore_closing_entries=False,
ignore_closing_entries=ignore_closing_entries,
root_type=root_type,
)

View File

@@ -2,6 +2,7 @@
# License: GNU General Public License v3. See license.txt
import copy
import functools
import math
import re
@@ -334,8 +335,8 @@ def filter_out_zero_value_rows(data, parent_children_map, show_zero_values=False
def add_total_row(out, root_type, balance_must_be, period_list, company_currency):
total_row = {
"account_name": _("Total {0} ({1})").format(_(root_type), _(balance_must_be)),
"account": _("Total {0} ({1})").format(_(root_type), _(balance_must_be)),
"account_name": "'" + _("Total {0} ({1})").format(_(root_type), _(balance_must_be)) + "'",
"account": "'" + _("Total {0} ({1})").format(_(root_type), _(balance_must_be)) + "'",
"currency": company_currency,
"opening_balance": 0.0,
}
@@ -526,9 +527,15 @@ def get_accounting_entries(
account_filter_query = get_account_filter_query(root_lft, root_rgt, root_type, gl_entry)
query = query.where(ExistsCriterion(account_filter_query))
entries = query.run(as_dict=True)
from frappe.desk.reportview import build_match_conditions
return entries
query, params = query.walk()
match_conditions = build_match_conditions(doctype)
if match_conditions:
query += "and" + match_conditions
return frappe.db.sql(query, params, as_dict=True)
def get_account_filter_query(root_lft, root_rgt, root_type, gl_entry):
@@ -616,11 +623,11 @@ def get_cost_centers_with_children(cost_centers):
return list(set(all_cost_centers))
def get_columns(periodicity, period_list, accumulated_values=1, company=None):
def get_columns(periodicity, period_list, accumulated_values=1, company=None, cash_flow=False):
columns = [
{
"fieldname": "account",
"label": _("Account"),
"label": _("Account") if not cash_flow else _("Section"),
"fieldtype": "Link",
"options": "Account",
"width": 300,
@@ -668,3 +675,67 @@ def get_filtered_list_for_consolidated_report(filters, period_list):
filtered_summary_list.append(period)
return filtered_summary_list
def compute_growth_view_data(data, columns):
data_copy = copy.deepcopy(data)
for row_idx in range(len(data_copy)):
for column_idx in range(1, len(columns)):
previous_period_key = columns[column_idx - 1].get("key")
current_period_key = columns[column_idx].get("key")
current_period_value = data_copy[row_idx].get(current_period_key)
previous_period_value = data_copy[row_idx].get(previous_period_key)
annual_growth = 0
if current_period_value is None:
data[row_idx][current_period_key] = None
continue
if previous_period_value == 0 and current_period_value > 0:
annual_growth = 1
elif previous_period_value > 0:
annual_growth = (current_period_value - previous_period_value) / previous_period_value
growth_percent = round(annual_growth * 100, 2)
data[row_idx][current_period_key] = growth_percent
def compute_margin_view_data(data, columns, accumulated_values):
if not columns:
return
if not accumulated_values:
columns.append({"key": "total"})
data_copy = copy.deepcopy(data)
base_row = None
for row in data_copy:
if row.get("account_name") == _("Income"):
base_row = row
break
if not base_row:
return
for row_idx in range(len(data_copy)):
# Taking the total income from each column (for all the financial years) as the base (100%)
row = data_copy[row_idx]
if not row:
continue
for column in columns:
curr_period = column.get("key")
base_value = base_row[curr_period]
curr_value = row[curr_period]
if curr_value is None or base_value <= 0:
data[row_idx][curr_period] = None
continue
margin_percent = round((curr_value / base_value) * 100, 2)
data[row_idx][curr_period] = margin_percent

View File

@@ -35,9 +35,6 @@ def execute(filters=None):
if filters.get("party"):
filters.party = frappe.parse_json(filters.get("party"))
if filters.get("voucher_no") and not filters.get("group_by"):
filters.group_by = "Group by Voucher (Consolidated)"
validate_filters(filters, account_details)
validate_party(filters)
@@ -373,16 +370,21 @@ def get_data_with_opening_closing(filters, account_details, accounting_dimension
if acc_dict.entries:
# opening
data.append({"debit_in_transaction_currency": None, "credit_in_transaction_currency": None})
if filters.get("group_by") != "Group by Voucher":
if (not filters.get("group_by") and not filters.get("voucher_no")) or (
filters.get("group_by") and filters.get("group_by") != "Group by Voucher"
):
data.append(acc_dict.totals.opening)
data += acc_dict.entries
# totals
data.append(acc_dict.totals.total)
if filters.get("group_by") or not filters.voucher_no:
data.append(acc_dict.totals.total)
# closing
if filters.get("group_by") != "Group by Voucher":
if (not filters.get("group_by") and not filters.get("voucher_no")) or (
filters.get("group_by") and filters.get("group_by") != "Group by Voucher"
):
data.append(acc_dict.totals.closing)
data.append({"debit_in_transaction_currency": None, "credit_in_transaction_currency": None})

View File

@@ -421,10 +421,10 @@ class GrossProfitGenerator:
self.load_invoice_items()
self.get_delivery_notes()
self.load_product_bundle()
if filters.group_by == "Invoice":
self.group_items_by_invoice()
self.load_product_bundle()
self.load_non_stock_items()
self.get_returned_invoice_items()
self.process()
@@ -440,6 +440,7 @@ class GrossProfitGenerator:
if grouped_by_invoice:
buying_amount = 0
base_amount = 0
for row in reversed(self.si_list):
if self.filters.get("group_by") == "Monthly":
@@ -480,12 +481,11 @@ class GrossProfitGenerator:
else:
row.buying_amount = flt(self.get_buying_amount(row, row.item_code), self.currency_precision)
if grouped_by_invoice:
if row.indent == 1.0:
buying_amount += row.buying_amount
elif row.indent == 0.0:
row.buying_amount = buying_amount
buying_amount = 0
if grouped_by_invoice and row.indent == 0.0:
row.buying_amount = buying_amount
row.base_amount = base_amount
buying_amount = 0
base_amount = 0
# get buying rate
if flt(row.qty):
@@ -495,11 +495,19 @@ class GrossProfitGenerator:
if self.is_not_invoice_row(row):
row.buying_rate, row.base_rate = 0.0, 0.0
if self.is_not_invoice_row(row):
self.update_return_invoices(row)
if grouped_by_invoice and row.indent == 1.0:
buying_amount += row.buying_amount
base_amount += row.base_amount
# calculate gross profit
row.gross_profit = flt(row.base_amount - row.buying_amount, self.currency_precision)
if row.base_amount:
row.gross_profit_percent = flt(
(row.gross_profit / row.base_amount) * 100.0, self.currency_precision
(row.gross_profit / row.base_amount) * 100.0,
self.currency_precision,
)
else:
row.gross_profit_percent = 0.0
@@ -510,33 +518,29 @@ class GrossProfitGenerator:
if self.grouped:
self.get_average_rate_based_on_group_by()
def update_return_invoices(self, row):
if row.parent in self.returned_invoices and row.item_code in self.returned_invoices[row.parent]:
returned_item_rows = self.returned_invoices[row.parent][row.item_code]
for returned_item_row in returned_item_rows:
# returned_items 'qty' should be stateful
if returned_item_row.qty != 0:
if row.qty >= abs(returned_item_row.qty):
row.qty += returned_item_row.qty
row.base_amount += flt(returned_item_row.base_amount, self.currency_precision)
returned_item_row.qty = 0
returned_item_row.base_amount = 0
else:
row.qty = 0
row.base_amount = 0
returned_item_row.qty += row.qty
returned_item_row.base_amount += row.base_amount
row.buying_amount = flt(flt(row.qty) * flt(row.buying_rate), self.currency_precision)
def get_average_rate_based_on_group_by(self):
for key in list(self.grouped):
if self.filters.get("group_by") == "Invoice":
for row in self.grouped[key]:
if row.indent == 1.0:
if (
row.parent in self.returned_invoices
and row.item_code in self.returned_invoices[row.parent]
):
returned_item_rows = self.returned_invoices[row.parent][row.item_code]
for returned_item_row in returned_item_rows:
# returned_items 'qty' should be stateful
if returned_item_row.qty != 0:
if row.qty >= abs(returned_item_row.qty):
row.qty += returned_item_row.qty
returned_item_row.qty = 0
else:
row.qty = 0
returned_item_row.qty += row.qty
row.base_amount += flt(returned_item_row.base_amount, self.currency_precision)
row.buying_amount = flt(
flt(row.qty) * flt(row.buying_rate), self.currency_precision
)
if flt(row.qty) or row.base_amount:
row = self.set_average_rate(row)
self.grouped_data.append(row)
elif self.filters.get("group_by") == "Payment Term":
if self.filters.get("group_by") == "Payment Term":
for i, row in enumerate(self.grouped[key]):
invoice_portion = 0
@@ -556,7 +560,7 @@ class GrossProfitGenerator:
new_row = self.set_average_rate(new_row)
self.grouped_data.append(new_row)
else:
elif self.filters.get("group_by") != "Invoice":
for i, row in enumerate(self.grouped[key]):
if i == 0:
new_row = row
@@ -632,6 +636,8 @@ class GrossProfitGenerator:
if packed_item.get("parent_detail_docname") == row.item_row:
packed_item_row = row.copy()
packed_item_row.warehouse = packed_item.warehouse
packed_item_row.qty = packed_item.total_qty * -1
packed_item_row.serial_and_batch_bundle = packed_item.serial_and_batch_bundle
buying_amount += self.get_buying_amount(packed_item_row, packed_item.item_code)
return flt(buying_amount, self.currency_precision)
@@ -664,7 +670,9 @@ class GrossProfitGenerator:
else:
my_sle = self.get_stock_ledger_entries(item_code, row.warehouse)
if (row.update_stock or row.dn_detail) and my_sle:
parenttype, parent = row.parenttype, row.parent
parenttype = row.parenttype
parent = row.invoice or row.parent
if row.dn_detail:
parenttype, parent = "Delivery Note", row.delivery_note
@@ -721,6 +729,7 @@ class GrossProfitGenerator:
"voucher_no": row.parent,
"allow_zero_valuation": True,
"company": self.filters.company,
"item_code": item_code,
}
)
@@ -741,12 +750,13 @@ class GrossProfitGenerator:
.inner_join(purchase_invoice)
.on(purchase_invoice.name == purchase_invoice_item.parent)
.select(
purchase_invoice.name,
purchase_invoice_item.base_rate / purchase_invoice_item.conversion_factor,
)
.where(purchase_invoice.docstatus == 1)
.where(purchase_invoice.posting_date <= self.filters.to_date)
.where(purchase_invoice_item.item_code == item_code)
.where(purchase_invoice.is_return == 0)
.where(purchase_invoice_item.parenttype == "Purchase Invoice")
)
if row.project:
@@ -783,7 +793,10 @@ class GrossProfitGenerator:
"""
if self.filters.group_by == "Sales Person":
sales_person_cols = ", sales.sales_person, sales.allocated_amount, sales.incentives"
sales_person_cols = """, sales.sales_person,
sales.allocated_percentage * `tabSales Invoice Item`.base_net_amount / 100 as allocated_amount,
sales.incentives
"""
sales_team_table = "left join `tabSales Team` sales on sales.parent = `tabSales Invoice`.name"
else:
sales_person_cols = ""
@@ -847,6 +860,7 @@ class GrossProfitGenerator:
`tabSales Invoice`.project, `tabSales Invoice`.update_stock,
`tabSales Invoice`.customer, `tabSales Invoice`.customer_group,
`tabSales Invoice`.territory, `tabSales Invoice Item`.item_code,
`tabSales Invoice`.base_net_total as "invoice_base_net_total",
`tabSales Invoice Item`.item_name, `tabSales Invoice Item`.description,
`tabSales Invoice Item`.warehouse, `tabSales Invoice Item`.item_group,
`tabSales Invoice Item`.brand, `tabSales Invoice Item`.so_detail,
@@ -907,6 +921,7 @@ class GrossProfitGenerator:
"""
grouped = OrderedDict()
product_bundles = self.product_bundles.get("Sales Invoice", {})
for row in self.si_list:
# initialize list with a header row for each new parent
@@ -917,8 +932,7 @@ class GrossProfitGenerator:
)
# if item is a bundle, add it's components as seperate rows
if frappe.db.exists("Product Bundle", row.item_code):
bundled_items = self.get_bundle_items(row)
if bundled_items := product_bundles.get(row.parent, {}).get(row.item_code):
for x in bundled_items:
bundle_item = self.get_bundle_item_row(row, x)
grouped.get(row.parent).append(bundle_item)
@@ -954,47 +968,41 @@ class GrossProfitGenerator:
"item_row": None,
"is_return": row.is_return,
"cost_center": row.cost_center,
"base_net_amount": frappe.db.get_value("Sales Invoice", row.parent, "base_net_total"),
"base_net_amount": row.invoice_base_net_total,
}
)
def get_bundle_items(self, product_bundle):
return frappe.get_all(
"Product Bundle Item", filters={"parent": product_bundle.item_code}, fields=["item_code", "qty"]
)
def get_bundle_item_row(self, product_bundle, item):
item_name, description, item_group, brand = self.get_bundle_item_details(item.item_code)
def get_bundle_item_row(self, row, item):
return frappe._dict(
{
"parent_invoice": product_bundle.item_code,
"indent": product_bundle.indent + 1,
"parent_invoice": row.item_code,
"parenttype": row.parenttype,
"indent": row.indent + 1,
"parent": None,
"invoice_or_item": item.item_code,
"posting_date": product_bundle.posting_date,
"posting_time": product_bundle.posting_time,
"project": product_bundle.project,
"customer": product_bundle.customer,
"customer_group": product_bundle.customer_group,
"posting_date": row.posting_date,
"posting_time": row.posting_time,
"project": row.project,
"customer": row.customer,
"customer_group": row.customer_group,
"item_code": item.item_code,
"item_name": item_name,
"description": description,
"warehouse": product_bundle.warehouse,
"item_group": item_group,
"brand": brand,
"dn_detail": product_bundle.dn_detail,
"delivery_note": product_bundle.delivery_note,
"qty": (flt(product_bundle.qty) * flt(item.qty)),
"item_row": None,
"is_return": product_bundle.is_return,
"cost_center": product_bundle.cost_center,
"item_name": item.item_name,
"description": item.description,
"warehouse": item.warehouse or row.warehouse,
"update_stock": row.update_stock,
"item_group": "",
"brand": "",
"dn_detail": row.dn_detail,
"delivery_note": row.delivery_note,
"qty": item.total_qty * -1,
"item_row": row.item_row,
"is_return": row.is_return,
"cost_center": row.cost_center,
"invoice": row.parent,
"serial_and_batch_bundle": row.serial_and_batch_bundle,
}
)
def get_bundle_item_details(self, item_code):
return frappe.db.get_value("Item", item_code, ["item_name", "description", "item_group", "brand"])
def get_stock_ledger_entries(self, item_code, warehouse):
if item_code and warehouse:
if (item_code, warehouse) not in self.sle:
@@ -1043,6 +1051,7 @@ class GrossProfitGenerator:
pki.rate,
(pki.rate * pki.qty).as_("base_amount"),
pki.parent_detail_docname,
pki.serial_and_batch_bundle,
)
.where(pki.docstatus == 1)
)

View File

@@ -418,12 +418,12 @@ class TestGrossProfit(FrappeTestCase):
"item_name": self.item,
"warehouse": "Stores - _GP",
"qty": 0.0,
"avg._selling_rate": 0.0,
"avg._selling_rate": 100,
"valuation_rate": 0.0,
"selling_amount": -100.0,
"selling_amount": 0.0,
"buying_amount": 0.0,
"gross_profit": -100.0,
"gross_profit_%": 100.0,
"gross_profit": 0.0,
"gross_profit_%": 0.0,
}
gp_entry = [x for x in data if x.parent_invoice == sinv.name]
# Both items of Invoice should have '0' qty

View File

@@ -318,7 +318,7 @@ def get_columns(additional_table_columns, filters):
"width": 100,
},
{
"label": _("Rate"),
"label": _("Tax Rate"),
"fieldname": "rate",
"fieldtype": "Float",
"options": "currency",

View File

@@ -7,6 +7,8 @@ from frappe import _
from frappe.utils import flt
from erpnext.accounts.report.financial_statements import (
compute_growth_view_data,
compute_margin_view_data,
get_columns,
get_data,
get_filtered_list_for_consolidated_report,
@@ -68,6 +70,12 @@ def execute(filters=None):
period_list, filters.periodicity, income, expense, net_profit_loss, currency, filters
)
if filters.get("selected_view") == "Growth":
compute_growth_view_data(data, period_list)
if filters.get("selected_view") == "Margin":
compute_margin_view_data(data, period_list, filters.accumulated_values)
return columns, data, None, chart, report_summary, primitive_summary

View File

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

View File

@@ -70,10 +70,10 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_
rate = tax_rate_map.get(tax_withholding_category)
if net_total_map.get((voucher_type, name)):
if voucher_type == "Journal Entry":
if voucher_type == "Journal Entry" and tax_amount and rate:
# back calcalute total amount from rate and tax_amount
if rate:
total_amount = grand_total = base_total = tax_amount / (rate / 100)
base_total = min(tax_amount / (rate / 100), net_total_map.get((voucher_type, name))[0])
total_amount = grand_total = base_total
elif voucher_type == "Purchase Invoice":
total_amount, grand_total, base_total, bill_no, bill_date = net_total_map.get(
(voucher_type, name)
@@ -405,7 +405,7 @@ def get_doc_info(vouchers, doctype, tax_category_map, net_total_map=None):
"paid_amount_after_tax",
"base_paid_amount",
],
"Journal Entry": ["total_amount"],
"Journal Entry": ["tax_withholding_category", "total_debit"],
}
entries = frappe.get_all(
@@ -427,7 +427,7 @@ def get_doc_info(vouchers, doctype, tax_category_map, net_total_map=None):
elif doctype == "Payment Entry":
value = [entry.paid_amount, entry.paid_amount_after_tax, entry.base_paid_amount]
else:
value = [entry.total_amount] * 3
value = [entry.total_debit] * 3
net_total_map[(doctype, entry.name)] = value

View File

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

View File

@@ -92,14 +92,14 @@ class TestUtils(unittest.TestCase):
payment_entry.deductions = []
payment_entry.save()
# below is the difference between base_received_amount and base_paid_amount
self.assertEqual(payment_entry.difference_amount, -4855.0)
# below is the difference between base_paid_amount and base_received_amount (exchange gain)
self.assertEqual(payment_entry.deductions[0].amount, -4855.0)
payment_entry.target_exchange_rate = 62.9
payment_entry.save()
# below is due to change in exchange rate
self.assertEqual(payment_entry.references[0].exchange_gain_loss, -4855.0)
# after changing the exchange rate, there is no exchange gain / loss
self.assertEqual(payment_entry.deductions, [])
payment_entry.references = []
self.assertEqual(payment_entry.difference_amount, 0.0)

View File

@@ -130,7 +130,9 @@ def get_fiscal_years(
else:
return ((fy.name, fy.year_start_date, fy.year_end_date),)
error_msg = _("""{0} {1} is not in any active Fiscal Year""").format(label, formatdate(transaction_date))
error_msg = _("""{0} {1} is not in any active Fiscal Year""").format(
_(label), formatdate(transaction_date)
)
if company:
error_msg = _("""{0} for {1}""").format(error_msg, frappe.bold(company))
@@ -630,6 +632,16 @@ def update_reference_in_journal_entry(d, journal_entry, do_not_save=False):
if jv_detail.get("reference_type") in ["Sales Order", "Purchase Order"]:
update_advance_paid.append((jv_detail.reference_type, jv_detail.reference_name))
rev_dr_or_cr = (
"debit_in_account_currency"
if d["dr_or_cr"] == "credit_in_account_currency"
else "credit_in_account_currency"
)
if jv_detail.get(rev_dr_or_cr):
d["dr_or_cr"] = rev_dr_or_cr
d["allocated_amount"] = d["allocated_amount"] * -1
d["unadjusted_amount"] = d["unadjusted_amount"] * -1
if flt(d["unadjusted_amount"]) - flt(d["allocated_amount"]) != 0:
# adjust the unreconciled balance
amount_in_account_currency = flt(d["unadjusted_amount"]) - flt(d["allocated_amount"])

View File

@@ -416,7 +416,7 @@ frappe.ui.form.on("Asset", {
}
frm.dashboard.render_graph({
title: "Asset Value",
title: __("Asset Value"),
data: {
labels: x_intervals,
datasets: [

View File

@@ -19,6 +19,7 @@ from frappe.utils import (
)
import erpnext
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_dimensions
from erpnext.accounts.general_ledger import make_reverse_gl_entries
from erpnext.assets.doctype.asset.depreciation import (
get_comma_separated_links,
@@ -308,12 +309,14 @@ class Asset(AccountsController):
)
def validate_precision(self):
float_precision = cint(frappe.db.get_default("float_precision")) or 2
if self.gross_purchase_amount:
self.gross_purchase_amount = flt(self.gross_purchase_amount, float_precision)
self.gross_purchase_amount = flt(
self.gross_purchase_amount, self.precision("gross_purchase_amount")
)
if self.opening_accumulated_depreciation:
self.opening_accumulated_depreciation = flt(
self.opening_accumulated_depreciation, float_precision
self.opening_accumulated_depreciation, self.precision("opening_accumulated_depreciation")
)
def validate_asset_values(self):
@@ -410,6 +413,9 @@ class Asset(AccountsController):
)
def validate_asset_finance_books(self, row):
row.expected_value_after_useful_life = flt(
row.expected_value_after_useful_life, self.precision("gross_purchase_amount")
)
if flt(row.expected_value_after_useful_life) >= flt(self.gross_purchase_amount):
frappe.throw(
_("Row {0}: Expected Value After Useful Life must be less than Gross Purchase Amount").format(
@@ -430,7 +436,10 @@ class Asset(AccountsController):
self.opening_accumulated_depreciation = 0
self.opening_number_of_booked_depreciations = 0
else:
depreciable_amount = flt(self.gross_purchase_amount) - flt(row.expected_value_after_useful_life)
depreciable_amount = flt(
flt(self.gross_purchase_amount) - flt(row.expected_value_after_useful_life),
self.precision("gross_purchase_amount"),
)
if flt(self.opening_accumulated_depreciation) > depreciable_amount:
frappe.throw(
_("Opening Accumulated Depreciation must be less than or equal to {0}").format(
@@ -481,11 +490,7 @@ class Asset(AccountsController):
def validate_expected_value_after_useful_life(self):
for row in self.get("finance_books"):
row.expected_value_after_useful_life = flt(
row.expected_value_after_useful_life, self.precision("gross_purchase_amount")
)
depr_schedule = get_depr_schedule(self.name, "Draft", row.finance_book)
if not depr_schedule:
continue
@@ -798,6 +803,9 @@ class Asset(AccountsController):
):
return args.get("rate_of_depreciation")
if args.get("rate_of_depreciation") and not flt(args.get("expected_value_after_useful_life")):
return args.get("rate_of_depreciation")
if self.flags.increase_in_asset_value_due_to_repair:
value = flt(args.get("expected_value_after_useful_life")) / flt(
args.get("value_after_depreciation")
@@ -880,6 +888,7 @@ def get_asset_naming_series():
@frappe.whitelist()
def make_sales_invoice(asset, item_code, company, serial_no=None):
asset_doc = frappe.get_doc("Asset", asset)
si = frappe.new_doc("Sales Invoice")
si.company = company
si.currency = frappe.get_cached_value("Company", company, "default_currency")
@@ -896,6 +905,16 @@ def make_sales_invoice(asset, item_code, company, serial_no=None):
"qty": 1,
},
)
accounting_dimensions = get_dimensions(with_cost_center_and_project=True)
for dimension in accounting_dimensions[0]:
si.update(
{
dimension["fieldname"]: asset_doc.get(dimension["fieldname"])
or dimension.get("default_dimension")
}
)
si.set_missing_values()
return si

View File

@@ -889,7 +889,7 @@ class TestDepreciationMethods(AssetSetup):
["2030-12-31", 28630.14, 28630.14],
["2031-12-31", 35684.93, 64315.07],
["2032-12-31", 17842.46, 82157.53],
["2033-06-06", 5342.46, 87499.99],
["2033-06-06", 5342.47, 87500.00],
]
schedules = [

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