Compare commits

..

82 Commits

Author SHA1 Message Date
Frappe PR Bot
76ea858e72 chore(release): Bumped to Version 14.78.6
## [14.78.6](https://github.com/frappe/erpnext/compare/v14.78.5...v14.78.6) (2025-01-01)

### Bug Fixes

* apply apply_pricing_rule date change ([cca507f](cca507f0bd))
* clear payment schedule in purchase invoice for is_paid ([cdd3763](cdd3763a8b))
* duplicate validate for closing stock balance (backport [#45015](https://github.com/frappe/erpnext/issues/45015)) ([#45021](https://github.com/frappe/erpnext/issues/45021)) ([e2b6615](e2b6615e72))
* failing tests fixed ([498abf7](498abf7c83))
* get item tax template based on posting date ([56d0686](56d06861d0))
* load customer default price list in pos during item selection (backport [#44991](https://github.com/frappe/erpnext/issues/44991)) ([#44992](https://github.com/frappe/erpnext/issues/44992)) ([0f687f1](0f687f1db7))
* pos payment using non-default mode of payment (backport [#44920](https://github.com/frappe/erpnext/issues/44920)) ([#44970](https://github.com/frappe/erpnext/issues/44970)) ([a0063b3](a0063b31c2)), closes [#41108](https://github.com/frappe/erpnext/issues/41108)
* refactor query in get_total_allocated_amount in bank_transaction ([cc0a478](cc0a478559))
* resolve conflicts ([443a0b8](443a0b81f9))
* set paid amount in party currency in bank reco payment entry ([43a40b1](43a40b1e66))
* Show order tax amount in customer currency on the portal (backport [#44915](https://github.com/frappe/erpnext/issues/44915)) ([#44922](https://github.com/frappe/erpnext/issues/44922)) ([78e0799](78e0799a06))
* update item_tax_rate in backend ([cf980a1](cf980a1304))
* update payment amount for partial pos return (backport [#44065](https://github.com/frappe/erpnext/issues/44065)) ([#44961](https://github.com/frappe/erpnext/issues/44961)) ([1da4712](1da4712919))
2025-01-01 08:56:51 +00:00
ruthra kumar
97487eb6e1 Merge pull request #45004 from frappe/version-14-hotfix
chore: release v14
2025-01-01 14:25:31 +05:30
ruthra kumar
97612ebbf7 Merge pull request #45007 from frappe/mergify/bp/version-14-hotfix/pr-44884
fix: update item_tax_rate in backend (backport #44884)
2025-01-01 13:48:40 +05:30
ruthra kumar
02a0bf35ea chore: remove tests for 'Tax Detail' report 2025-01-01 13:08:08 +05:30
ruthra kumar
0d17cf115a Merge pull request #45022 from frappe/mergify/bp/version-14-hotfix/pr-44989
fix: apply apply_pricing_rule on date change (backport #44989)
2025-01-01 10:18:10 +05:30
DHINESH00
cca507f0bd fix: apply apply_pricing_rule date change
(cherry picked from commit 2cbab9b875)
2025-01-01 04:42:47 +00:00
mergify[bot]
e2b6615e72 fix: duplicate validate for closing stock balance (backport #45015) (#45021)
fix: duplicate validate for closing stock balance (#45015)

(cherry picked from commit 8d650e56ba)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2025-01-01 09:32:51 +05:30
ruthra kumar
fd2a1a0ba0 refactor: use correct method parameters 2024-12-31 17:10:30 +05:30
ruthra kumar
514835b5dd Merge pull request #45009 from frappe/mergify/bp/version-14-hotfix/pr-44903
fix: set paid amount in party currency in bank reco payment entry (backport #44903)
2024-12-31 16:16:06 +05:30
ruthra kumar
bcd3b36821 chore: resolve conflict 2024-12-31 15:55:03 +05:30
ljain112
43a40b1e66 fix: set paid amount in party currency in bank reco payment entry
(cherry picked from commit 70b1077286)
2024-12-31 10:23:34 +00:00
ljain112
cf980a1304 fix: update item_tax_rate in backend
(cherry picked from commit de54c0b41f)

# Conflicts:
#	erpnext/controllers/taxes_and_totals.py
2024-12-31 10:21:30 +00:00
mergify[bot]
0f687f1db7 fix: load customer default price list in pos during item selection (backport #44991) (#44992)
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:36 +05:30
mergify[bot]
a0063b31c2 fix: pos payment using non-default mode of payment (backport #44920) (#44970)
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:57:08 +05:30
ruthra kumar
47e2699315 Merge pull request #44965 from frappe/mergify/bp/version-14-hotfix/pr-44921
fix: get item tax template based on posting date (backport #44921)
2024-12-30 13:09:06 +05:30
ruthra kumar
899acc3601 Merge pull request #44962 from vishakhdesai/backport-v14-#44787
fix: refactor query in get_total_allocated_amount in bank_transaction (backport #44787)
2024-12-30 13:08:38 +05:30
ljain112
56d06861d0 fix: get item tax template based on posting date
(cherry picked from commit 976e35d547)
2024-12-30 12:33:40 +05:30
ruthra kumar
45bf65f37c Merge pull request #44959 from frappe/mergify/bp/version-14-hotfix/pr-44958
refactor(test): make manufacturing test idempotent (backport #44958)
2024-12-30 12:28:08 +05:30
vishakhdesai
443a0b81f9 fix: resolve conflicts 2024-12-30 12:27:14 +05:30
ruthra kumar
d348d587e2 refactor(test): make manufacturing test idempotent
(cherry picked from commit f3be246df3)
2024-12-30 12:04:36 +05:30
mergify[bot]
1da4712919 fix: update payment amount for partial pos return (backport #44065) (#44961)
fix: update payment amount for partial pos return

(cherry picked from commit 53ef6336b6)

Co-authored-by: Kavin <78342682+kavin0411@users.noreply.github.com>
2024-12-30 11:54:14 +05:30
ruthra kumar
3dcb7c1380 Merge pull request #44934 from frappe/mergify/bp/version-14-hotfix/pr-44892
fix: clear payment schedule in purchase invoice for is_paid (backport #44892)
2024-12-27 14:44:51 +05:30
ruthra kumar
ce7dc5ecb3 chore: resolve conflicts 2024-12-27 13:51:11 +05:30
ruthra kumar
d5f30202b4 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)

# Conflicts:
#	erpnext/controllers/accounts_controller.py
2024-12-27 07:54:39 +00:00
Sanket322
cdd3763a8b fix: clear payment schedule in purchase invoice for is_paid
(cherry picked from commit e1fc239f3d)

# Conflicts:
#	erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
#	erpnext/controllers/accounts_controller.py
2024-12-27 07:54:38 +00:00
mergify[bot]
78e0799a06 fix: Show order tax amount in customer currency on the portal (backport #44915) (#44922)
* fix: Show order tax amount in customer currency on the portal (#44915)

(cherry picked from commit b998933ef0)

# Conflicts:
#	erpnext/templates/includes/order/order_taxes.html

* fix: resolved conflict

---------

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2024-12-27 11:25:59 +05:30
Frappe PR Bot
27b7de4854 chore(release): Bumped to Version 14.78.5
## [14.78.5](https://github.com/frappe/erpnext/compare/v14.78.4...v14.78.5) (2024-12-25)

### Bug Fixes

* 'str' object has no attribute 'get_sql' ([510e3ce](510e3cebc9))
* added docs.frappe.io in documentation_url ([#44776](https://github.com/frappe/erpnext/issues/44776)) ([82a3fd1](82a3fd13f2))
* buying rate for service item in gross profit report ([7fa3a78](7fa3a789b1))
* closing stock balance permissions (backport [#44791](https://github.com/frappe/erpnext/issues/44791)) ([#44792](https://github.com/frappe/erpnext/issues/44792)) ([4cb27b9](4cb27b97b4))
* correct tds rate with lower deduction certificate ([d55fe7d](d55fe7d33f))
* do not set cost_center update_voucher_balance as it is set in init_voucher_balance ([97d5d18](97d5d18041))
* fetch tax withholding category from the voucher ([1093c22](1093c227f1))
* permissions for marking Quotation as lost ([0179358](0179358f07))
* Remove typo ([422ada2](422ada2726))
* show profit and loss after period closing ([1a089da](1a089da51a))
* slow posting datetime update (backport [#44799](https://github.com/frappe/erpnext/issues/44799)) ([#44804](https://github.com/frappe/erpnext/issues/44804)) ([d2ede71](d2ede713e4))
* update correct cost center in Accounts Receivable Report ([197b13e](197b13eb87))
* use utility method to generate url ([d042330](d042330c30))
* **ux:** purchase invoice link in error message ([#44797](https://github.com/frappe/erpnext/issues/44797)) ([c9d43f4](c9d43f4c88))
* Warehouse wise Stock Value chart roles (backport [#44865](https://github.com/frappe/erpnext/issues/44865)) ([#44866](https://github.com/frappe/erpnext/issues/44866)) ([177ca6f](177ca6f431))
2024-12-25 03:34:28 +00:00
ruthra kumar
1b5384f8d4 Merge pull request #44886 from frappe/version-14-hotfix
chore: release v14
2024-12-25 09:03:10 +05:30
vishakhdesai
498abf7c83 fix: failing tests fixed
(cherry picked from commit 2ce07865d3)

# Conflicts:
#	erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
2024-12-24 12:23:59 +00:00
vishakhdesai
cc0a478559 fix: refactor query in get_total_allocated_amount in bank_transaction
(cherry picked from commit 6b847cdb62)

# Conflicts:
#	erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
#	erpnext/accounts/doctype/bank_transaction/bank_transaction.py
2024-12-24 12:23:59 +00:00
ruthra kumar
07947eb3f4 Merge pull request #44893 from frappe/mergify/bp/version-14-hotfix/pr-44878
fix: show profit and loss after period closing (backport #44878)
2024-12-24 17:52:45 +05:30
venkat102
1a089da51a fix: show profit and loss after period closing
(cherry picked from commit dc5cd93bf0)
2024-12-24 11:33:39 +00:00
ruthra kumar
67c9872146 Merge pull request #44881 from frappe/mergify/bp/version-14-hotfix/pr-44794
fix: correct tds rate with lower deduction certificate (backport #44794)
2024-12-24 14:37:27 +05:30
ljain112
d55fe7d33f fix: correct tds rate with lower deduction certificate
(cherry picked from commit cb9c12d495)
2024-12-24 08:15:49 +00:00
mergify[bot]
177ca6f431 fix: Warehouse wise Stock Value chart roles (backport #44865) (#44866)
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:45 +05:30
ruthra kumar
8915c804c1 Merge pull request #44848 from frappe/mergify/bp/version-14-hotfix/pr-44797
fix(ux): purchase invoice link in error message (backport #44797)
2024-12-23 15:17:58 +05:30
ruthra kumar
d506589d10 Merge pull request #44846 from frappe/mergify/bp/version-14-hotfix/pr-44738
fix: fetch tax withholding category from the voucher (backport #44738)
2024-12-23 15:03:12 +05:30
ruthra kumar
7ef15ec082 Merge pull request #44842 from frappe/mergify/bp/version-14-hotfix/pr-44813
fix: update correct cost center in Accounts Receivable Report (backport #44813)
2024-12-23 14:55:56 +05:30
Nijith anil
c9d43f4c88 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:19:26 +00:00
venkat102
1093c227f1 fix: fetch tax withholding category from the voucher
(cherry picked from commit 09e64594db)
2024-12-23 09:06:02 +00:00
venkat102
d0c60343cd chore: use get function
(cherry picked from commit 1663c7983e)
2024-12-23 09:06:01 +00:00
vishakhdesai
97d5d18041 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
197b13eb87 fix: update correct cost center in Accounts Receivable Report
(cherry picked from commit 09776e9a5a)
2024-12-23 08:51:37 +00:00
ruthra kumar
0986434871 Merge pull request #44837 from frappe/mergify/bp/version-14-hotfix/pr-44751
fix: buying rate for service item in gross profit report (backport #44751)
2024-12-23 12:08:12 +05:30
ljain112
7fa3a789b1 fix: buying rate for service item in gross profit report
(cherry picked from commit 8d6e79a16f)
2024-12-23 06:16:21 +00:00
ruthra kumar
647f039598 Merge pull request #44833 from frappe/mergify/bp/version-14-hotfix/pr-44644
fix: permissions for marking Quotation as lost (backport #44644)
2024-12-23 11:41:55 +05:30
ruthra kumar
00baa6a07f Merge pull request #44829 from frappe/mergify/bp/version-14-hotfix/pr-44826
fix: Remove typo from `Bank Account` on trash (backport #44826)
2024-12-23 11:26:29 +05:30
ruthra kumar
67ba639ae1 chore: resolve conflicts 2024-12-23 11:16:04 +05:30
barredterra
0179358f07 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
mergify[bot]
4cb27b97b4 fix: closing stock balance permissions (backport #44791) (#44792)
* 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-23 10:54:34 +05:30
Abdeali Chharchhoda
422ada2726 fix: Remove typo
(cherry picked from commit ba28f6bf73)
2024-12-23 04:52:05 +00:00
mergify[bot]
d2ede713e4 fix: slow posting datetime update (backport #44799) (#44804)
fix: slow posting datetime update

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2024-12-20 13:37:00 +05:30
ruthra kumar
e48022f2fe Merge pull request #44777 from frappe/mergify/bp/version-14-hotfix/pr-44776
fix: added docs.frappe.io in documentation_url (backport #44776)
2024-12-18 17:53:22 +05:30
Nabin Hait
82a3fd13f2 fix: added docs.frappe.io in documentation_url (#44776)
(cherry picked from commit febdf4c61e)
2024-12-18 11:59:32 +00:00
Frappe PR Bot
561fe5a171 chore(release): Bumped to Version 14.78.4
## [14.78.4](https://github.com/frappe/erpnext/compare/v14.78.3...v14.78.4) (2024-12-18)

### Bug Fixes

* 'str' object has no attribute 'get_sql' ([bd20ff5](bd20ff581b))
2024-12-18 09:07:38 +00:00
ruthra kumar
f8f2c39ed5 Merge pull request #44768 from frappe/mergify/bp/version-14/pr-44765
fix: 'str' object has no attribute 'get_sql' (backport #44765)
2024-12-18 14:36:18 +05:30
ruthra kumar
becd64fccb Merge pull request #44769 from frappe/mergify/bp/version-14-hotfix/pr-44765
fix: 'str' object has no attribute 'get_sql' (backport #44765)
2024-12-18 14:34:21 +05:30
ljain112
510e3cebc9 fix: 'str' object has no attribute 'get_sql'
(cherry picked from commit 9a43acb65c)
2024-12-18 08:43:18 +00:00
ljain112
bd20ff581b fix: 'str' object has no attribute 'get_sql'
(cherry picked from commit 9a43acb65c)
2024-12-18 08:43:15 +00:00
ruthra kumar
b4faee24da Merge pull request #44759 from frappe/mergify/bp/version-14-hotfix/pr-44758
fix: use utility method to generate url (backport #44758)
2024-12-18 11:17:18 +05:30
ruthra kumar
d042330c30 fix: use utility method to generate url
(cherry picked from commit b970eb8b15)
2024-12-18 05:33:03 +00:00
Frappe PR Bot
d241862f14 chore(release): Bumped to Version 14.78.3
## [14.78.3](https://github.com/frappe/erpnext/compare/v14.78.2...v14.78.3) (2024-12-18)

### Bug Fixes

* allow all dispatch address for drop ship invoice ([0688c0a](0688c0ab6b))
* better indicator base amount for Tax Witholding in Journal Entry ([4a261b5](4a261b5cef))
* broken CI ([c86174d](c86174d0f2))
* incorrect status of the purchase receipt ([#44689](https://github.com/frappe/erpnext/issues/44689)) ([4b4d5df](4b4d5dfa63))
* purchase return entry issue (backport [#44721](https://github.com/frappe/erpnext/issues/44721)) ([#44736](https://github.com/frappe/erpnext/issues/44736)) ([744f345](744f3457de))
* remove invalid filter in Account Receivable report ([b571c7a](b571c7af87))
* set company bank account if default account not set in mode of payment ([2d12f2c](2d12f2cebd))
* Stock Entry uses incorrect company when generated from Pick List ([#44679](https://github.com/frappe/erpnext/issues/44679)) ([00898be](00898be8e4))
* update discount when pricing rule is changed ([0a7832d](0a7832d8d3))
* User permissions in financial statements ([8a9c457](8a9c457d37))
* using query.walk() for escaping ([3a7e335](3a7e335d4b))
* Wrong allocated_amount for sales_team in gross_profit report ([#42989](https://github.com/frappe/erpnext/issues/42989)) ([d83cc57](d83cc57e58))
2024-12-18 05:01:40 +00:00
ruthra kumar
8e34e20b27 Merge pull request #44740 from frappe/version-14-hotfix
chore: release v14
2024-12-18 10:30:20 +05:30
ruthra kumar
caea52c280 Merge pull request #44752 from frappe/mergify/bp/version-14-hotfix/pr-44695
fix: User permissions in financial statements (backport #44695)
2024-12-17 21:18:53 +05:30
ruthra kumar
4473b74e1b Merge pull request #44754 from frappe/mergify/bp/version-14-hotfix/pr-44708
fix: update discount when pricing rule is changed (backport #44708)
2024-12-17 21:10:41 +05:30
venkat102
0a7832d8d3 fix: update discount when pricing rule is changed
(cherry picked from commit 8338d1d5b4)
2024-12-17 15:13:03 +00:00
ljain112
3a7e335d4b fix: using query.walk() for escaping
(cherry picked from commit 5ea131c763)
2024-12-17 15:09:08 +00:00
ljain112
8a9c457d37 fix: User permissions in financial statements
(cherry picked from commit a626372d66)
2024-12-17 15:09:08 +00:00
ruthra kumar
13be763105 Merge pull request #44749 from ruthra-kumar/backport_v14_pr_44581
fix: allow all dispatch address for drop ship invoice (backport #44581)
2024-12-17 20:39:05 +05:30
ruthra kumar
0688c0ab6b fix: allow all dispatch address for drop ship invoice 2024-12-17 20:34:10 +05:30
ruthra kumar
7e00e55d18 Merge pull request #44734 from frappe/mergify/bp/version-14-hotfix/pr-44660
fix: better indicator base amount for Tax Witholding in Journal Entry (backport #44660)
2024-12-17 17:45:43 +05:30
ruthra kumar
ecca59c8a8 Merge pull request #44747 from frappe/mergify/bp/version-14-hotfix/pr-44685
fix: set company bank account if default account not set in mode of p… (backport #44685)
2024-12-17 17:29:15 +05:30
venkat102
2d12f2cebd fix: set company bank account if default account not set in mode of payment
(cherry picked from commit 91c7e3d5f3)
2024-12-17 11:50:04 +00:00
ruthra kumar
c86174d0f2 fix: broken CI
- pin ubuntu-22.04
2024-12-17 16:28:15 +05:30
mergify[bot]
744f3457de fix: purchase return entry issue (backport #44721) (#44736)
fix: purchase return entry issue (#44721)

(cherry picked from commit 1f5d7072e7)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-12-17 14:48:59 +05:30
Smit Vora
4a261b5cef fix: better indicator base amount for Tax Witholding in Journal Entry
(cherry picked from commit 56a0a0db18)
2024-12-17 06:20:32 +00:00
ruthra kumar
bad744194f Merge pull request #44699 from ruthra-kumar/backport_v14_pr_44676
fix: remove invalid filter in Account Receivable report (backport #44676)
2024-12-13 17:53:28 +05:30
ljain112
b571c7af87 fix: remove invalid filter in Account Receivable report 2024-12-13 17:29:17 +05:30
rohitwaghchaure
4b4d5dfa63 fix: incorrect status of the purchase receipt (#44689) 2024-12-13 12:44:03 +05:30
ruthra kumar
4c8b4419b6 Merge pull request #44687 from ruthra-kumar/backport_v14_pr_42989
fix: Wrong allocated_amount for sales_team in gross_profit report (backport #43989)
2024-12-13 12:39:28 +05:30
Diógenes Souza
d83cc57e58 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 12:01:04 +05:30
Nicolas Pereira
00898be8e4 fix: Stock Entry uses incorrect company when generated from Pick List (#44679) 2024-12-13 10:21:30 +05:30
40 changed files with 359 additions and 1233 deletions

View File

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

View File

@@ -16,7 +16,7 @@ concurrency:
jobs:
test:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
timeout-minutes: 60
name: Patch Test

View File

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

View File

@@ -21,7 +21,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

@@ -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,
@@ -284,54 +285,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,
}
]
)
@@ -455,8 +458,12 @@ def get_linked_payments(
def subtract_allocations(gl_account, vouchers):
"Look up & subtract any existing Bank Transaction allocations"
copied = []
voucher_docs = [(voucher[1], voucher[2]) for voucher in vouchers]
voucher_allocated_amounts = get_total_allocated_amount(voucher_docs)
for voucher in vouchers:
rows = get_total_allocated_amount(voucher[1], voucher[2])
rows = voucher_allocated_amounts.get((voucher[1], voucher[2])) or []
amount = None
for row in rows:
if row["gl_account"] == gl_account:

View File

@@ -93,10 +93,16 @@ class BankTransaction(StatusUpdater):
- clear means: set the latest transaction date as clearance date
"""
remaining_amount = self.unallocated_amount
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:
@@ -182,7 +188,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.
@@ -191,7 +197,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,
@@ -247,44 +252,52 @@ def get_related_bank_gl_entries(doctype, docname):
return result
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

@@ -1088,6 +1088,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);

View File

@@ -328,6 +328,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,
}
)

View File

@@ -366,6 +366,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

@@ -1443,7 +1443,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

@@ -36,6 +36,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
@@ -2817,13 +2818,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):

View File

@@ -215,14 +215,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",
@@ -270,7 +270,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:
@@ -507,7 +507,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":
@@ -519,9 +519,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

View File

@@ -129,7 +129,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):
@@ -145,6 +144,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"):
@@ -270,9 +272,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)
@@ -529,9 +528,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

View File

@@ -355,7 +355,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

@@ -526,9 +526,15 @@ def get_accounting_entries(
query = apply_additional_conditions(doctype, query, from_date, ignore_closing_entries, filters)
query = query.where(gl_entry.account.isin(accounts))
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 apply_additional_conditions(doctype, query, from_date, ignore_closing_entries, filters):

View File

@@ -726,12 +726,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:
@@ -768,7 +769,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 = ""

View File

@@ -1,840 +0,0 @@
[
{
"account_manager": null,
"accounts": [],
"companies": [],
"credit_limits": [],
"customer_details": null,
"customer_group": "All Customer Groups",
"customer_name": "_Test Customer",
"customer_pos_id": null,
"customer_primary_address": null,
"customer_primary_contact": null,
"customer_type": "Company",
"default_bank_account": null,
"default_commission_rate": 0.0,
"default_currency": null,
"default_price_list": null,
"default_sales_partner": null,
"disabled": 0,
"dn_required": 0,
"docstatus": 0,
"doctype": "Customer",
"email_id": null,
"gender": null,
"image": null,
"industry": null,
"is_frozen": 0,
"is_internal_customer": 0,
"language": "en",
"lead_name": null,
"loyalty_program": null,
"loyalty_program_tier": null,
"market_segment": null,
"mobile_no": null,
"modified": "2021-02-15 05:18:03.624724",
"name": "_Test Customer",
"naming_series": "CUST-.YYYY.-",
"pan": null,
"parent": null,
"parentfield": null,
"parenttype": null,
"payment_terms": null,
"primary_address": null,
"represents_company": "",
"sales_team": [],
"salutation": null,
"so_required": 0,
"tax_category": null,
"tax_id": null,
"tax_withholding_category": null,
"territory": "All Territories",
"website": null
},{
"accounts": [],
"allow_purchase_invoice_creation_without_purchase_order": 0,
"allow_purchase_invoice_creation_without_purchase_receipt": 0,
"companies": [],
"country": "United Kingdom",
"default_bank_account": null,
"default_currency": null,
"default_price_list": null,
"disabled": 0,
"docstatus": 0,
"doctype": "Supplier",
"hold_type": "",
"image": null,
"is_frozen": 0,
"is_internal_supplier": 0,
"is_transporter": 0,
"language": "en",
"modified": "2021-03-31 16:47:10.109316",
"name": "_Test Supplier",
"naming_series": "SUP-.YYYY.-",
"on_hold": 0,
"pan": null,
"parent": null,
"parentfield": null,
"parenttype": null,
"payment_terms": null,
"prevent_pos": 0,
"prevent_rfqs": 0,
"release_date": null,
"represents_company": null,
"supplier_details": null,
"supplier_group": "Raw Material",
"supplier_name": "_Test Supplier",
"supplier_type": "Company",
"tax_category": null,
"tax_id": null,
"tax_withholding_category": null,
"warn_pos": 0,
"warn_rfqs": 0,
"website": null
},{
"account_currency": "GBP",
"account_name": "Debtors",
"account_number": "",
"account_type": "Receivable",
"balance_must_be": "",
"company": "_T",
"disabled": 0,
"docstatus": 0,
"doctype": "Account",
"freeze_account": "No",
"include_in_gross": 0,
"inter_company_account": 0,
"is_group": 0,
"lft": 58,
"modified": "2021-03-26 04:44:19.955468",
"name": "Debtors - _T",
"old_parent": null,
"parent": null,
"parent_account": "Application of Funds (Assets) - _T",
"parentfield": null,
"parenttype": null,
"report_type": "Balance Sheet",
"rgt": 59,
"root_type": "Asset",
"tax_rate": 0.0
},{
"account_currency": "GBP",
"account_name": "Sales",
"account_number": "",
"account_type": "Income Account",
"balance_must_be": "",
"company": "_T",
"disabled": 0,
"docstatus": 0,
"doctype": "Account",
"freeze_account": "No",
"include_in_gross": 0,
"inter_company_account": 0,
"is_group": 0,
"lft": 291,
"modified": "2021-03-26 04:50:21.697703",
"name": "Sales - _T",
"old_parent": null,
"parent": null,
"parent_account": "Income - _T",
"parentfield": null,
"parenttype": null,
"report_type": "Profit and Loss",
"rgt": 292,
"root_type": "Income",
"tax_rate": 0.0
},{
"account_currency": "GBP",
"account_name": "VAT on Sales",
"account_number": "",
"account_type": "Tax",
"balance_must_be": "",
"company": "_T",
"disabled": 0,
"docstatus": 0,
"doctype": "Account",
"freeze_account": "No",
"include_in_gross": 0,
"inter_company_account": 0,
"is_group": 0,
"lft": 317,
"modified": "2021-03-26 04:50:21.697703",
"name": "VAT on Sales - _T",
"old_parent": null,
"parent": null,
"parent_account": "Source of Funds (Liabilities) - _T",
"parentfield": null,
"parenttype": null,
"report_type": "Balance Sheet",
"rgt": 318,
"root_type": "Liability",
"tax_rate": 0.0
},{
"account_currency": "GBP",
"account_name": "Cost of Goods Sold",
"account_number": "",
"account_type": "Cost of Goods Sold",
"balance_must_be": "",
"company": "_T",
"disabled": 0,
"docstatus": 0,
"doctype": "Account",
"freeze_account": "No",
"include_in_gross": 0,
"inter_company_account": 0,
"is_group": 0,
"lft": 171,
"modified": "2021-03-26 04:44:19.994857",
"name": "Cost of Goods Sold - _T",
"old_parent": null,
"parent": null,
"parent_account": "Expenses - _T",
"parentfield": null,
"parenttype": null,
"report_type": "Profit and Loss",
"rgt": 172,
"root_type": "Expense",
"tax_rate": 0.0
},{
"account_currency": "GBP",
"account_name": "VAT on Purchases",
"account_number": "",
"account_type": "Tax",
"balance_must_be": "",
"company": "_T",
"disabled": 0,
"docstatus": 0,
"doctype": "Account",
"freeze_account": "No",
"include_in_gross": 0,
"inter_company_account": 0,
"is_group": 0,
"lft": 80,
"modified": "2021-03-26 04:44:19.961983",
"name": "VAT on Purchases - _T",
"old_parent": null,
"parent": null,
"parent_account": "Application of Funds (Assets) - _T",
"parentfield": null,
"parenttype": null,
"report_type": "Balance Sheet",
"rgt": 81,
"root_type": "Asset",
"tax_rate": 0.0
},{
"account_currency": "GBP",
"account_name": "Creditors",
"account_number": "",
"account_type": "Payable",
"balance_must_be": "",
"company": "_T",
"disabled": 0,
"docstatus": 0,
"doctype": "Account",
"freeze_account": "No",
"include_in_gross": 0,
"inter_company_account": 0,
"is_group": 0,
"lft": 302,
"modified": "2021-03-26 04:50:21.697703",
"name": "Creditors - _T",
"old_parent": null,
"parent": null,
"parent_account": "Source of Funds (Liabilities) - _T",
"parentfield": null,
"parenttype": null,
"report_type": "Balance Sheet",
"rgt": 303,
"root_type": "Liability",
"tax_rate": 0.0
},{
"additional_discount_percentage": 0.0,
"address_display": null,
"adjust_advance_taxes": 0,
"advances": [],
"against_expense_account": "Cost of Goods Sold - _T",
"allocate_advances_automatically": 0,
"amended_from": null,
"apply_discount_on": "Grand Total",
"apply_tds": 0,
"auto_repeat": null,
"base_discount_amount": 0.0,
"base_grand_total": 511.68,
"base_in_words": "GBP Five Hundred And Eleven and Sixty Eight Pence only.",
"base_net_total": 426.4,
"base_paid_amount": 0.0,
"base_rounded_total": 511.68,
"base_rounding_adjustment": 0.0,
"base_taxes_and_charges_added": 85.28,
"base_taxes_and_charges_deducted": 0.0,
"base_total": 426.4,
"base_total_taxes_and_charges": 85.28,
"base_write_off_amount": 0.0,
"bill_date": null,
"bill_no": null,
"billing_address": null,
"billing_address_display": null,
"buying_price_list": "Standard Buying",
"cash_bank_account": null,
"clearance_date": null,
"company": "_T",
"contact_display": null,
"contact_email": null,
"contact_mobile": null,
"contact_person": null,
"conversion_rate": 1.0,
"cost_center": null,
"credit_to": "Creditors - _T",
"currency": "GBP",
"disable_rounded_total": 0,
"discount_amount": 0.0,
"docstatus": 0,
"doctype": "Purchase Invoice",
"due_date": null,
"from_date": null,
"grand_total": 511.68,
"group_same_items": 0,
"hold_comment": null,
"ignore_pricing_rule": 0,
"in_words": "GBP Five Hundred And Eleven and Sixty Eight Pence only.",
"inter_company_invoice_reference": null,
"is_internal_supplier": 0,
"is_opening": "No",
"is_paid": 0,
"is_return": 0,
"is_subcontracted": 0,
"items": [
{
"allow_zero_valuation_rate": 0,
"amount": 426.4,
"asset_category": null,
"asset_location": null,
"base_amount": 426.4,
"base_net_amount": 426.4,
"base_net_rate": 5.33,
"base_price_list_rate": 5.33,
"base_rate": 5.33,
"base_rate_with_margin": 0.0,
"batch_no": null,
"bom": null,
"brand": null,
"conversion_factor": 0.0,
"cost_center": "Main - _T",
"deferred_expense_account": null,
"description": "<div class=\"ql-editor read-mode\"><p>Fluid to make widgets</p></div>",
"discount_amount": 0.0,
"discount_percentage": 0.0,
"enable_deferred_expense": 0,
"expense_account": "Cost of Goods Sold - _T",
"from_warehouse": null,
"image": null,
"include_exploded_items": 0,
"is_fixed_asset": 0,
"is_free_item": 0,
"item_code": null,
"item_group": null,
"item_name": "Widget Fluid 1Litre",
"item_tax_amount": 0.0,
"item_tax_rate": "{\"VAT on Purchases - _T\": 20.0}",
"item_tax_template": null,
"landed_cost_voucher_amount": 0.0,
"manufacturer": null,
"manufacturer_part_no": null,
"margin_rate_or_amount": 0.0,
"margin_type": "",
"net_amount": 426.4,
"net_rate": 5.33,
"page_break": 0,
"parent": null,
"parentfield": "items",
"parenttype": "Purchase Invoice",
"po_detail": null,
"pr_detail": null,
"price_list_rate": 5.33,
"pricing_rules": null,
"project": null,
"purchase_invoice_item": null,
"purchase_order": null,
"purchase_receipt": null,
"qty": 80.0,
"quality_inspection": null,
"rate": 5.33,
"rate_with_margin": 0.0,
"received_qty": 0.0,
"rejected_qty": 0.0,
"rejected_serial_no": null,
"rejected_warehouse": null,
"rm_supp_cost": 0.0,
"sales_invoice_item": null,
"serial_no": null,
"service_end_date": null,
"service_start_date": null,
"service_stop_date": null,
"stock_qty": 0.0,
"stock_uom": "Nos",
"stock_uom_rate": 0.0,
"total_weight": 0.0,
"uom": "Nos",
"valuation_rate": 0.0,
"warehouse": null,
"weight_per_unit": 0.0,
"weight_uom": null
}
],
"language": "en",
"letter_head": null,
"mode_of_payment": null,
"modified": "2021-04-03 03:33:09.180453",
"name": null,
"naming_series": "ACC-PINV-.YYYY.-",
"net_total": 426.4,
"on_hold": 0,
"other_charges_calculation": "<div class=\"tax-break-up\" style=\"overflow-x: auto;\">\n\t<table class=\"table table-bordered table-hover\">\n\t\t<thead>\n\t\t\t<tr>\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t<th class=\"text-left\">Item</th>\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t<th class=\"text-right\">Taxable Amount</th>\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t<th class=\"text-right\">VAT on Purchases</th>\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t</tr>\n\t\t</thead>\n\t\t<tbody>\n\t\t\t\n\t\t\t\t<tr>\n\t\t\t\t\t<td>Widget Fluid 1Litre</td>\n\t\t\t\t\t<td class='text-right'>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\u00a3 426.40\n\t\t\t\t\t\t\n\t\t\t\t\t</td>\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<td class='text-right'>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t(20.0%)\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\u00a3 85.28\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t</tr>\n\t\t\t\n\t\t</tbody>\n\t</table>\n</div>",
"outstanding_amount": 511.68,
"paid_amount": 0.0,
"parent": null,
"parentfield": null,
"parenttype": null,
"party_account_currency": "GBP",
"payment_schedule": [],
"payment_terms_template": null,
"plc_conversion_rate": 1.0,
"posting_date": null,
"posting_time": "16:59:56.789522",
"price_list_currency": "GBP",
"pricing_rules": [],
"project": null,
"rejected_warehouse": null,
"release_date": null,
"remarks": "No Remarks",
"represents_company": null,
"return_against": null,
"rounded_total": 511.68,
"rounding_adjustment": 0.0,
"scan_barcode": null,
"select_print_heading": null,
"set_from_warehouse": null,
"set_posting_time": 0,
"set_warehouse": null,
"shipping_address": null,
"shipping_address_display": "",
"shipping_rule": null,
"status": "Unpaid",
"supplied_items": [],
"supplier": "_Test Supplier",
"supplier_address": null,
"supplier_name": "_Test Supplier",
"supplier_warehouse": "Stores - _T",
"tax_category": null,
"tax_id": null,
"tax_withholding_category": null,
"taxes": [
{
"account_head": "VAT on Purchases - _T",
"add_deduct_tax": "Add",
"base_tax_amount": 85.28,
"base_tax_amount_after_discount_amount": 85.28,
"base_total": 511.68,
"category": "Total",
"charge_type": "On Net Total",
"cost_center": "Main - _T",
"description": "VAT on Purchases",
"included_in_print_rate": 0,
"item_wise_tax_detail": "{\"Widget Fluid 1Litre\":[20.0,85.28]}",
"parent": null,
"parentfield": "taxes",
"parenttype": "Purchase Invoice",
"rate": 0.0,
"row_id": null,
"tax_amount": 85.28,
"tax_amount_after_discount_amount": 85.28,
"total": 511.68
}
],
"taxes_and_charges": null,
"taxes_and_charges_added": 85.28,
"taxes_and_charges_deducted": 0.0,
"tc_name": null,
"terms": null,
"title": "_Purchase Invoice",
"to_date": null,
"total": 426.4,
"total_advance": 0.0,
"total_net_weight": 0.0,
"total_qty": 80.0,
"total_taxes_and_charges": 85.28,
"unrealized_profit_loss_account": null,
"update_stock": 0,
"write_off_account": null,
"write_off_amount": 0.0,
"write_off_cost_center": null
},{
"account_for_change_amount": null,
"additional_discount_percentage": 0.0,
"address_display": null,
"advances": [],
"against_income_account": "Sales - _T",
"allocate_advances_automatically": 0,
"amended_from": null,
"apply_discount_on": "Grand Total",
"auto_repeat": null,
"base_change_amount": 0.0,
"base_discount_amount": 0.0,
"base_grand_total": 868.25,
"base_in_words": "GBP Eight Hundred And Sixty Eight and Twenty Five Pence only.",
"base_net_total": 825.0,
"base_paid_amount": 0.0,
"base_rounded_total": 868.25,
"base_rounding_adjustment": 0.0,
"base_total": 825.0,
"base_total_taxes_and_charges": 43.25,
"base_write_off_amount": 0.0,
"c_form_applicable": "No",
"c_form_no": null,
"campaign": null,
"cash_bank_account": null,
"change_amount": 0.0,
"commission_rate": 0.0,
"company": "_T",
"company_address": null,
"company_address_display": null,
"company_tax_id": null,
"contact_display": null,
"contact_email": null,
"contact_mobile": null,
"contact_person": null,
"conversion_rate": 1.0,
"cost_center": null,
"currency": "GBP",
"customer": "_Test Customer",
"customer_address": null,
"customer_group": "All Customer Groups",
"customer_name": "_Test Customer",
"debit_to": "Debtors - _T",
"discount_amount": 0.0,
"docstatus": 0,
"doctype": "Sales Invoice",
"due_date": null,
"from_date": null,
"grand_total": 868.25,
"group_same_items": 0,
"ignore_pricing_rule": 0,
"in_words": "GBP Eight Hundred And Sixty Eight and Twenty Five Pence only.",
"inter_company_invoice_reference": null,
"is_consolidated": 0,
"is_discounted": 0,
"is_internal_customer": 0,
"is_opening": "No",
"is_pos": 0,
"is_return": 0,
"items": [
{
"actual_batch_qty": 0.0,
"actual_qty": 0.0,
"allow_zero_valuation_rate": 0,
"amount": 200.0,
"asset": null,
"barcode": null,
"base_amount": 200.0,
"base_net_amount": 200.0,
"base_net_rate": 50.0,
"base_price_list_rate": 0.0,
"base_rate": 50.0,
"base_rate_with_margin": 0.0,
"batch_no": null,
"brand": null,
"conversion_factor": 1.0,
"cost_center": "Main - _T",
"customer_item_code": null,
"deferred_revenue_account": null,
"delivered_by_supplier": 0,
"delivered_qty": 0.0,
"delivery_note": null,
"description": "<div class=\"ql-editor read-mode\"><p>Used</p></div>",
"discount_amount": 0.0,
"discount_percentage": 0.0,
"dn_detail": null,
"enable_deferred_revenue": 0,
"expense_account": null,
"finance_book": null,
"image": null,
"income_account": "Sales - _T",
"incoming_rate": 0.0,
"is_fixed_asset": 0,
"is_free_item": 0,
"item_code": null,
"item_group": null,
"item_name": "Dunlop tyres",
"item_tax_rate": "{\"VAT on Sales - _T\": 20.0}",
"item_tax_template": null,
"margin_rate_or_amount": 0.0,
"margin_type": "",
"net_amount": 200.0,
"net_rate": 50.0,
"page_break": 0,
"parent": null,
"parentfield": "items",
"parenttype": "Sales Invoice",
"price_list_rate": 0.0,
"pricing_rules": null,
"project": null,
"qty": 4.0,
"quality_inspection": null,
"rate": 50.0,
"rate_with_margin": 0.0,
"sales_invoice_item": null,
"sales_order": null,
"serial_no": null,
"service_end_date": null,
"service_start_date": null,
"service_stop_date": null,
"so_detail": null,
"stock_qty": 4.0,
"stock_uom": "Nos",
"stock_uom_rate": 50.0,
"target_warehouse": null,
"total_weight": 0.0,
"uom": "Nos",
"warehouse": null,
"weight_per_unit": 0.0,
"weight_uom": null
},
{
"actual_batch_qty": 0.0,
"actual_qty": 0.0,
"allow_zero_valuation_rate": 0,
"amount": 65.0,
"asset": null,
"barcode": null,
"base_amount": 65.0,
"base_net_amount": 65.0,
"base_net_rate": 65.0,
"base_price_list_rate": 0.0,
"base_rate": 65.0,
"base_rate_with_margin": 0.0,
"batch_no": null,
"brand": null,
"conversion_factor": 1.0,
"cost_center": "Main - _T",
"customer_item_code": null,
"deferred_revenue_account": null,
"delivered_by_supplier": 0,
"delivered_qty": 0.0,
"delivery_note": null,
"description": "<div class=\"ql-editor read-mode\"><p>Used</p></div>",
"discount_amount": 0.0,
"discount_percentage": 0.0,
"dn_detail": null,
"enable_deferred_revenue": 0,
"expense_account": null,
"finance_book": null,
"image": null,
"income_account": "Sales - _T",
"incoming_rate": 0.0,
"is_fixed_asset": 0,
"is_free_item": 0,
"item_code": "",
"item_group": null,
"item_name": "Continental tyres",
"item_tax_rate": "{\"VAT on Sales - _T\": 5.0}",
"item_tax_template": null,
"margin_rate_or_amount": 0.0,
"margin_type": "",
"net_amount": 65.0,
"net_rate": 65.0,
"page_break": 0,
"parent": null,
"parentfield": "items",
"parenttype": "Sales Invoice",
"price_list_rate": 0.0,
"pricing_rules": null,
"project": null,
"qty": 1.0,
"quality_inspection": null,
"rate": 65.0,
"rate_with_margin": 0.0,
"sales_invoice_item": null,
"sales_order": null,
"serial_no": null,
"service_end_date": null,
"service_start_date": null,
"service_stop_date": null,
"so_detail": null,
"stock_qty": 1.0,
"stock_uom": null,
"stock_uom_rate": 65.0,
"target_warehouse": null,
"total_weight": 0.0,
"uom": "Nos",
"warehouse": null,
"weight_per_unit": 0.0,
"weight_uom": null
},
{
"actual_batch_qty": 0.0,
"actual_qty": 0.0,
"allow_zero_valuation_rate": 0,
"amount": 560.0,
"asset": null,
"barcode": null,
"base_amount": 560.0,
"base_net_amount": 560.0,
"base_net_rate": 70.0,
"base_price_list_rate": 0.0,
"base_rate": 70.0,
"base_rate_with_margin": 0.0,
"batch_no": null,
"brand": null,
"conversion_factor": 1.0,
"cost_center": "Main - _T",
"customer_item_code": null,
"deferred_revenue_account": null,
"delivered_by_supplier": 0,
"delivered_qty": 0.0,
"delivery_note": null,
"description": "<div class=\"ql-editor read-mode\"><p>New</p></div>",
"discount_amount": 0.0,
"discount_percentage": 0.0,
"dn_detail": null,
"enable_deferred_revenue": 0,
"expense_account": null,
"finance_book": null,
"image": null,
"income_account": "Sales - _T",
"incoming_rate": 0.0,
"is_fixed_asset": 0,
"is_free_item": 0,
"item_code": null,
"item_group": null,
"item_name": "Toyo tyres",
"item_tax_rate": "{\"VAT on Sales - _T\": 0.0}",
"item_tax_template": null,
"margin_rate_or_amount": 0.0,
"margin_type": "",
"net_amount": 560.0,
"net_rate": 70.0,
"page_break": 0,
"parent": null,
"parentfield": "items",
"parenttype": "Sales Invoice",
"price_list_rate": 0.0,
"pricing_rules": null,
"project": null,
"qty": 8.0,
"quality_inspection": null,
"rate": 70.0,
"rate_with_margin": 0.0,
"sales_invoice_item": null,
"sales_order": null,
"serial_no": null,
"service_end_date": null,
"service_start_date": null,
"service_stop_date": null,
"so_detail": null,
"stock_qty": 8.0,
"stock_uom": null,
"stock_uom_rate": 70.0,
"target_warehouse": null,
"total_weight": 0.0,
"uom": "Nos",
"warehouse": null,
"weight_per_unit": 0.0,
"weight_uom": null
}
],
"language": "en",
"letter_head": null,
"loyalty_amount": 0.0,
"loyalty_points": 0,
"loyalty_program": null,
"loyalty_redemption_account": null,
"loyalty_redemption_cost_center": null,
"modified": "2021-02-16 05:18:59.755144",
"name": null,
"naming_series": "ACC-SINV-.YYYY.-",
"net_total": 825.0,
"other_charges_calculation": "<div class=\"tax-break-up\" style=\"overflow-x: auto;\">\n\t<table class=\"table table-bordered table-hover\">\n\t\t<thead>\n\t\t\t<tr>\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t<th class=\"text-left\">Item</th>\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t<th class=\"text-right\">Taxable Amount</th>\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t<th class=\"text-right\">VAT on Sales</th>\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t</tr>\n\t\t</thead>\n\t\t<tbody>\n\t\t\t\n\t\t\t\t<tr>\n\t\t\t\t\t<td>Dunlop tyres</td>\n\t\t\t\t\t<td class='text-right'>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\u00a3 200.00\n\t\t\t\t\t\t\n\t\t\t\t\t</td>\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<td class='text-right'>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t(20.0%)\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\u00a3 40.00\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t</tr>\n\t\t\t\n\t\t\t\t<tr>\n\t\t\t\t\t<td>Continental tyres</td>\n\t\t\t\t\t<td class='text-right'>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\u00a3 65.00\n\t\t\t\t\t\t\n\t\t\t\t\t</td>\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<td class='text-right'>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t(5.0%)\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\u00a3 3.25\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t</tr>\n\t\t\t\n\t\t\t\t<tr>\n\t\t\t\t\t<td>Toyo tyres</td>\n\t\t\t\t\t<td class='text-right'>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\u00a3 560.00\n\t\t\t\t\t\t\n\t\t\t\t\t</td>\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<td class='text-right'>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t(0.0%)\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\u00a3 0.00\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t</tr>\n\t\t\t\n\t\t</tbody>\n\t</table>\n</div>",
"outstanding_amount": 868.25,
"packed_items": [],
"paid_amount": 0.0,
"parent": null,
"parentfield": null,
"parenttype": null,
"party_account_currency": "GBP",
"payment_schedule": [],
"payment_terms_template": null,
"payments": [],
"plc_conversion_rate": 1.0,
"po_date": null,
"po_no": "",
"pos_profile": null,
"posting_date": null,
"posting_time": "5:19:02.994077",
"price_list_currency": "GBP",
"pricing_rules": [],
"project": null,
"redeem_loyalty_points": 0,
"remarks": "No Remarks",
"represents_company": "",
"return_against": null,
"rounded_total": 868.25,
"rounding_adjustment": 0.0,
"sales_partner": null,
"sales_team": [],
"scan_barcode": null,
"select_print_heading": null,
"selling_price_list": "Standard Selling",
"set_posting_time": 0,
"set_target_warehouse": null,
"set_warehouse": null,
"shipping_address": null,
"shipping_address_name": "",
"shipping_rule": null,
"source": null,
"status": "Overdue",
"tax_category": "",
"tax_id": null,
"taxes": [
{
"account_head": "VAT on Sales - _T",
"base_tax_amount": 43.25,
"base_tax_amount_after_discount_amount": 43.25,
"base_total": 868.25,
"charge_type": "On Net Total",
"cost_center": "Main - _T",
"description": "VAT on Sales",
"included_in_print_rate": 0,
"item_wise_tax_detail": "{\"Dunlop tyres\":[20.0,40.0],\"Continental tyres\":[5.0,3.25],\"Toyo tyres\":[0.0,0.0]}",
"parent": null,
"parentfield": "taxes",
"parenttype": "Sales Invoice",
"rate": 0.0,
"row_id": null,
"tax_amount": 43.25,
"tax_amount_after_discount_amount": 43.25,
"total": 868.25
}
],
"taxes_and_charges": null,
"tc_name": null,
"terms": null,
"territory": "All Territories",
"timesheets": [],
"title": "_Sales Invoice",
"to_date": null,
"total": 825.0,
"total_advance": 0.0,
"total_billing_amount": 0.0,
"total_commission": 0.0,
"total_net_weight": 0.0,
"total_qty": 13.0,
"total_taxes_and_charges": 43.25,
"unrealized_profit_loss_account": null,
"update_billed_amount_in_sales_order": 0,
"update_stock": 0,
"write_off_account": null,
"write_off_amount": 0.0,
"write_off_cost_center": null,
"write_off_outstanding_amount_automatically": 0
}
]

View File

@@ -1,220 +0,0 @@
import datetime
import json
import os
import unittest
import frappe
from frappe.utils import (
add_to_date,
get_first_day,
get_last_day,
get_year_ending,
get_year_start,
getdate,
)
from .tax_detail import filter_match, save_custom_report
class TestTaxDetail(unittest.TestCase):
def load_testdocs(self):
from erpnext.accounts.utils import FiscalYearError, get_fiscal_year
datapath, _ = os.path.splitext(os.path.realpath(__file__))
with open(datapath + ".json") as fp:
docs = json.load(fp)
now = getdate()
self.from_date = get_first_day(now)
self.to_date = get_last_day(now)
try:
get_fiscal_year(now, company="_T")
except FiscalYearError:
docs = [
{
"companies": [
{
"company": "_T",
"parent": "_Test Fiscal",
"parentfield": "companies",
"parenttype": "Fiscal Year",
}
],
"doctype": "Fiscal Year",
"year": "_Test Fiscal",
"year_end_date": get_year_ending(now),
"year_start_date": get_year_start(now),
},
*docs,
]
docs = [
{
"abbr": "_T",
"company_name": "_T",
"country": "United Kingdom",
"default_currency": "GBP",
"doctype": "Company",
"name": "_T",
},
*docs,
]
for doc in docs:
try:
db_doc = frappe.get_doc(doc)
if "Invoice" in db_doc.doctype:
db_doc.due_date = add_to_date(now, days=1)
db_doc.insert()
# Create GL Entries:
db_doc.submit()
else:
db_doc.insert(ignore_if_duplicate=True)
except frappe.exceptions.DuplicateEntryError:
pass
def load_defcols(self):
self.company = frappe.get_doc("Company", "_T")
custom_report = frappe.get_doc("Report", "Tax Detail")
self.default_columns, _ = custom_report.run_query_report(
filters={
"from_date": "2021-03-01",
"to_date": "2021-03-31",
"company": self.company.name,
"mode": "run",
"report_name": "Tax Detail",
},
user=frappe.session.user,
)
def rm_testdocs(self):
"Remove the Company and all data"
from erpnext.setup.doctype.company.company import create_transaction_deletion_request
create_transaction_deletion_request(self.company.name)
def test_report(self):
self.load_testdocs()
self.load_defcols()
report_name = save_custom_report(
"Tax Detail",
"_Test Tax Detail",
json.dumps(
{
"columns": self.default_columns,
"sections": {
"Box1": {"Filter0": {"type": "filter", "filters": {"4": "VAT on Sales"}}},
"Box2": {"Filter0": {"type": "filter", "filters": {"4": "Acquisition"}}},
"Box3": {"Box1": {"type": "section"}, "Box2": {"type": "section"}},
"Box4": {"Filter0": {"type": "filter", "filters": {"4": "VAT on Purchases"}}},
"Box5": {"Box3": {"type": "section"}, "Box4": {"type": "section"}},
"Box6": {"Filter0": {"type": "filter", "filters": {"3": "!=Tax", "4": "Sales"}}},
"Box7": {"Filter0": {"type": "filter", "filters": {"2": "Expense", "3": "!=Tax"}}},
"Box8": {
"Filter0": {"type": "filter", "filters": {"3": "!=Tax", "4": "Sales", "12": "EU"}}
},
"Box9": {
"Filter0": {
"type": "filter",
"filters": {"2": "Expense", "3": "!=Tax", "12": "EU"},
}
},
},
"show_detail": 1,
}
),
)
data = frappe.desk.query_report.run(
report_name,
filters={
"from_date": self.from_date,
"to_date": self.to_date,
"company": self.company.name,
"mode": "run",
"report_name": report_name,
},
user=frappe.session.user,
)
self.assertListEqual(data.get("columns"), self.default_columns)
expected = (
("Box1", 43.25),
("Box2", 0.0),
("Box3", 43.25),
("Box4", -85.28),
("Box5", -42.03),
("Box6", 825.0),
("Box7", -426.40),
("Box8", 0.0),
("Box9", 0.0),
)
exrow = iter(expected)
for row in data.get("result"):
if row.get("voucher_no") and not row.get("posting_date"):
label, value = next(exrow)
self.assertDictEqual(row, {"voucher_no": label, "amount": value})
self.assertListEqual(
data.get("report_summary"),
[{"label": label, "datatype": "Currency", "value": value} for label, value in expected],
)
self.rm_testdocs()
def test_filter_match(self):
# None - treated as -inf number except range
self.assertTrue(filter_match(None, "!="))
self.assertTrue(filter_match(None, "<"))
self.assertTrue(filter_match(None, "<jjj"))
self.assertTrue(filter_match(None, " : "))
self.assertTrue(filter_match(None, ":56"))
self.assertTrue(filter_match(None, ":de"))
self.assertFalse(filter_match(None, "3.4"))
self.assertFalse(filter_match(None, "="))
self.assertFalse(filter_match(None, "=3.4"))
self.assertFalse(filter_match(None, ">3.4"))
self.assertFalse(filter_match(None, " <"))
self.assertFalse(filter_match(None, "ew"))
self.assertFalse(filter_match(None, " "))
self.assertFalse(filter_match(None, " f :"))
# Numbers
self.assertTrue(filter_match(3.4, "3.4"))
self.assertTrue(filter_match(3.4, ".4"))
self.assertTrue(filter_match(3.4, "3"))
self.assertTrue(filter_match(-3.4, "< -3"))
self.assertTrue(filter_match(-3.4, "> -4"))
self.assertTrue(filter_match(3.4, "= 3.4 "))
self.assertTrue(filter_match(3.4, "!=4.5"))
self.assertTrue(filter_match(3.4, " 3 : 4 "))
self.assertTrue(filter_match(0.0, " : "))
self.assertFalse(filter_match(3.4, "=4.5"))
self.assertFalse(filter_match(3.4, " = 3.4 "))
self.assertFalse(filter_match(3.4, "!=3.4"))
self.assertFalse(filter_match(3.4, ">6"))
self.assertFalse(filter_match(3.4, "<-4.5"))
self.assertFalse(filter_match(3.4, "4.5"))
self.assertFalse(filter_match(3.4, "5:9"))
# Strings
self.assertTrue(filter_match("ACC-SINV-2021-00001", "SINV"))
self.assertTrue(filter_match("ACC-SINV-2021-00001", "sinv"))
self.assertTrue(filter_match("ACC-SINV-2021-00001", "-2021"))
self.assertTrue(filter_match(" ACC-SINV-2021-00001", " acc"))
self.assertTrue(filter_match("ACC-SINV-2021-00001", "=2021"))
self.assertTrue(filter_match("ACC-SINV-2021-00001", "!=zz"))
self.assertTrue(filter_match("ACC-SINV-2021-00001", "< zzz "))
self.assertTrue(filter_match("ACC-SINV-2021-00001", " : sinv "))
self.assertFalse(filter_match("ACC-SINV-2021-00001", " sinv :"))
self.assertFalse(filter_match("ACC-SINV-2021-00001", " acc"))
self.assertFalse(filter_match("ACC-SINV-2021-00001", "= 2021 "))
self.assertFalse(filter_match("ACC-SINV-2021-00001", "!=sinv"))
self.assertFalse(filter_match("ACC-SINV-2021-00001", " >"))
self.assertFalse(filter_match("ACC-SINV-2021-00001", ">aa"))
self.assertFalse(filter_match("ACC-SINV-2021-00001", " <"))
self.assertFalse(filter_match("ACC-SINV-2021-00001", "< "))
self.assertFalse(filter_match("ACC-SINV-2021-00001", " ="))
self.assertFalse(filter_match("ACC-SINV-2021-00001", "="))
# Date - always match
self.assertTrue(filter_match(datetime.date(2021, 3, 19), " kdsjkldfs "))

View File

@@ -72,8 +72,8 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_
if net_total_map.get((voucher_type, name)):
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

@@ -29,10 +29,6 @@ REPORT_FILTER_TEST_CASES: list[tuple[ReportName, ReportFilters]] = [
("Sales Register", {}),
("Sales Register", {"item_group": "All Item Groups"}),
("Purchase Register", {}),
(
"Tax Detail",
{"mode": "run", "report_name": "Tax Detail"},
),
]
OPTIONAL_FILTERS = {}

View File

@@ -415,9 +415,16 @@ class AccountsController(TransactionBase):
)
def validate_invoice_documents_schedule(self):
if self.is_return:
if (
self.is_return
or (self.doctype == "Purchase Invoice" and self.is_paid)
or (self.doctype == "Sales Invoice" and self.is_pos)
or self.get("is_opening") == "Yes"
):
self.payment_terms_template = ""
self.payment_schedule = []
if self.is_return:
return
self.validate_payment_schedule_dates()
@@ -2196,7 +2203,7 @@ class AccountsController(TransactionBase):
frappe.throw(_("Rows with duplicate due dates in other rows were found: {0}").format(duplicates))
def validate_payment_schedule_amount(self):
if self.doctype == "Sales Invoice" and self.is_pos:
if (self.doctype == "Sales Invoice" and self.is_pos) or self.get("is_opening") == "Yes":
return
party_account_currency = self.get("party_account_currency")

View File

@@ -71,16 +71,13 @@ def validate_returned_items(doc):
valid_items = frappe._dict()
select_fields = "item_code, qty, stock_qty, rate, parenttype, conversion_factor"
select_fields = "item_code, qty, stock_qty, rate, parenttype, conversion_factor, name"
if doc.doctype != "Purchase Invoice":
select_fields += ",serial_no, batch_no"
if doc.doctype in ["Purchase Invoice", "Purchase Receipt", "Subcontracting Receipt"]:
select_fields += ",rejected_qty, received_qty"
if doc.doctype in ["Purchase Receipt", "Purchase Invoice"]:
select_fields += ",name"
for d in frappe.db.sql(
f"""select {select_fields} from `tab{doc.doctype} Item` where parent = %s""",
doc.return_against,
@@ -108,11 +105,13 @@ def validate_returned_items(doc):
for d in doc.get("items"):
key = d.item_code
raise_exception = False
if doc.doctype in ["Purchase Receipt", "Purchase Invoice"]:
if doc.doctype in ["Purchase Receipt", "Purchase Invoice", "Sales Invoice"]:
field = frappe.scrub(doc.doctype) + "_item"
if d.get(field):
key = (d.item_code, d.get(field))
raise_exception = True
elif doc.doctype == "Delivery Note":
key = (d.item_code, d.get("dn_detail"))
if d.item_code and (flt(d.qty) < 0 or flt(d.get("received_qty")) < 0):
if key not in valid_items:
@@ -124,7 +123,7 @@ def validate_returned_items(doc):
)
else:
ref = valid_items.get(key, frappe._dict())
validate_quantity(doc, d, ref, valid_items, already_returned_items)
validate_quantity(doc, key, d, ref, valid_items, already_returned_items)
if (
ref.rate
@@ -174,12 +173,12 @@ def validate_returned_items(doc):
frappe.throw(_("Atleast one item should be entered with negative quantity in return document"))
def validate_quantity(doc, args, ref, valid_items, already_returned_items):
def validate_quantity(doc, key, args, ref, valid_items, already_returned_items):
fields = ["stock_qty"]
if doc.doctype in ["Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"]:
fields.extend(["received_qty", "rejected_qty"])
already_returned_data = already_returned_items.get(args.item_code) or {}
already_returned_data = already_returned_items.get(key) or {}
company_currency = erpnext.get_company_currency(doc.company)
stock_qty_precision = get_field_precision(
@@ -262,15 +261,20 @@ def get_already_returned_items(doc):
column += """, sum(abs(child.rejected_qty) * child.conversion_factor) as rejected_qty,
sum(abs(child.received_qty) * child.conversion_factor) as received_qty"""
field = (
frappe.scrub(doc.doctype) + "_item"
if doc.doctype in ["Purchase Invoice", "Purchase Receipt", "Sales Invoice"]
else "dn_detail"
)
data = frappe.db.sql(
f"""
select {column}
select {column}, {field}
from
`tab{doc.doctype} Item` child, `tab{doc.doctype}` par
where
child.parent = par.name and par.docstatus = 1
and par.is_return = 1 and par.return_against = %s
group by item_code
group by item_code, {field}
""",
doc.return_against,
as_dict=1,
@@ -280,7 +284,7 @@ def get_already_returned_items(doc):
for d in data:
items.setdefault(
d.item_code,
(d.item_code, d.get(field)),
frappe._dict(
{
"qty": d.get("qty"),

View File

@@ -94,7 +94,10 @@ status_map = {
["To Bill", "eval:self.per_billed == 0 and self.docstatus == 1"],
["Partly Billed", "eval:self.per_billed > 0 and self.per_billed < 100 and self.docstatus == 1"],
["Return Issued", "eval:self.per_returned == 100 and self.docstatus == 1"],
["Completed", "eval:self.per_billed == 100 and self.docstatus == 1"],
[
"Completed",
"eval:(self.per_billed == 100 and self.docstatus == 1) or (self.docstatus == 1 and self.grand_total == 0 and self.per_returned != 100 and self.is_return == 0)",
],
["Cancelled", "eval:self.docstatus==2"],
["Closed", "eval:self.status=='Closed' and self.docstatus != 2"],
],

View File

@@ -18,7 +18,7 @@ from erpnext.controllers.accounts_controller import (
validate_inclusive_tax,
validate_taxes_and_charges,
)
from erpnext.stock.get_item_details import _get_item_tax_template
from erpnext.stock.get_item_details import _get_item_tax_template, get_item_tax_map
from erpnext.utilities.regional import temporary_flag
@@ -67,6 +67,7 @@ class calculate_taxes_and_totals:
self.validate_conversion_rate()
self.calculate_item_values()
self.validate_item_tax_template()
self.update_item_tax_map()
self.initialize_taxes()
self.determine_exclusive_rate()
self.calculate_net_total()
@@ -130,6 +131,14 @@ class calculate_taxes_and_totals:
)
)
def update_item_tax_map(self):
for item in self.doc.items:
item.item_tax_rate = get_item_tax_map(
company=self.doc.get("company"),
item_tax_template=item.item_tax_template,
as_json=True,
)
def validate_conversion_rate(self):
# validate conversion rate
company_currency = erpnext.get_company_currency(self.doc.company)

View File

@@ -38,7 +38,7 @@
"table_fieldname": "competitors"
}
],
"modified": "2023-11-23 19:33:54.284279",
"modified": "2024-12-10 08:26:38.496003",
"modified_by": "Administrator",
"module": "CRM",
"name": "Competitor",
@@ -53,20 +53,25 @@
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"role": "Sales Master Manager",
"share": 1,
"write": 1
},
{
"create": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales User",
"share": 1,
"write": 1
"role": "Sales User"
},
{
"read": 1,
"role": "Sales Manager"
},
{
"read": 1,
"role": "Maintenance Manager"
},
{
"read": 1,
"role": "Maintenance User"
}
],
"quick_entry": 1,

View File

@@ -25,7 +25,12 @@ frappe.ui.form.on("Plaid Settings", {
method: "erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.enqueue_synchronization",
freeze: true,
callback: () => {
let bank_transaction_link = '<a href="#List/Bank Transaction">Bank Transaction</a>';
let bank_transaction_link = frappe.utils.get_form_link(
"Bank Transaction",
"",
true,
"Bank Transaction"
);
frappe.msgprint({
title: __("Sync Started"),

View File

@@ -4,61 +4,67 @@ import frappe
from erpnext.tests.utils import ReportFilters, ReportName, execute_script_report
DEFAULT_FILTERS = {
"company": "_Test Company",
"from_date": "2010-01-01",
"to_date": "2030-01-01",
"warehouse": "_Test Warehouse - _TC",
}
REPORT_FILTER_TEST_CASES: list[tuple[ReportName, ReportFilters]] = [
("BOM Explorer", {"bom": frappe.get_last_doc("BOM").name}),
("BOM Operations Time", {}),
("BOM Stock Calculated", {"bom": frappe.get_last_doc("BOM").name, "qty_to_make": 2}),
("BOM Stock Report", {"bom": frappe.get_last_doc("BOM").name, "qty_to_produce": 2}),
("Cost of Poor Quality Report", {"item": "_Test Item", "serial_no": "00"}),
("Downtime Analysis", {}),
(
"Exponential Smoothing Forecasting",
{
"based_on_document": "Sales Order",
"based_on_field": "Qty",
"no_of_years": 3,
"periodicity": "Yearly",
"smoothing_constant": 0.3,
},
),
("Job Card Summary", {"fiscal_year": "2021-2022"}),
("Production Analytics", {"range": "Monthly"}),
("Quality Inspection Summary", {}),
("Process Loss Report", {}),
("Work Order Stock Report", {}),
("Work Order Summary", {"fiscal_year": "2021-2022", "age": 0}),
]
if frappe.db.a_row_exists("Production Plan"):
REPORT_FILTER_TEST_CASES.append(
("Production Plan Summary", {"production_plan": frappe.get_last_doc("Production Plan").name})
)
OPTIONAL_FILTERS = {
"warehouse": "_Test Warehouse - _TC",
"item": "_Test Item",
"item_group": "_Test Item Group",
}
class TestManufacturingReports(unittest.TestCase):
def setUp(self):
self.setup_default_filters()
def tearDown(self):
frappe.db.rollback()
def setup_default_filters(self):
self.last_bom = frappe.get_last_doc("BOM").name
self.DEFAULT_FILTERS = {
"company": "_Test Company",
"from_date": "2010-01-01",
"to_date": "2030-01-01",
"warehouse": "_Test Warehouse - _TC",
}
self.REPORT_FILTER_TEST_CASES: list[tuple[ReportName, ReportFilters]] = [
("BOM Explorer", {"bom": self.last_bom}),
("BOM Operations Time", {}),
("BOM Stock Calculated", {"bom": self.last_bom, "qty_to_make": 2}),
("BOM Stock Report", {"bom": self.last_bom, "qty_to_produce": 2}),
("Cost of Poor Quality Report", {"item": "_Test Item", "serial_no": "00"}),
("Downtime Analysis", {}),
(
"Exponential Smoothing Forecasting",
{
"based_on_document": "Sales Order",
"based_on_field": "Qty",
"no_of_years": 3,
"periodicity": "Yearly",
"smoothing_constant": 0.3,
},
),
("Job Card Summary", {"fiscal_year": "2021-2022"}),
("Production Analytics", {"range": "Monthly"}),
("Quality Inspection Summary", {}),
("Process Loss Report", {}),
("Work Order Stock Report", {}),
("Work Order Summary", {"fiscal_year": "2021-2022", "age": 0}),
]
if frappe.db.a_row_exists("Production Plan"):
self.REPORT_FILTER_TEST_CASES.append(
("Production Plan Summary", {"production_plan": frappe.get_last_doc("Production Plan").name})
)
self.OPTIONAL_FILTERS = {
"warehouse": "_Test Warehouse - _TC",
"item": "_Test Item",
"item_group": "_Test Item Group",
}
def test_execute_all_manufacturing_reports(self):
"""Test that all script report in manufacturing modules are executable with supported filters"""
for report, filter in REPORT_FILTER_TEST_CASES:
for report, filter in self.REPORT_FILTER_TEST_CASES:
with self.subTest(report=report):
execute_script_report(
report_name=report,
module="Manufacturing",
filters=filter,
default_filters=DEFAULT_FILTERS,
optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
default_filters=self.DEFAULT_FILTERS,
optional_filters=self.OPTIONAL_FILTERS if filter.get("_optional") else None,
)

View File

@@ -828,13 +828,13 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
);
}
if(!this.frm.doc.is_return){
this.frm.doc.payments.find(payment => {
if (payment.default) {
payment.amount = total_amount_to_pay;
}
});
}
this.frm.doc.payments.find(payment => {
if (payment.default) {
payment.amount = total_amount_to_pay;
} else {
payment.amount = 0
}
});
this.frm.refresh_fields();
}

View File

@@ -713,6 +713,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
}
validate() {
this.apply_pricing_rule()
this.calculate_taxes_and_totals(false);
}
@@ -841,6 +842,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
}
transaction_date() {
this.apply_pricing_rule()
if (this.frm.doc.transaction_date) {
this.frm.transaction_date = this.frm.doc.transaction_date;
frappe.ui.form.trigger(this.frm.doc.doctype, "currency");
@@ -849,6 +851,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
posting_date() {
var me = this;
me.apply_pricing_rule()
if (this.frm.doc.posting_date) {
this.frm.posting_date = this.frm.doc.posting_date;

View File

@@ -107,9 +107,12 @@ $.extend(erpnext.queries, {
},
dispatch_address_query: function (doc) {
var filters = { link_doctype: "Company", link_name: doc.company || "" };
var is_drop_ship = doc.items.some((item) => item.delivered_by_supplier);
if (is_drop_ship) filters = {};
return {
query: "frappe.contacts.doctype.address.address.address_query",
filters: { link_doctype: "Company", link_name: doc.company || "" },
filters: filters,
};
},

View File

@@ -284,6 +284,7 @@ erpnext.PointOfSale.Controller = class {
edit_cart: () => this.payment.edit_cart(),
customer_details_updated: (details) => {
this.item_selector.load_items_data();
this.customer_details = details;
// will add/remove LP payment method
this.payment.render_loyalty_points_payment_mode();

View File

@@ -235,7 +235,7 @@ erpnext.PointOfSale.Payment = class {
frappe.ui.form.on("Sales Invoice Payment", "amount", (frm, cdt, cdn) => {
// for setting correct amount after loyalty points are redeemed
const default_mop = locals[cdt][cdn];
const mode = default_mop.mode_of_payment.replace(/ +/g, "_").toLowerCase();
const mode = this.sanitize_mode_of_payment(default_mop.mode_of_payment);
if (this[`${mode}_control`] && this[`${mode}_control`].get_value() != default_mop.amount) {
this[`${mode}_control`].set_value(default_mop.amount);
}
@@ -383,7 +383,7 @@ erpnext.PointOfSale.Payment = class {
this.$payment_modes.html(
`${payments
.map((p, i) => {
const mode = p.mode_of_payment.replace(/ +/g, "_").toLowerCase();
const mode = this.sanitize_mode_of_payment(p.mode_of_payment);
const payment_type = p.type;
const margin = i % 2 === 0 ? "pr-2" : "pl-2";
const amount = p.amount > 0 ? format_currency(p.amount, currency) : "";
@@ -402,7 +402,7 @@ erpnext.PointOfSale.Payment = class {
);
payments.forEach((p) => {
const mode = p.mode_of_payment.replace(/ +/g, "_").toLowerCase();
const mode = this.sanitize_mode_of_payment(p.mode_of_payment);
const me = this;
this[`${mode}_control`] = frappe.ui.form.make_control({
df: {
@@ -437,7 +437,7 @@ erpnext.PointOfSale.Payment = class {
const doc = this.events.get_frm().doc;
const payments = doc.payments;
payments.forEach((p) => {
const mode = p.mode_of_payment.replace(/ +/g, "_").toLowerCase();
const mode = this.sanitize_mode_of_payment(p.mode_of_payment);
if (p.default) {
setTimeout(() => {
this.$payment_modes.find(`.${mode}.mode-of-payment-control`).parent().click();
@@ -607,4 +607,12 @@ erpnext.PointOfSale.Payment = class {
toggle_component(show) {
show ? this.$component.css("display", "flex") : this.$component.css("display", "none");
}
sanitize_mode_of_payment(mode_of_payment) {
return mode_of_payment
.replace(/ +/g, "_")
.replace(/[^\p{L}\p{N}_-]/gu, "")
.replace(/^[^_a-zA-Z\p{L}]+/u, "")
.toLowerCase();
}
};

View File

@@ -32,7 +32,7 @@
"table_fieldname": "lost_reasons"
}
],
"modified": "2023-11-23 19:31:02.743353",
"modified": "2024-12-10 08:21:38.280627",
"modified_by": "Administrator",
"module": "Setup",
"name": "Quotation Lost Reason",
@@ -49,6 +49,22 @@
"role": "Sales Master Manager",
"share": 1,
"write": 1
},
{
"read": 1,
"role": "Sales User"
},
{
"read": 1,
"role": "Sales Manager"
},
{
"read": 1,
"role": "Maintenance User"
},
{
"read": 1,
"role": "Maintenance Manager"
}
],
"quick_entry": 1,

View File

@@ -1,19 +1,37 @@
{
"chart_name": "Warehouse wise Stock Value",
"chart_type": "Custom",
"creation": "2020-07-20 21:01:04.296157",
"creation": "2022-03-30 00:58:02.018824",
"docstatus": 0,
"doctype": "Dashboard Chart",
"filters_json": "{}",
"idx": 0,
"is_public": 1,
"is_standard": 1,
"modified": "2020-07-22 13:01:01.815123",
"last_synced_on": "2024-12-23 18:44:46.822164",
"modified": "2024-12-23 19:31:17.003946",
"modified_by": "Administrator",
"module": "Stock",
"name": "Warehouse wise Stock Value",
"number_of_groups": 0,
"owner": "Administrator",
"roles": [
{
"role": "Sales Manager"
},
{
"role": "Accounts Manager"
},
{
"role": "Stock Manager"
},
{
"role": "Stock User"
},
{
"role": "Accounts User"
}
],
"source": "Warehouse wise Stock Value",
"timeseries": 0,
"type": "Bar",

View File

@@ -113,7 +113,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2023-05-17 11:46:04.448220",
"modified": "2024-12-19 13:48:46.618066",
"modified_by": "Administrator",
"module": "Stock",
"name": "Closing Stock Balance",
@@ -121,6 +121,7 @@
"owner": "Administrator",
"permissions": [
{
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
@@ -130,6 +131,35 @@
"report": 1,
"role": "System Manager",
"share": 1,
"submit": 1,
"write": 1
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock Manager",
"share": 1,
"submit": 1,
"write": 1
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock User",
"share": 1,
"submit": 1,
"write": 1
}
],

View File

@@ -44,7 +44,7 @@ class ClosingStockBalance(Document):
& (
(table.from_date.between(self.from_date, self.to_date))
| (table.to_date.between(self.from_date, self.to_date))
| ((table.from_date >= self.from_date) & (table.to_date >= self.to_date))
| ((self.from_date >= table.from_date) & (table.from_date >= self.to_date))
)
)
)

View File

@@ -982,6 +982,7 @@ def create_stock_entry(pick_list):
stock_entry = frappe.new_doc("Stock Entry")
stock_entry.pick_list = pick_list.get("name")
stock_entry.purpose = pick_list.get("purpose")
stock_entry.company = pick_list.get("company")
stock_entry.set_stock_entry_type()
if pick_list.get("work_order"):

View File

@@ -41,6 +41,7 @@ class StockLedgerEntry(Document):
self.flags.ignore_submit_comment = True
from erpnext.stock.utils import validate_disabled_warehouse, validate_warehouse_company
self.set_posting_datetime()
self.validate_mandatory()
self.validate_item()
self.validate_batch()
@@ -56,7 +57,6 @@ class StockLedgerEntry(Document):
from erpnext.stock.utils import get_combine_datetime
self.posting_datetime = get_combine_datetime(self.posting_date, self.posting_time)
self.db_set("posting_datetime", self.posting_datetime)
def validate_inventory_dimension_negative_stock(self):
if self.is_cancelled:
@@ -128,7 +128,6 @@ class StockLedgerEntry(Document):
return inv_dimension_dict
def on_submit(self):
self.set_posting_datetime()
self.check_stock_frozen_date()
self.calculate_batch_qty()

View File

@@ -640,7 +640,10 @@ def _get_item_tax_template(args, taxes, out=None, for_validate=False):
if tax.valid_from or tax.maximum_net_rate:
# In purchase Invoice first preference will be given to supplier invoice date
# if supplier date is not present then posting date
validation_date = args.get("bill_date") or args.get("transaction_date")
validation_date = (
args.get("bill_date") or args.get("posting_date") or args.get("transaction_date")
)
if getdate(tax.valid_from) <= getdate(validation_date) and is_within_valid_range(args, tax):
taxes_with_validity.append(tax)

View File

@@ -12,14 +12,14 @@
{% endif %}
{% for d in doc.taxes %}
{% if d.base_tax_amount %}
{% if d.tax_amount %}
<div class="order-taxes w-100 mt-5">
<div class="col-4 d-flex border-btm pb-5">
<div class="item-grand-total col-8">
{{ d.description }}
</div>
<div class="item-grand-total col-4 text-right pr-0">
{{ doc.get_formatted("net_total") }}
{{ d.get_formatted("tax_amount") }}
</div>
</div>
</div>