Compare commits

...

89 Commits

Author SHA1 Message Date
Frappe PR Bot
35c71f5923 chore(release): Bumped to Version 13.42.5
## [13.42.5](https://github.com/frappe/erpnext/compare/v13.42.4...v13.42.5) (2022-12-20)

### Bug Fixes

* conflict ([7ef0c6b](7ef0c6bb01))
* conflict in hooks file ([2a18067](2a18067aad))
* conflict in stock_entry ([4587bb3](4587bb3767))
* conflicts ([086e747](086e74791b))
* Consolidated financial report ([7825c56](7825c564eb))
* Cost center filter not working in cash flow report ([684a45f](684a45f234))
* daily scheduler to identify and fix stock transfer entries having incorrect valuation ([b82154c](b82154cb9e))
* disabled items showing in the report 'Itemwise Recommended Reorder Level ([c3fca3c](c3fca3cfcb))
* get_serial_nos not defined ([e5b3748](e5b3748b49))
* get_serial_nos_for_fg() missing 1 required positional argument: 'args' ([eddb7b4](eddb7b429e))
* linter issue ([ab2f250](ab2f250960))
* translation for warning on Overbilling/-receipt/-delivery ([b13ee4f](b13ee4fc8c))
* unsupported operand type(s) for +: 'int' and 'NoneType' ([a6241fc](a6241fc813))
* unsupported operand type(s) for +=: 'int' and 'NoneType' ([b573d97](b573d9739f))
2022-12-20 14:02:06 +00:00
Deepesh Garg
52d4e2acf8 Merge pull request #33403 from frappe/version-13-hotfix
chore: release v13
2022-12-20 19:30:24 +05:30
Deepesh Garg
3691eec66c Merge pull request #33401 from frappe/mergify/bp/version-13-hotfix/pr-33393
fix: Cost center filter not working in cash flow report (backport #33393)
2022-12-20 18:22:46 +05:30
rohitwaghchaure
e93af962a1 Merge pull request #33390 from frappe/mergify/bp/version-13-hotfix/pr-33387
fix: daily scheduler to identify and fix stock transfer entries having incorrect valuation (backport #33387)
2022-12-20 16:59:58 +05:30
rohitwaghchaure
9692eeeb15 Merge pull request #33392 from frappe/mergify/bp/version-13-hotfix/pr-33382
fix: unsupported operand type(s) for +=: 'int' and 'NoneType' (backport #33382)
2022-12-20 16:59:40 +05:30
Deepesh Garg
7825c564eb fix: Consolidated financial report 2022-12-20 16:52:28 +05:30
Deepesh Garg
e5fd95bb21 chore: remove print statement
(cherry picked from commit 068df9f815)
2022-12-20 08:17:21 +00:00
Deepesh Garg
684a45f234 fix: Cost center filter not working in cash flow report
(cherry picked from commit d0dbfec052)
2022-12-20 08:17:20 +00:00
rohitwaghchaure
7ef0c6bb01 fix: conflict 2022-12-20 11:55:22 +05:30
rohitwaghchaure
4587bb3767 fix: conflict in stock_entry 2022-12-20 11:52:33 +05:30
rohitwaghchaure
2a18067aad fix: conflict in hooks file 2022-12-20 11:49:22 +05:30
Rohit Waghchaure
b573d9739f fix: unsupported operand type(s) for +=: 'int' and 'NoneType'
(cherry picked from commit 2b4eae5f84)
2022-12-20 04:19:14 +00:00
Rohit Waghchaure
4dbce87660 test: added test case to validate audit for incorrect entries
(cherry picked from commit f31612376a)

# Conflicts:
#	erpnext/hooks.py
#	erpnext/stock/doctype/stock_entry/test_stock_entry.py
2022-12-20 04:18:19 +00:00
Rohit Waghchaure
b82154cb9e fix: daily scheduler to identify and fix stock transfer entries having incorrect valuation
(cherry picked from commit b1721b79ce)

# Conflicts:
#	erpnext/stock/doctype/stock_entry/stock_entry.py
2022-12-20 04:18:18 +00:00
Deepesh Garg
2105193594 Merge pull request #33367 from ruthra-kumar/using_subquery_for_fetching_dr_cr_notes
perf: using subquery in get_dr_or_cr_notes() to improve performance
2022-12-17 16:41:58 +05:30
Deepesh Garg
ef74c6689b Merge pull request #33360 from frappe/mergify/bp/version-13-hotfix/pr-33355
fix: disabled items showing in the report Itemwise Recommended Reorder Level (backport #33355)
2022-12-16 16:12:29 +05:30
ruthra kumar
799d7b254e refactor: using subquery in get_dr_or_cr_notes to improve performance 2022-12-16 14:06:05 +05:30
rohitwaghchaure
086e74791b fix: conflicts 2022-12-16 11:41:22 +05:30
Rohit Waghchaure
c3fca3cfcb fix: disabled items showing in the report 'Itemwise Recommended Reorder Level
'

(cherry picked from commit ae31ff1c48)

# Conflicts:
#	erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py
2022-12-15 12:39:14 +00:00
rohitwaghchaure
1634448864 Merge pull request #33357 from frappe/mergify/bp/version-13-hotfix/pr-33354
fix: unsupported operand type(s) for +: 'int' and 'NoneType' (backport #33354)
2022-12-15 18:08:33 +05:30
Rohit Waghchaure
a6241fc813 fix: unsupported operand type(s) for +: 'int' and 'NoneType'
(cherry picked from commit 0f28074e5a)
2022-12-15 11:44:56 +00:00
Deepesh Garg
896bac10bc Merge pull request #33343 from frappe/mergify/bp/version-13-hotfix/pr-33323
fix: translatability of warning on overbilling/-receipt/-delivery (backport #33323)
2022-12-15 09:17:19 +05:30
Raffael Meyer
0992ca40b0 chore: resolve merge conflict (2) 2022-12-15 00:13:13 +01:00
Raffael Meyer
10ac8d6e67 chore: resolve merge conflicts 2022-12-15 00:11:35 +01:00
rohitwaghchaure
c8a2f9f857 Merge pull request #33334 from frappe/mergify/bp/version-13-hotfix/pr-33332
fix: get_serial_nos_for_fg() missing 1 required positional argument: … (backport #33332)
2022-12-15 00:55:00 +05:30
barredterra
b13ee4fc8c fix: translation for warning on Overbilling/-receipt/-delivery
(cherry picked from commit 36997d9788)

# Conflicts:
#	erpnext/controllers/status_updater.py
#	erpnext/translations/de.csv
2022-12-14 17:55:29 +00:00
rohitwaghchaure
ab2f250960 fix: linter issue 2022-12-14 23:23:19 +05:30
rohitwaghchaure
e5b3748b49 fix: get_serial_nos not defined 2022-12-14 23:06:38 +05:30
Rohit Waghchaure
eddb7b429e fix: get_serial_nos_for_fg() missing 1 required positional argument: 'args'
(cherry picked from commit 410a58b3de)
2022-12-14 10:38:38 +00:00
Frappe PR Bot
b3a9c1eb2a chore(release): Bumped to Version 13.42.4
## [13.42.4](https://github.com/frappe/erpnext/compare/v13.42.3...v13.42.4) (2022-12-13)

### Bug Fixes

* `Enough Parts to Build` in `BOM Stock Report` ([50b2898](50b2898a2c))
* `Material Request` reference in internal `Sales Order` ([988a327](988a327b58))
* incorrect balance on parent company due to key mismatch ([b17ac52](b17ac522f5))
* order status in `Production Planning Report` ([2880469](2880469706))

### Performance Improvements

* add indexes on payment entry reference (backport [#33288](https://github.com/frappe/erpnext/issues/33288)) ([#33290](https://github.com/frappe/erpnext/issues/33290)) ([45f79ef](45f79ef644))
2022-12-13 12:31:01 +00:00
Ankush Menat
e44646054c Merge pull request #33317 from frappe/version-13-hotfix
chore: release v13
2022-12-13 17:59:05 +05:30
Sagar Sharma
12f11a6976 Merge pull request #33321 from frappe/mergify/bp/version-13-hotfix/pr-33314
fix: `Enough Parts to Build` in `BOM Stock Report` (backport #33314)
2022-12-13 15:58:15 +05:30
s-aga-r
50b2898a2c fix: Enough Parts to Build in BOM Stock Report
(cherry picked from commit 723c64ba73)
2022-12-13 09:50:30 +00:00
ruthra kumar
23830266f2 Merge pull request #33310 from frappe/mergify/bp/version-13-hotfix/pr-33303
fix: incorrect balance on parent company on consolidate Balance sheet due to key mismatch (backport #33303)
2022-12-13 13:56:31 +05:30
ruthra kumar
b17ac522f5 fix: incorrect balance on parent company due to key mismatch
(cherry picked from commit 7b3316dc31)
2022-12-13 03:36:32 +00:00
Sagar Sharma
1b22f53fde Merge pull request #33307 from frappe/mergify/bp/version-13-hotfix/pr-33304
fix: `Material Request` reference in internal `Sales Order` (backport #33304)
2022-12-13 00:01:25 +05:30
s-aga-r
988a327b58 fix: Material Request reference in internal Sales Order
(cherry picked from commit 78b438f6cf)
2022-12-12 18:19:15 +00:00
mergify[bot]
45f79ef644 perf: add indexes on payment entry reference (backport #33288) (#33290)
perf: add indexes on payment entry reference (#33288)

Adds index on:
1. reference doctype
2. reference name

*Why not composite index?*

There are three type of queries on this doctype

- filtering ref_doctype - doctype index helps here
- filtering ref_name - name index helps here
- filtering both - name index helps here too. Since it has sufficiently
  high cardinality. Composite index wont help in case where ref_doctype
  isn't specfied.

[skip ci]

(cherry picked from commit 593626f502)

Co-authored-by: Ankush Menat <ankush@frappe.io>
2022-12-12 13:02:08 +05:30
Sagar Sharma
bce3506e90 Merge pull request #33257 from frappe/mergify/bp/version-13-hotfix/pr-33255
fix: order status in `Production Planning Report` (backport #33255)
2022-12-08 00:04:53 +05:30
s-aga-r
2880469706 fix: order status in Production Planning Report
(cherry picked from commit 632c08f7e0)
2022-12-07 18:07:23 +00:00
Frappe PR Bot
104967881d chore(release): Bumped to Version 13.42.3
## [13.42.3](https://github.com/frappe/erpnext/compare/v13.42.2...v13.42.3) (2022-12-06)

### Bug Fixes

* add company filter in RFQ Items ([a716f78](a716f780a8))
* key error on p/l and balance sheet reports on foreign currency ([0003e0c](0003e0cb5b))
* key error while filtering on date range and different currency ([84ef814](84ef814f45))
* non empty FG batch picked while completing work order ([635d80d](635d80dc2f))
* remove duplicate schema ([4ad9aa2](4ad9aa29ee))
* replace sql code with fields list in get_cached_value ([b3ccad8](b3ccad8cf4))
2022-12-06 14:37:49 +00:00
Deepesh Garg
b2ef5f7cd2 Merge pull request #33232 from frappe/version-13-hotfix
chore: release v13
2022-12-06 20:06:03 +05:30
Deepesh Garg
cd5b8aeb64 Merge pull request #33234 from frappe/mergify/bp/version-13-hotfix/pr-33191
fix: key error while filtering on date range and reporting on foreign currency (backport #33191)
2022-12-06 17:36:37 +05:30
ruthra kumar
0003e0cb5b fix: key error on p/l and balance sheet reports on foreign currency
(cherry picked from commit a6794c3606)
2022-12-06 16:52:26 +05:30
ruthra kumar
b3ccad8cf4 fix: replace sql code with fields list in get_cached_value
(cherry picked from commit 19db7e2989)
2022-12-06 16:52:22 +05:30
ruthra kumar
84ef814f45 fix: key error while filtering on date range and different currency
(cherry picked from commit 9b8d6fe411)
2022-12-06 10:13:40 +00:00
rohitwaghchaure
ac432ea52f Merge pull request #33226 from frappe/mergify/bp/version-13-hotfix/pr-33224
fix: non empty FG batch picked while completing work order (backport #33224)
2022-12-05 23:58:52 +05:30
Rohit Waghchaure
635d80dc2f fix: non empty FG batch picked while completing work order
(cherry picked from commit 713330cbf6)
2022-12-05 15:00:38 +00:00
Sagar Sharma
0c4de03baa Merge pull request #33176 from frappe/mergify/bp/version-13-hotfix/pr-33174
fix: add company filter in RFQ Items (backport #33174)
2022-11-30 12:25:15 +05:30
s-aga-r
a716f780a8 fix: add company filter in RFQ Items
(cherry picked from commit ca0485a503)
2022-11-30 05:07:27 +00:00
Deepesh Garg
6f6598878e Merge pull request #33173 from frappe/mergify/bp/version-13-hotfix/pr-33115
fix: remove product schema block from additional info section on item template (backport #33115)
2022-11-30 09:46:49 +05:30
ruthra kumar
4ad9aa29ee fix: remove duplicate schema
(cherry picked from commit 2c18a95115)
2022-11-30 03:49:36 +00:00
Frappe PR Bot
e54b23d71b chore(release): Bumped to Version 13.42.2
## [13.42.2](https://github.com/frappe/erpnext/compare/v13.42.1...v13.42.2) (2022-11-29)

### Bug Fixes

* `production_item` filter in `Job Card Summary Report` ([ce54198](ce5419888b))
* `Work Order` filter typo in `Job Card Summary Report` ([2de239c](2de239c73b))
* cannot update auth token until token expiry if credentials change ([2121714](2121714856))
* company name with `,` in `Job Card Summary Report` ([ffef0cb](ffef0cb771))
* company name with `,` in `Work Order Summary Report` ([11978fc](11978fca4e))
* create rounding gl entry for PCV during gle post processing ([7af4597](7af45972ae))
* disbursable amount on currrent security price ([eca2d96](eca2d96419))
* Dispatch address display ([10cfcb5](10cfcb5e8a))
* incorrect balance qty ([78e64fa](78e64fa486))
* linter ([b91860d](b91860ddf2))
* MR Item `description` and `item_name` gets reset on `qty` change ([b66976b](b66976bd36))
* Multicurrency invoice with exchange gain and loss showing up in AR/AP report ([d38a289](d38a2895b0))
* only consider draft pending asset repair docs ([6da7b38](6da7b38f6e))
* only show serial no batch selector only once ([0c6a7ce](0c6a7cef95))
* reset `voucher_type` and `voucher_no` if `based_on` is set to `Item and Warehouse` ([ff59483](ff594831b0))
* validate voucher type while checking journal entry against payroll entry ([07c25ac](07c25ace5c))
2022-11-29 13:19:11 +00:00
Deepesh Garg
ba9220f9d2 Merge pull request #33164 from frappe/version-13-hotfix
chore: release v13
2022-11-29 18:47:36 +05:30
Sagar Sharma
354f258543 Merge pull request #33160 from frappe/mergify/bp/version-13-hotfix/pr-33136
fix: reset `voucher_type` and `voucher_no` if `based_on` is set to `Transaction` (backport #33136)
2022-11-29 13:24:45 +05:30
s-aga-r
f7d3f136c5 chore: make posting_date and posting_time read-only if based_on is set to Transaction
(cherry picked from commit 4e10352b48)
2022-11-29 06:44:57 +00:00
s-aga-r
ff594831b0 fix: reset voucher_type and voucher_no if based_on is set to Item and Warehouse
(cherry picked from commit eeec008547)
2022-11-29 06:44:57 +00:00
rohitwaghchaure
b08d36cb7b Merge pull request #33150 from frappe/mergify/bp/version-13-hotfix/pr-33144
fix: incorrect balance qty (backport #33144)
2022-11-29 12:06:09 +05:30
Sagar Sharma
cdb6a4e3f7 Merge branch 'version-13-hotfix' into mergify/bp/version-13-hotfix/pr-33144 2022-11-29 11:17:07 +05:30
Deepesh Garg
99188afa16 Merge pull request #33157 from frappe/mergify/bp/version-13-hotfix/pr-33116
fix: only show serial no batch selector only once (backport #33116)
2022-11-29 11:07:09 +05:30
Deepesh Garg
64fda0d4b7 Merge pull request #33028 from saurabh6790/small-fixes
chore: link payroll entry reference in accrual payroll journal entry
2022-11-29 10:53:42 +05:30
Shariq Ansari
0c6a7cef95 fix: only show serial no batch selector only once
(cherry picked from commit 0f87d329d6)
2022-11-29 04:51:41 +00:00
Rohit Waghchaure
c930d64e8d test: test case for serialized batched item
(cherry picked from commit b606a9684b)
2022-11-29 03:19:16 +00:00
Rohit Waghchaure
78e64fa486 fix: incorrect balance qty
(cherry picked from commit b2105a8be7)
2022-11-29 03:19:15 +00:00
Deepesh Garg
2a0d7acc2b Merge pull request #33122 from deepeshgarg007/receivable_payable_multi_currency
fix: Multicurrency invoice with exchange gain and loss showing up in AR/AP report
2022-11-28 22:49:06 +05:30
Sagar Sharma
24a3da55e6 Merge pull request #33124 from frappe/mergify/bp/version-13-hotfix/pr-33120
fix: `Work Order Summary` and `Job Card Summary` Report (backport #33120)
2022-11-27 23:23:06 +05:30
Sagar Sharma
c3289c265a Merge branch 'version-13-hotfix' into mergify/bp/version-13-hotfix/pr-33120 2022-11-27 22:11:06 +05:30
s-aga-r
b39f367dbd chore: conflicts 2022-11-27 22:10:10 +05:30
Deepesh Garg
d76e291927 Merge pull request #33114 from frappe/mergify/bp/version-13-hotfix/pr-33111
fix: Loan disbursable amount on current security price (backport #33111)
2022-11-27 20:50:19 +05:30
s-aga-r
ce5419888b fix: production_item filter in Job Card Summary Report
(cherry picked from commit ef7fd670fc)

# Conflicts:
#	erpnext/manufacturing/report/job_card_summary/job_card_summary.py
2022-11-26 16:25:16 +00:00
s-aga-r
ffef0cb771 fix: company name with , in Job Card Summary Report
(cherry picked from commit 481149814e)

# Conflicts:
#	erpnext/manufacturing/report/job_card_summary/job_card_summary.py
2022-11-26 16:25:15 +00:00
s-aga-r
2de239c73b fix: Work Order filter typo in Job Card Summary Report
(cherry picked from commit 2e4f3e9317)
2022-11-26 16:25:14 +00:00
s-aga-r
11978fca4e fix: company name with , in Work Order Summary Report
(cherry picked from commit 87b39f045c)
2022-11-26 16:25:14 +00:00
Deepesh Garg
d38a2895b0 fix: Multicurrency invoice with exchange gain and loss showing up in AR/AP report 2022-11-26 20:21:22 +05:30
Sagar Sharma
4492ee4771 Merge pull request #33109 from frappe/mergify/bp/version-13-hotfix/pr-33090
fix: MR Item `item_name` and `description` gets reset on `qty` change (backport #33090)
2022-11-26 10:07:37 +05:30
Abhinav Raut
eca2d96419 fix: disbursable amount on currrent security price
(cherry picked from commit fe87c27acd)
2022-11-25 09:49:03 +00:00
s-aga-r
b66976bd36 fix: MR Item description and item_name gets reset on qty change
(cherry picked from commit df0fee2312)
2022-11-25 05:50:10 +00:00
Deepesh Garg
776c8c6d6a Merge pull request #33093 from frappe/einv-reset-client-creds
fix: cannot update auth token until token expiry if credentials change
2022-11-24 21:25:46 +05:30
Deepesh Garg
452db7ed15 Merge pull request #33105 from frappe/mergify/bp/version-13-hotfix/pr-33100
fix: Dispatch address display (backport #33100)
2022-11-24 21:22:13 +05:30
Deepesh Garg
10cfcb5e8a fix: Dispatch address display
(cherry picked from commit 104fdcb9f9)
2022-11-24 12:31:40 +00:00
Saqib Ansari
b91860ddf2 fix: linter 2022-11-24 15:26:32 +05:30
Deepesh Garg
eda89a467c Merge pull request #33086 from AnandBaburajan/pending_asset_repair
fix: only consider draft pending asset repair docs
2022-11-24 14:37:36 +05:30
Saqib Ansari
2121714856 fix: cannot update auth token until token expiry if credentials change 2022-11-23 21:33:04 +05:30
Saurabh
8b46da39ea Merge branch 'version-13-hotfix' into small-fixes 2022-11-23 18:16:49 +05:30
anandbaburajan
6da7b38f6e fix: only consider draft pending asset repair docs 2022-11-23 13:05:52 +05:30
Deepesh Garg
7688239fc0 Merge pull request #33084 from frappe/mergify/bp/version-13-hotfix/pr-33062
fix: create rounding gl entry for PCV during gle post processing (backport #33062)
2022-11-23 11:50:14 +05:30
Saurabh
07c25ace5c fix: validate voucher type while checking journal entry against payroll entry 2022-11-23 11:45:50 +05:30
Saurabh
6ae21c92de chore: link payroll entry reference in accrual payroll journal entry 2022-11-23 11:45:50 +05:30
Nabin Hait
7af45972ae fix: create rounding gl entry for PCV during gle post processing
(cherry picked from commit 022d8d5d79)
2022-11-23 05:07:10 +00:00
38 changed files with 447 additions and 166 deletions

View File

@@ -4,7 +4,7 @@ import frappe
from erpnext.hooks import regional_overrides
__version__ = "13.42.1"
__version__ = "13.42.5"
def get_default_company(user=None):

View File

@@ -169,5 +169,6 @@ def auto_create_fiscal_year():
def get_from_and_to_date(fiscal_year):
fields = ["year_start_date as from_date", "year_end_date as to_date"]
return frappe.db.get_value("Fiscal Year", fiscal_year, fields, as_dict=1)
fields = ["year_start_date", "year_end_date"]
cached_results = frappe.get_cached_value("Fiscal Year", fiscal_year, fields, as_dict=1)
return dict(from_date=cached_results.year_start_date, to_date=cached_results.year_end_date)

View File

@@ -25,7 +25,8 @@
"in_list_view": 1,
"label": "Type",
"options": "DocType",
"reqd": 1
"reqd": 1,
"search_index": 1
},
{
"columns": 2,
@@ -35,7 +36,8 @@
"in_list_view": 1,
"label": "Name",
"options": "reference_doctype",
"reqd": 1
"reqd": 1,
"search_index": 1
},
{
"fieldname": "due_date",
@@ -104,7 +106,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2021-09-26 17:06:55.597389",
"modified": "2022-12-12 12:31:44.919895",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry Reference",
@@ -113,5 +115,6 @@
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}

View File

@@ -3,8 +3,10 @@
import frappe
from frappe import _, msgprint
from frappe import _, msgprint, qb
from frappe.model.document import Document
from frappe.query_builder import Criterion
from frappe.query_builder.functions import Sum
from frappe.utils import flt, getdate, nowdate, today
import erpnext
@@ -120,58 +122,77 @@ class PaymentReconciliation(Document):
return list(journal_entries)
def get_dr_or_cr_notes(self):
condition = self.get_conditions(get_return_invoices=True)
gl = qb.DocType("GL Entry")
voucher_type = "Sales Invoice" if self.party_type == "Customer" else "Purchase Invoice"
doc = qb.DocType(voucher_type)
# build conditions
sub_query_conditions = []
conditions = []
sub_query_conditions.append(doc.company == self.company)
if self.get("from_payment_date"):
sub_query_conditions.append(doc.posting_date.gte(self.from_payment_date))
if self.get("to_payment_date"):
sub_query_conditions.append(doc.posting_date.lte(self.to_payment_date))
if self.get("cost_center"):
condition += " and doc.cost_center = '{0}' ".format(self.cost_center)
sub_query_conditions.append(doc.cost_center == self.cost_center)
dr_or_cr = (
"credit_in_account_currency"
gl["credit_in_account_currency"]
if erpnext.get_party_account_type(self.party_type) == "Receivable"
else "debit_in_account_currency"
else gl["debit_in_account_currency"]
)
reconciled_dr_or_cr = (
"debit_in_account_currency"
if dr_or_cr == "credit_in_account_currency"
else "credit_in_account_currency"
gl["debit_in_account_currency"]
if dr_or_cr == gl["credit_in_account_currency"]
else gl["credit_in_account_currency"]
)
voucher_type = "Sales Invoice" if self.party_type == "Customer" else "Purchase Invoice"
if self.minimum_payment_amount:
conditions.append(dr_or_cr.gte(self.minimum_payment_amount))
if self.maximum_payment_amount:
conditions.append(dr_or_cr.lte(self.maximum_payment_amount))
return frappe.db.sql(
""" SELECT doc.name as reference_name, %(voucher_type)s as reference_type,
(sum(gl.{dr_or_cr}) - sum(gl.{reconciled_dr_or_cr})) as amount, doc.posting_date,
account_currency as currency
FROM `tab{doc}` doc, `tabGL Entry` gl
WHERE
(doc.name = gl.against_voucher or doc.name = gl.voucher_no)
and doc.{party_type_field} = %(party)s
and doc.is_return = 1 and ifnull(doc.return_against, "") = ""
and gl.against_voucher_type = %(voucher_type)s
and doc.docstatus = 1 and gl.party = %(party)s
and gl.party_type = %(party_type)s and gl.account = %(account)s
and gl.is_cancelled = 0 {condition}
GROUP BY doc.name
Having
amount > 0
ORDER BY doc.posting_date
""".format(
doc=voucher_type,
dr_or_cr=dr_or_cr,
reconciled_dr_or_cr=reconciled_dr_or_cr,
party_type_field=frappe.scrub(self.party_type),
condition=condition or "",
),
{
"party": self.party,
"party_type": self.party_type,
"voucher_type": voucher_type,
"account": self.receivable_payable_account,
},
as_dict=1,
sub_query = (
qb.from_(doc)
.select(doc.name)
.where(Criterion.all(sub_query_conditions))
.where(
(doc.docstatus == 1)
& (doc.is_return == 1)
& ((doc.return_against == "") | (doc.return_against.isnull()))
)
)
query = (
qb.from_(gl)
.select(
gl.voucher_type.as_("reference_type"),
gl.voucher_no.as_("reference_name"),
(Sum(dr_or_cr) - Sum(reconciled_dr_or_cr)).as_("amount"),
gl.posting_date,
gl.account_currency.as_("currency"),
)
.where(
(gl.voucher_type == voucher_type)
& (gl.voucher_no.isin(sub_query))
& (gl.is_cancelled == 0)
& (gl.account == self.receivable_payable_account)
& (gl.party_type == self.party_type)
& (gl.party == self.party)
)
.where(Criterion.all(conditions))
.groupby(gl.voucher_no)
.having(qb.Field("amount") > 0)
)
dr_cr_notes = query.run(as_dict=True)
return dr_cr_notes
def add_payment_entries(self, non_reconciled_payments):
self.set("payments", [])
@@ -369,7 +390,7 @@ class PaymentReconciliation(Document):
if not invoices_to_reconcile:
frappe.throw(_("No records found in Allocation table"))
def get_conditions(self, get_invoices=False, get_payments=False, get_return_invoices=False):
def get_conditions(self, get_invoices=False, get_payments=False):
condition = " and company = '{0}' ".format(self.company)
if get_invoices:
@@ -397,35 +418,7 @@ class PaymentReconciliation(Document):
condition += " and {dr_or_cr} <= {amount}".format(
dr_or_cr=dr_or_cr, amount=flt(self.maximum_invoice_amount)
)
elif get_return_invoices:
condition = " and doc.company = '{0}' ".format(self.company)
condition += (
" and doc.posting_date >= {0}".format(frappe.db.escape(self.from_payment_date))
if self.from_payment_date
else ""
)
condition += (
" and doc.posting_date <= {0}".format(frappe.db.escape(self.to_payment_date))
if self.to_payment_date
else ""
)
dr_or_cr = (
"debit_in_account_currency"
if erpnext.get_party_account_type(self.party_type) == "Receivable"
else "credit_in_account_currency"
)
if self.minimum_invoice_amount:
condition += " and gl.{dr_or_cr} >= {amount}".format(
dr_or_cr=dr_or_cr, amount=flt(self.minimum_payment_amount)
)
if self.maximum_invoice_amount:
condition += " and gl.{dr_or_cr} <= {amount}".format(
dr_or_cr=dr_or_cr, amount=flt(self.maximum_payment_amount)
)
else:
elif get_payments:
condition += (
" and posting_date >= {0}".format(frappe.db.escape(self.from_payment_date))
if self.from_payment_date

View File

@@ -298,20 +298,22 @@ 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(
gl_map[0].company, gl_map[0].voucher_type, gl_map[0].voucher_no
)
round_off_account_exists = False
round_off_gle = frappe._dict()
for d in gl_map:
if d.account == round_off_account:
round_off_gle = d
if d.debit:
debit_credit_diff -= flt(d.debit)
else:
debit_credit_diff += flt(d.credit)
round_off_account_exists = True
round_off_account_exists = False
if round_off_account_exists and abs(debit_credit_diff) < (1.0 / (10**precision)):
gl_map.remove(round_off_gle)
return
if gl_map[0].voucher_type != "Period Closing Voucher":
for d in gl_map:
if d.account == round_off_account:
round_off_gle = d
if d.debit:
debit_credit_diff -= flt(d.debit) - flt(d.credit)
else:
debit_credit_diff += flt(d.credit)
round_off_account_exists = True
if round_off_account_exists and abs(debit_credit_diff) < (1.0 / (10**precision)):
gl_map.remove(round_off_gle)
return
if not round_off_gle:
for k in ["voucher_type", "voucher_no", "company", "posting_date", "remarks"]:
@@ -334,7 +336,6 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
)
update_accounting_dimensions(round_off_gle)
if not round_off_account_exists:
gl_map.append(round_off_gle)

View File

@@ -685,10 +685,10 @@ class ReceivablePayableReport(object):
if self.filters.get(scrub(self.party_type)):
select_fields = "debit_in_account_currency as debit, credit_in_account_currency as credit"
doc_currency_fields = "debit as debit_in_account_currency, credit as credit_in_account_currency"
else:
select_fields = "debit, credit"
doc_currency_fields = "debit_in_account_currency, credit_in_account_currency"
doc_currency_fields = "debit_in_account_currency, credit_in_account_currency"
remarks = ", remarks" if self.filters.get("show_remarks") else ""

View File

@@ -9,6 +9,7 @@ from six import iteritems
from erpnext.accounts.report.financial_statements import (
get_columns,
get_cost_centers_with_children,
get_data,
get_filtered_list_for_consolidated_report,
get_period_list,
@@ -161,10 +162,11 @@ def get_account_type_based_data(company, account_type, period_list, accumulated_
total = 0
for period in period_list:
start_date = get_start_date(period, accumulated_values, company)
filters.start_date = start_date
filters.end_date = period["to_date"]
filters.account_type = account_type
amount = get_account_type_based_gl_data(
company, start_date, period["to_date"], account_type, filters
)
amount = get_account_type_based_gl_data(company, filters)
if amount and account_type == "Depreciation":
amount *= -1
@@ -176,7 +178,7 @@ def get_account_type_based_data(company, account_type, period_list, accumulated_
return data
def get_account_type_based_gl_data(company, start_date, end_date, account_type, filters=None):
def get_account_type_based_gl_data(company, filters=None):
cond = ""
filters = frappe._dict(filters or {})
@@ -192,17 +194,21 @@ def get_account_type_based_gl_data(company, start_date, end_date, account_type,
frappe.db.escape(cstr(filters.finance_book))
)
if filters.get("cost_center"):
filters.cost_center = get_cost_centers_with_children(filters.cost_center)
cond += " and cost_center in %(cost_center)s"
gl_sum = frappe.db.sql_list(
"""
select sum(credit) - sum(debit)
from `tabGL Entry`
where company=%s and posting_date >= %s and posting_date <= %s
where company=%(company)s and posting_date >= %(start_date)s and posting_date <= %(end_date)s
and voucher_type != 'Period Closing Voucher'
and account in ( SELECT name FROM tabAccount WHERE account_type = %s) {cond}
and account in ( SELECT name FROM tabAccount WHERE account_type = %(account_type)s) {cond}
""".format(
cond=cond
),
(company, start_date, end_date, account_type),
filters,
)
return gl_sum[0] if gl_sum and gl_sum[0] else 0

View File

@@ -268,10 +268,12 @@ def get_cash_flow_data(fiscal_year, companies, filters):
def get_account_type_based_data(account_type, companies, fiscal_year, filters):
data = {}
total = 0
filters.account_type = account_type
filters.start_date = fiscal_year.year_start_date
filters.end_date = fiscal_year.year_end_date
for company in companies:
amount = get_account_type_based_gl_data(
company, fiscal_year.year_start_date, fiscal_year.year_end_date, account_type, filters
)
amount = get_account_type_based_gl_data(company, filters)
if amount and account_type == "Depreciation":
amount *= -1
@@ -533,12 +535,13 @@ def get_accounts(root_type, companies):
],
filters={"company": company, "root_type": root_type},
):
if account.account_name not in added_accounts:
if account.account_number:
account_key = account.account_number + "-" + account.account_name
else:
account_key = account.account_name
if account_key not in added_accounts:
accounts.append(account)
if account.account_number:
account_key = account.account_number + "-" + account.account_name
else:
account_key = account.account_name
added_accounts.append(account_key)
return accounts

View File

@@ -28,7 +28,7 @@ def get_currency(filters):
filters["presentation_currency"] if filters.get("presentation_currency") else company_currency
)
report_date = filters.get("to_date")
report_date = filters.get("to_date") or filters.get("period_end_date")
if not report_date:
fiscal_year_to_date = get_from_and_to_date(filters.get("to_fiscal_year"))["to_date"]

View File

@@ -825,7 +825,9 @@ def update_maintenance_status():
for asset in assets:
asset = frappe.get_doc("Asset", asset.name)
if frappe.db.exists("Asset Repair", {"asset_name": asset.name, "repair_status": "Pending"}):
if frappe.db.exists(
"Asset Repair", {"asset_name": asset.name, "repair_status": "Pending", "docstatus": 0}
):
asset.set_status("Out of Order")
elif frappe.db.exists(
"Asset Maintenance Task", {"parent": asset.name, "next_due_date": today()}

View File

@@ -22,6 +22,13 @@ frappe.ui.form.on("Request for Quotation",{
}
};
}
frm.set_query('warehouse', 'items', () => ({
filters: {
company: frm.doc.company,
is_group: 0
}
}));
},
onload: function(frm) {

View File

@@ -578,6 +578,7 @@ class SellingController(StockController):
"customer_address": "address_display",
"shipping_address_name": "shipping_address",
"company_address": "company_address_display",
"dispatch_address_name": "dispatch_address",
}
for address_field, address_display_field in address_dict.items():

View File

@@ -333,16 +333,21 @@ class StatusUpdater(Document):
)
def warn_about_bypassing_with_role(self, item, qty_or_amount, role):
action = _("Over Receipt/Delivery") if qty_or_amount == "qty" else _("Overbilling")
if qty_or_amount == "qty":
msg = _("Over Receipt/Delivery of {0} {1} ignored for item {2} because you have {3} role.")
else:
msg = _("Overbilling of {0} {1} ignored for item {2} because you have {3} role.")
msg = _("{} of {} {} ignored for item {} because you have {} role.").format(
action,
_(item["target_ref_field"].title()),
frappe.bold(item["reduce_by"]),
frappe.bold(item.get("item_code")),
role,
frappe.msgprint(
msg.format(
_(item["target_ref_field"].title()),
frappe.bold(item["reduce_by"]),
frappe.bold(item.get("item_code")),
role,
),
indicator="orange",
alert=True,
)
frappe.msgprint(msg, indicator="orange", alert=True)
def update_qty(self, update_modified=True):
"""Updates qty or amount at row level

View File

@@ -526,6 +526,7 @@ scheduler_events = {
"erpnext.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall.create_process_loan_security_shortfall",
"erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual.process_loan_interest_accrual_for_term_loans",
"erpnext.crm.doctype.lead.lead.daily_open_lead",
"erpnext.stock.doctype.stock_entry.stock_entry.audit_incorrect_valuation_entries",
],
"weekly": ["erpnext.hr.doctype.employee.employee_reminders.send_reminders_in_advance_weekly"],
"monthly": ["erpnext.hr.doctype.employee.employee_reminders.send_reminders_in_advance_monthly"],

View File

@@ -191,7 +191,9 @@ def get_total_pledged_security_value(loan):
for security, qty in pledged_securities.items():
after_haircut_percentage = 100 - hair_cut_map.get(security)
security_value += (loan_security_price_map.get(security) * qty * after_haircut_percentage) / 100
security_value += (
loan_security_price_map.get(security, 0) * qty * after_haircut_percentage
) / 100
return security_value

View File

@@ -625,6 +625,10 @@ class TestWorkOrder(FrappeTestCase):
bom.submit()
bom_name = bom.name
ste1 = test_stock_entry.make_stock_entry(
item_code=rm1, target="_Test Warehouse - _TC", qty=32, basic_rate=5000.0
)
work_order = make_wo_order_test_record(
item=fg_item, skip_transfer=True, planned_start_date=now(), qty=1
)
@@ -649,11 +653,29 @@ class TestWorkOrder(FrappeTestCase):
work_order.insert()
work_order.submit()
self.assertEqual(work_order.has_batch_no, 1)
ste1 = frappe.get_doc(make_stock_entry(work_order.name, "Manufacture", 30))
batches = frappe.get_all("Batch", filters={"reference_name": work_order.name})
self.assertEqual(len(batches), 3)
batches = [batch.name for batch in batches]
ste1 = frappe.get_doc(make_stock_entry(work_order.name, "Manufacture", 10))
for row in ste1.get("items"):
if row.is_finished_item:
self.assertEqual(row.item_code, fg_item)
self.assertEqual(row.qty, 10)
self.assertTrue(row.batch_no in batches)
batches.remove(row.batch_no)
ste1.submit()
remaining_batches = []
ste1 = frappe.get_doc(make_stock_entry(work_order.name, "Manufacture", 20))
for row in ste1.get("items"):
if row.is_finished_item:
self.assertEqual(row.item_code, fg_item)
self.assertEqual(row.qty, 10)
remaining_batches.append(row.batch_no)
self.assertEqual(sorted(remaining_batches), sorted(batches))
frappe.db.set_value("Manufacturing Settings", None, "make_serial_no_batch_from_work_order", 0)
@@ -1123,6 +1145,37 @@ class TestWorkOrder(FrappeTestCase):
except frappe.MandatoryError:
self.fail("Batch generation causing failing in Work Order")
@change_settings("Manufacturing Settings", {"make_serial_no_batch_from_work_order": 1})
def test_auto_serial_no_creation(self):
from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
fg_item = frappe.generate_hash(length=20)
child_item = frappe.generate_hash(length=20)
bom_tree = {fg_item: {child_item: {}}}
create_nested_bom(bom_tree, prefix="")
item = frappe.get_doc("Item", fg_item)
item.has_serial_no = 1
item.serial_no_series = f"{item.name}.#####"
item.save()
try:
wo_order = make_wo_order_test_record(item=fg_item, qty=2, skip_transfer=True)
serial_nos = wo_order.serial_no
stock_entry = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 10))
stock_entry.set_work_order_details()
stock_entry.set_serial_no_batch_for_finished_good()
for row in stock_entry.items:
if row.item_code == fg_item:
self.assertTrue(row.serial_no)
self.assertEqual(sorted(get_serial_nos(row.serial_no)), sorted(get_serial_nos(serial_nos)))
except frappe.MandatoryError:
self.fail("Batch generation causing failing in Work Order")
@change_settings(
"Manufacturing Settings",
{"backflush_raw_materials_based_on": "Material Transferred for Manufacture"},

View File

@@ -4,7 +4,7 @@
import frappe
from frappe import _
from frappe.query_builder.functions import Floor, Sum
from frappe.query_builder.functions import Sum
from pypika.terms import ExistsCriterion
@@ -58,9 +58,9 @@ def get_bom_stock(filters):
bom_item.description,
bom_item.stock_qty,
bom_item.stock_uom,
bom_item.stock_qty * qty_to_produce / bom.quantity,
Sum(bin.actual_qty).as_("actual_qty"),
Sum(Floor(bin.actual_qty / (bom_item.stock_qty * qty_to_produce / bom.quantity))),
(bom_item.stock_qty / bom.quantity) * qty_to_produce,
Sum(bin.actual_qty),
Sum(bin.actual_qty) / (bom_item.stock_qty / bom.quantity),
)
.where((bom_item.parent == filters.get("bom")) & (bom_item.parenttype == "BOM"))
.groupby(bom_item.item_code)

View File

@@ -54,11 +54,11 @@ frappe.query_reports["Job Card Summary"] = {
options: ["", "Open", "Work In Progress", "Completed", "On Hold"]
},
{
label: __("Sales Orders"),
fieldname: "sales_order",
label: __("Work Orders"),
fieldname: "work_order",
fieldtype: "MultiSelectList",
get_data: function(txt) {
return frappe.db.get_link_options('Sales Order', txt);
return frappe.db.get_link_options('Work Order', txt);
}
},
{

View File

@@ -36,10 +36,14 @@ def get_data(filters):
"total_time_in_mins",
]
for field in ["work_order", "workstation", "operation", "company"]:
for field in ["work_order", "production_item"]:
if filters.get(field):
query_filters[field] = ("in", filters.get(field))
for field in ["workstation", "operation", "status", "company"]:
if filters.get(field):
query_filters[field] = filters.get(field)
data = frappe.get_all("Job Card", fields=fields, filters=query_filters)
if not data:

View File

@@ -49,7 +49,7 @@ class ProductionPlanReport(object):
parent.bom_no,
parent.fg_warehouse.as_("warehouse"),
)
.where(parent.status.notin(["Completed", "Stopped"]))
.where(parent.status.notin(["Completed", "Stopped", "Closed"]))
)
if order_by == "Planned Start Date":
@@ -79,10 +79,11 @@ class ProductionPlanReport(object):
query = query.where(child.parent.isin(self.filters.docnames))
if doctype == "Sales Order":
query = query.select(
child.delivery_date,
parent.base_grand_total,
).where((child.stock_qty > child.produced_qty) & (parent.per_delivered < 100.0))
query = query.select(child.delivery_date, parent.base_grand_total,).where(
(child.stock_qty > child.produced_qty)
& (parent.per_delivered < 100.0)
& (parent.status.notin(["Completed", "Closed"]))
)
if order_by == "Delivery Date":
query = query.orderby(child.delivery_date, order=Order.asc)
@@ -91,7 +92,9 @@ class ProductionPlanReport(object):
elif doctype == "Material Request":
query = query.select(child.schedule_date,).where(
(parent.per_ordered < 100) & (parent.material_request_type == "Manufacture")
(parent.per_ordered < 100)
& (parent.material_request_type == "Manufacture")
& (parent.status != "Stopped")
)
if order_by == "Required Date":

View File

@@ -39,10 +39,14 @@ def get_data(filters):
"lead_time",
]
for field in ["sales_order", "production_item", "status", "company"]:
for field in ["sales_order", "production_item"]:
if filters.get(field):
query_filters[field] = ("in", filters.get(field))
for field in ["status", "company"]:
if filters.get(field):
query_filters[field] = filters.get(field)
query_filters["planned_start_date"] = (">=", filters.get("from_date"))
query_filters["planned_end_date"] = ("<=", filters.get("to_date"))

View File

@@ -346,6 +346,8 @@ class PayrollEntry(Document):
"credit_in_account_currency": flt(payable_amt, precision),
"exchange_rate": flt(exchange_rate),
"cost_center": self.cost_center,
"reference_type": self.doctype,
"reference_name": self.name,
},
accounting_dimensions,
)
@@ -720,12 +722,21 @@ def get_month_details(year, month):
def get_payroll_entry_bank_entries(payroll_entry_name):
journal_entries = frappe.db.sql(
"select name from `tabJournal Entry Account` "
'where reference_type="Payroll Entry" '
"and reference_name=%s and docstatus=1",
"""
select
je.name
from
`tabJournal Entry` je,
`tabJournal Entry Account` jea
where
je.name = jea.parent
and je.voucher_type = 'Bank Entry'
and jea.reference_type = 'Payroll Entry'
and jea.reference_name = %s
""",
payroll_entry_name,
as_dict=1,
)
as_dict=True,
) # nosemgrep
return journal_entries

View File

@@ -133,9 +133,17 @@ class TestPayrollEntry(FrappeTestCase):
payment_entry = frappe.db.sql(
"""
Select ifnull(sum(je.total_debit),0) as total_debit, ifnull(sum(je.total_credit),0) as total_credit from `tabJournal Entry` je, `tabJournal Entry Account` jea
Where je.name = jea.parent
And jea.reference_name = %s
select
ifnull(sum(je.total_debit),0) as total_debit,
ifnull(sum(je.total_credit),0) as total_credit
from
`tabJournal Entry` je,
`tabJournal Entry Account` jea
Where
je.name = jea.parent
and je.voucher_type = 'Bank Entry'
and jea.reference_type = 'Payroll Entry'
and jea.reference_name = %s
""",
(payroll_entry.name),
as_dict=1,

View File

@@ -10,3 +10,8 @@ class EInvoiceSettings(Document):
def validate(self):
if self.enable and not self.credentials:
frappe.throw(_("You must add atleast one credentials to be able to use E Invoicing."))
prev_doc = self.get_doc_before_save()
if prev_doc.client_secret != self.client_secret or prev_doc.client_id != self.client_id:
self.auth_token = None
self.token_expiry = None

View File

@@ -12,7 +12,10 @@ def get_data():
"Auto Repeat": "reference_document",
"Maintenance Visit": "prevdoc_docname",
},
"internal_links": {"Quotation": ["items", "prevdoc_docname"]},
"internal_links": {
"Quotation": ["items", "prevdoc_docname"],
"Material Request": ["items", "material_request"],
},
"transactions": [
{
"label": _("Fulfillment"),

View File

@@ -370,9 +370,6 @@ frappe.ui.form.on("Material Request Item", {
if (flt(d.qty) < flt(d.min_order_qty)) {
frappe.msgprint(__("Warning: Material Requested Qty is less than Minimum Order Qty"));
}
const item = locals[doctype][name];
frm.events.get_item_data(frm, item, false);
},
from_warehouse: function(frm, doctype, name) {

View File

@@ -181,13 +181,13 @@ class PickList(Document):
if item_map.get(key):
item_map[key].qty += item.qty
item_map[key].stock_qty += item.stock_qty
item_map[key].stock_qty += flt(item.stock_qty, item.precision("stock_qty"))
else:
item_map[key] = item
# maintain count of each item (useful to limit get query)
self.item_count_map.setdefault(item_code, 0)
self.item_count_map[item_code] += item.stock_qty
self.item_count_map[item_code] += flt(item.stock_qty, item.precision("stock_qty"))
return item_map.values()

View File

@@ -34,6 +34,22 @@ frappe.ui.form.on('Repost Item Valuation', {
frm.trigger('setup_realtime_progress');
},
based_on: function(frm) {
var fields_to_reset = [];
if (frm.doc.based_on == 'Transaction') {
fields_to_reset = ['item_code', 'warehouse'];
} else if (frm.doc.based_on == 'Item and Warehouse') {
fields_to_reset = ['voucher_type', 'voucher_no'];
}
if (fields_to_reset) {
fields_to_reset.forEach(field => {
frm.set_value(field, undefined);
});
}
},
setup_realtime_progress: function(frm) {
frappe.realtime.on('item_reposting_progress', data => {
if (frm.doc.name !== data.name) {

View File

@@ -50,13 +50,15 @@
"fieldname": "posting_date",
"fieldtype": "Date",
"label": "Posting Date",
"read_only_depends_on": "eval: doc.based_on == \"Transaction\"",
"reqd": 1
},
{
"fetch_from": "voucher_no.posting_time",
"fieldname": "posting_time",
"fieldtype": "Time",
"label": "Posting Time"
"label": "Posting Time",
"read_only_depends_on": "eval: doc.based_on == \"Transaction\""
},
{
"default": "Queued",
@@ -195,7 +197,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2022-06-13 12:20:22.182322",
"modified": "2022-11-28 16:00:05.637440",
"modified_by": "Administrator",
"module": "Stock",
"name": "Repost Item Valuation",

View File

@@ -1050,7 +1050,8 @@ erpnext.stock.select_batch_and_serial_no = (frm, item) => {
if (frm.doc.purpose === 'Material Receipt') return;
frappe.require("assets/erpnext/js/utils/serial_no_batch_selector.js", function() {
new erpnext.SerialNoBatchSelector({
if (frm.batch_selector?.dialog?.display) return;
frm.batch_selector = new erpnext.SerialNoBatchSelector({
frm: frm,
item: item,
warehouse_details: get_warehouse_type_and_name(item),

View File

@@ -4,13 +4,25 @@
import json
from collections import defaultdict
from typing import Dict
import frappe
from frappe import _
from frappe.model.mapper import get_mapped_doc
from frappe.query_builder.functions import Sum
from frappe.utils import cint, comma_or, cstr, flt, format_time, formatdate, getdate, nowdate
from six import iteritems, itervalues, string_types
from frappe.utils import (
add_days,
cint,
comma_or,
cstr,
flt,
format_time,
formatdate,
getdate,
nowdate,
today,
)
import erpnext
from erpnext.accounts.general_ledger import process_gl_map
@@ -1474,6 +1486,7 @@ class StockEntry(StockController):
"reference_name": self.pro_doc.name,
"reference_doctype": self.pro_doc.doctype,
"qty_to_produce": (">", 0),
"batch_qty": ("=", 0),
}
fields = ["qty_to_produce as qty", "produced_qty", "name"]
@@ -2191,16 +2204,16 @@ class StockEntry(StockController):
d.qty -= process_loss_dict[d.item_code][1]
def set_serial_no_batch_for_finished_good(self):
args = {}
serial_nos = []
if self.pro_doc.serial_no:
self.get_serial_nos_for_fg(args)
serial_nos = self.get_serial_nos_for_fg() or []
for row in self.items:
if row.is_finished_item and row.item_code == self.pro_doc.production_item:
if args.get("serial_no"):
row.serial_no = "\n".join(args["serial_no"][0 : cint(row.qty)])
if serial_nos:
row.serial_no = "\n".join(serial_nos[0 : cint(row.qty)])
def get_serial_nos_for_fg(self, args):
def get_serial_nos_for_fg(self):
fields = [
"`tabStock Entry`.`name`",
"`tabStock Entry Detail`.`qty`",
@@ -2211,14 +2224,12 @@ class StockEntry(StockController):
filters = [
["Stock Entry", "work_order", "=", self.work_order],
["Stock Entry", "purpose", "=", "Manufacture"],
["Stock Entry", "docstatus", "=", 1],
["Stock Entry", "docstatus", "<", 2],
["Stock Entry Detail", "item_code", "=", self.pro_doc.production_item],
]
stock_entries = frappe.get_all("Stock Entry", fields=fields, filters=filters)
if self.pro_doc.serial_no:
args["serial_no"] = self.get_available_serial_nos(stock_entries)
return self.get_available_serial_nos(stock_entries)
def get_available_serial_nos(self, stock_entries):
used_serial_nos = []
@@ -2555,3 +2566,63 @@ def get_supplied_items(purchase_order):
)
return supplied_item_details
def audit_incorrect_valuation_entries():
# Audit of stock transfer entries having incorrect valuation
from erpnext.controllers.stock_controller import create_repost_item_valuation_entry
stock_entries = get_incorrect_stock_entries()
for stock_entry, values in stock_entries.items():
reposting_data = frappe._dict(
{
"posting_date": values.posting_date,
"posting_time": values.posting_time,
"voucher_type": "Stock Entry",
"voucher_no": stock_entry,
"company": values.company,
}
)
create_repost_item_valuation_entry(reposting_data)
def get_incorrect_stock_entries() -> Dict:
stock_entry = frappe.qb.DocType("Stock Entry")
stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry")
transfer_purposes = [
"Material Transfer",
"Material Transfer for Manufacture",
"Send to Subcontractor",
]
query = (
frappe.qb.from_(stock_entry)
.inner_join(stock_ledger_entry)
.on(stock_entry.name == stock_ledger_entry.voucher_no)
.select(
stock_entry.name,
stock_entry.company,
stock_entry.posting_date,
stock_entry.posting_time,
Sum(stock_ledger_entry.stock_value_difference).as_("stock_value"),
)
.where(
(stock_entry.docstatus == 1)
& (stock_entry.purpose.isin(transfer_purposes))
& (stock_ledger_entry.modified > add_days(today(), -2))
)
.groupby(stock_ledger_entry.voucher_detail_no)
.having(Sum(stock_ledger_entry.stock_value_difference) != 0)
)
data = query.run(as_dict=True)
stock_entries = {}
for row in data:
if abs(row.stock_value) > 0.1 and row.name not in stock_entries:
stock_entries.setdefault(row.name, row)
return stock_entries

View File

@@ -5,7 +5,7 @@
import frappe
from frappe.permissions import add_user_permission, remove_user_permission
from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import add_days, flt, nowdate, nowtime, today
from frappe.utils import add_days, flt, now, nowdate, nowtime, today
from six import iteritems
from erpnext.accounts.doctype.account.test_account import get_inventory_account
@@ -18,6 +18,8 @@ from erpnext.stock.doctype.item.test_item import (
from erpnext.stock.doctype.serial_no.serial_no import * # noqa
from erpnext.stock.doctype.stock_entry.stock_entry import (
FinishedGoodError,
audit_incorrect_valuation_entries,
get_incorrect_stock_entries,
move_sample_to_retention_warehouse,
)
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
@@ -1571,6 +1573,44 @@ class TestStockEntry(FrappeTestCase):
self.assertRaises(BatchExpiredError, se.save)
def test_audit_incorrect_stock_entries(self):
item_code = "Test Incorrect Valuation Rate Item - 001"
create_item(item_code=item_code, is_stock_item=1)
make_stock_entry(
item_code=item_code,
purpose="Material Receipt",
posting_date=add_days(nowdate(), -10),
qty=2,
rate=500,
to_warehouse="_Test Warehouse - _TC",
)
transfer_entry = make_stock_entry(
item_code=item_code,
purpose="Material Transfer",
qty=2,
rate=500,
from_warehouse="_Test Warehouse - _TC",
to_warehouse="_Test Warehouse 1 - _TC",
)
sle_name = frappe.db.get_value(
"Stock Ledger Entry", {"voucher_no": transfer_entry.name, "actual_qty": (">", 0)}, "name"
)
frappe.db.set_value(
"Stock Ledger Entry", sle_name, {"modified": add_days(now(), -1), "stock_value_difference": 10}
)
stock_entries = get_incorrect_stock_entries()
self.assertTrue(transfer_entry.name in stock_entries)
audit_incorrect_valuation_entries()
stock_entries = get_incorrect_stock_entries()
self.assertFalse(transfer_entry.name in stock_entries)
def make_serialized_item(**args):
args = frappe._dict(args)

View File

@@ -229,7 +229,7 @@ class StockReconciliation(StockController):
if item.has_serial_no or item.has_batch_no:
has_serial_no = True
self.get_sle_for_serialized_items(row, sl_entries)
self.get_sle_for_serialized_items(row, sl_entries, item)
else:
if row.serial_no or row.batch_no:
frappe.throw(
@@ -281,7 +281,7 @@ class StockReconciliation(StockController):
if has_serial_no and sl_entries:
self.update_valuation_rate_for_serial_no()
def get_sle_for_serialized_items(self, row, sl_entries):
def get_sle_for_serialized_items(self, row, sl_entries, item):
from erpnext.stock.stock_ledger import get_previous_sle
serial_nos = get_serial_nos(row.serial_no)
@@ -347,6 +347,9 @@ class StockReconciliation(StockController):
if row.qty:
args = self.get_sle_for_items(row)
if item.has_serial_no and item.has_batch_no:
args["qty_after_transaction"] = row.qty
args.update(
{
"actual_qty": row.qty,

View File

@@ -643,6 +643,38 @@ class TestStockReconciliation(FrappeTestCase, StockTestMixin):
)
self.assertEqual(len(active_sr_no), 0)
def test_serial_no_batch_no_item(self):
item = self.make_item(
"Test Serial No Batch No Item",
{
"is_stock_item": 1,
"has_serial_no": 1,
"has_batch_no": 1,
"serial_no_series": "SRS9.####",
"batch_number_series": "BNS9.####",
"create_new_batch": 1,
},
)
warehouse = "_Test Warehouse - _TC"
sr = create_stock_reconciliation(
item_code=item.name,
warehouse=warehouse,
qty=1,
rate=100,
)
sl_entry = frappe.db.get_value(
"Stock Ledger Entry",
{"voucher_type": "Stock Reconciliation", "voucher_no": sr.name},
["actual_qty", "qty_after_transaction"],
as_dict=1,
)
self.assertEqual(flt(sl_entry.actual_qty), 1.0)
self.assertEqual(flt(sl_entry.qty_after_transaction), 1.0)
def create_batch_item_with_batch(item_name, batch_id):
batch_item_doc = create_item(item_name, is_stock_item=1)

View File

@@ -813,9 +813,9 @@ def insert_item_price(args):
):
if frappe.has_permission("Item Price", "write"):
price_list_rate = (
(args.rate + args.discount_amount) / args.get("conversion_factor")
(flt(args.rate) + flt(args.discount_amount)) / args.get("conversion_factor")
if args.get("conversion_factor")
else (args.rate + args.discount_amount)
else (flt(args.rate) + flt(args.discount_amount))
)
item_price = frappe.db.get_value(

View File

@@ -75,6 +75,7 @@ def get_item_info(filters):
if filters.get("brand"):
conditions.append("item.brand=%(brand)s")
conditions.append("is_stock_item = 1")
conditions.append("disabled = 0")
return frappe.db.sql(
"""select name, item_name, description, brand, item_group,

View File

@@ -32,7 +32,7 @@
<div class="product-container mt-4 {{ padding_top }} {{ info_col }}">
<div class="item-content {{ 'mt-minus-2' if (show_tabs and tabs) else '' }}">
<div class="product-page-content" itemscope itemtype="http://schema.org/Product">
<div class="product-page-content">
<!-- Product Specifications Table Section -->
{% if show_tabs and tabs %}
<div class="category-tabs">

View File

@@ -1844,6 +1844,8 @@ Outstanding Amt,Offener Betrag,
Outstanding Cheques and Deposits to clear,Ausstehende Schecks und Anzahlungen zum verbuchen,
Outstanding for {0} cannot be less than zero ({1}),Ausstände für {0} können nicht kleiner als Null sein ({1}),
Outward taxable supplies(zero rated),Steuerpflichtige Lieferungen aus dem Ausland (null bewertet),
Over Receipt/Delivery of {0} {1} ignored for item {2} because you have {3} role.,"Überhöhte Annahme bzw. Lieferung von Artikel {2} mit {0} {1} wurde ignoriert, weil Sie die Rolle {3} haben."
Overbilling of {0} {1} ignored for item {2} because you have {3} role.,"Überhöhte Abrechnung von Artikel {2} mit {0} {1} wurde ignoriert, weil Sie die Rolle {3} haben."
Overdue,Überfällig,
Overlap in scoring between {0} and {1},Überlappung beim Scoring zwischen {0} und {1},
Overlapping conditions found between:,Überlagernde Bedingungen gefunden zwischen:,
Can't render this file because it is too large.