From 3e85b4937bb1b197cecffd08cdcf2e698c8f12a7 Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Mon, 22 Jul 2019 17:31:14 +0530 Subject: [PATCH 001/124] Release Version 12 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index cb88a1122e..020f843c1a 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '11.1.39' +__version__ = '12.0.0' def get_default_company(user=None): '''Get default company for user''' From 85d88395ba315ede94320861e882f079a564ab64 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 22 Jul 2019 17:39:18 +0530 Subject: [PATCH 002/124] changelog: release 12.0.0 --- erpnext/change_log/v12/v12_0_0.md | 41 +++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 erpnext/change_log/v12/v12_0_0.md diff --git a/erpnext/change_log/v12/v12_0_0.md b/erpnext/change_log/v12/v12_0_0.md new file mode 100644 index 0000000000..dcbc9a00dd --- /dev/null +++ b/erpnext/change_log/v12/v12_0_0.md @@ -0,0 +1,41 @@ +# Version 12 Release Notes + +### Accounting +1. [Accounting Dimensions](/docs/user/manual/en/accounts/accounting-dimensions) +1. [Chart of Accounts Importer](/docs/user/manual/en/setting-up/chart-of-accounts-importer) +1. [Invoice Discounting](/docs/user/manual/en/accounts/invoice_discounting) +1. [Tally Migrator](https://github.com/frappe/erpnext/pull/17405) + +### Stock +1. [Serialized & Batched Item Reconciliation](/docs/user/manual/en/setting-up/stock-reconciliation#12-for-serialized-items) +1. [Auto Fetch Serialized Items](/version-12/release-notes/features#new-upload-dialog) +1. [Item Tax Templates](/docs/user/manual/en/accounts/item-tax-template) + +### HR +1. [Auto Attendance](/docs/user/manual/en/human-resources/auto-attendance) +1. [Employee Skill Map](/docs/user/manual/en/human-resources/employee_skill_map) +1. [Encrypted Salary Slips](/docs/user/manual/en/human-resources/hr-settings#24-encrypt-salary-slips-in-emails) +1. [Leave Ledger](/docs/user/manual/en/human-resources/leave-ledger-entry) +1. [Staffing Plan](/docs/user/manual/en/human-resources/staffing-plan) + +### CRM +1. [Promotional Scheme](/docs/user/manual/en/accounts/promotional-schemes) +1. [SLA](/docs/user/manual/en/support/service-level-agreement) +1. [Exotel Call Integration](/docs/user/manual/en/erpnext_integration/exotel_integration) +1. [Email Campaign](/docs/user/manual/en/CRM/email-campaign) + +### Domain Specific Features +1. [Learning Management System](/docs/user/manual/en/education/setting-up-lms) +1. [Quality Management System](/docs/user/manual/en/quality-management) +1. [Production Planning Enhancements](/docs/user/manual/en/manufacturing/production-plan/planning-for-material-requests) +1. [Project Template](/docs/user/manual/en/projects/project-template) + +### New Reports +1. [Bank Remittance](/docs/user/manual/en/human-resources/human-resources-reports#bank-remittance-report) +1. [BOM Explorer](/docs/user/manual/en/stock/articles/bom_explorer) +1. [Billing Summary Report](/docs/user/manual/en/projects/reports/billing_summary_reports) +1. [Procurement Tracker Report](docs/user/manual/en/buying/articles/procurement-tracker-report) +1. [Loan Repayment](/docs/user/manual/en/human-resources/human-resources-reports#loan-repayment-report) +1. [GSTR-3B](/docs/user/manual/en/regional/india/gst-3b-report) +1. [Sales Partner](/docs/user/manual/en/selling/sales-partner#sales-partner-reports) +1. [Sales Partner Target Variance based on Item Group](sales-partner-target-variance-based-on-item-group) From 06c7a7e6601914c36092c4cb1230f39701340ef2 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 23 Jul 2019 13:40:40 +0530 Subject: [PATCH 003/124] =?UTF-8?q?fix(website):=20Remove=20references=20t?= =?UTF-8?q?o=20Product=20Settings.products=5Fa=E2=80=A6=20(#18451)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was accidentally added back in https://github.com/frappe/erpnext/commit/34c551d9a54573e5184bb16831e0baa4e7429dc2#diff-f0a387cdb305471e74e523ecc4e646ac --- erpnext/setup/doctype/item_group/item_group.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index 8fbeac8138..cab21162c7 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -69,8 +69,7 @@ class ItemGroup(NestedSet, WebsiteGenerator): "items": get_product_list_for_group(product_group = self.name, start=start, limit=context.page_length + 1, search=frappe.form_dict.get("search")), "parents": get_parent_item_groups(self.parent_item_group), - "title": self.name, - "products_as_list": cint(frappe.db.get_single_value('Products Settings', 'products_as_list')) + "title": self.name }) if self.slideshow: From 05425d414cb20a9b6b52bb4d0708edd81fa5eb14 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 23 Jul 2019 16:58:13 +0530 Subject: [PATCH 004/124] fix: change agreement fulfilled to ongoing --- erpnext/support/doctype/issue/issue.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 98d8c99809..58e2076858 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -210,6 +210,7 @@ class Issue(Document): self.service_level_agreement_creation = now_datetime() self.set_response_and_resolution_time(priority=self.priority, service_level_agreement=self.service_level_agreement) + self.agreement_fulfilled = "Ongoing" self.save() def get_expected_time_for(parameter, service_level, start_date_time): From 6d0c6a17d971c944b50b7c928f53f08d0eef05ed Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 23 Jul 2019 23:13:33 +0530 Subject: [PATCH 005/124] fix: multi currency bank reco issue --- .../doctype/bank_transaction/bank_transaction.py | 14 +++++++++++--- .../bank_reconciliation/bank_reconciliation.py | 2 -- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index f943b34581..4e5057048f 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -45,7 +45,7 @@ class BankTransaction(StatusUpdater): def clear_linked_payment_entries(self): for payment_entry in self.payment_entries: allocated_amount = get_total_allocated_amount(payment_entry) - paid_amount = get_paid_amount(payment_entry) + paid_amount = get_paid_amount(payment_entry, self.currency) if paid_amount and allocated_amount: if flt(allocated_amount[0]["allocated_amount"]) > flt(paid_amount): @@ -80,9 +80,17 @@ def get_total_allocated_amount(payment_entry): AND bt.docstatus = 1""", (payment_entry.payment_document, payment_entry.payment_entry), as_dict=True) -def get_paid_amount(payment_entry): +def get_paid_amount(payment_entry, currency): if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]: - return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "paid_amount") + + paid_amount_field = "paid_amount" + if payment_entry.payment_document == 'Payment Entry': + doc = frappe.get_doc("Payment Entry", payment_entry.payment_entry) + paid_amount_field = ("base_paid_amount" + if doc.paid_to_account_currency == currency else "paid_amount") + + return frappe.db.get_value(payment_entry.payment_document, + payment_entry.payment_entry, paid_amount_field) elif payment_entry.payment_document == "Journal Entry": return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_credit") diff --git a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py index 36c939996f..bd4b4d7e0b 100644 --- a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py +++ b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py @@ -124,8 +124,6 @@ def check_matching_amount(bank_account, company, transaction): 'txt': '%%%s%%' % amount }, as_dict=True) - frappe.errprint(journal_entries) - if transaction.credit > 0: sales_invoices = frappe.db.sql(""" SELECT From 4865eabee5152d43f4b827d1ec03a2cf050b4705 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Wed, 24 Jul 2019 13:37:54 +0530 Subject: [PATCH 006/124] fix: add Company by default in session defaults (#18460) --- erpnext/setup/install.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py index 03da833dec..5e85f7d526 100644 --- a/erpnext/setup/install.py +++ b/erpnext/setup/install.py @@ -22,6 +22,7 @@ def after_install(): add_all_roles_to("Administrator") create_default_cash_flow_mapper_templates() create_default_success_action() + add_company_to_session_defaults() frappe.db.commit() @@ -84,3 +85,10 @@ def create_default_success_action(): if not frappe.db.exists('Success Action', success_action.get("ref_doctype")): doc = frappe.get_doc(success_action) doc.insert(ignore_permissions=True) + +def add_company_to_session_defaults(): + settings = frappe.get_single("Session Default Settings") + settings.append("session_defaults", { + "ref_doctype": "Company" + }) + settings.save() From cb19ee457c8a1644642ad81b34ef6e7390687115 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 24 Jul 2019 16:05:59 +0530 Subject: [PATCH 007/124] fix: urls for changelog --- erpnext/change_log/v12/v12_0_0.md | 50 +++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/erpnext/change_log/v12/v12_0_0.md b/erpnext/change_log/v12/v12_0_0.md index dcbc9a00dd..198e3d77d6 100644 --- a/erpnext/change_log/v12/v12_0_0.md +++ b/erpnext/change_log/v12/v12_0_0.md @@ -1,41 +1,41 @@ # Version 12 Release Notes ### Accounting -1. [Accounting Dimensions](/docs/user/manual/en/accounts/accounting-dimensions) -1. [Chart of Accounts Importer](/docs/user/manual/en/setting-up/chart-of-accounts-importer) -1. [Invoice Discounting](/docs/user/manual/en/accounts/invoice_discounting) +1. [Accounting Dimensions](https://erpnext.com/docs/user/manual/en/accounts/accounting-dimensions) +1. [Chart of Accounts Importer](https://erpnext.com/docs/user/manual/en/setting-up/chart-of-accounts-importer) +1. [Invoice Discounting](https://erpnext.com/docs/user/manual/en/accounts/invoice_discounting) 1. [Tally Migrator](https://github.com/frappe/erpnext/pull/17405) ### Stock -1. [Serialized & Batched Item Reconciliation](/docs/user/manual/en/setting-up/stock-reconciliation#12-for-serialized-items) +1. [Serialized & Batched Item Reconciliation](https://erpnext.com/docs/user/manual/en/setting-up/stock-reconciliation#12-for-serialized-items) 1. [Auto Fetch Serialized Items](/version-12/release-notes/features#new-upload-dialog) -1. [Item Tax Templates](/docs/user/manual/en/accounts/item-tax-template) +1. [Item Tax Templates](https://erpnext.com/docs/user/manual/en/accounts/item-tax-template) ### HR -1. [Auto Attendance](/docs/user/manual/en/human-resources/auto-attendance) -1. [Employee Skill Map](/docs/user/manual/en/human-resources/employee_skill_map) -1. [Encrypted Salary Slips](/docs/user/manual/en/human-resources/hr-settings#24-encrypt-salary-slips-in-emails) -1. [Leave Ledger](/docs/user/manual/en/human-resources/leave-ledger-entry) -1. [Staffing Plan](/docs/user/manual/en/human-resources/staffing-plan) +1. [Auto Attendance](https://erpnext.com/docs/user/manual/en/human-resources/auto-attendance) +1. [Employee Skill Map](https://erpnext.com/docs/user/manual/en/human-resources/employee_skill_map) +1. [Encrypted Salary Slips](https://erpnext.com/docs/user/manual/en/human-resources/hr-settings#24-encrypt-salary-slips-in-emails) +1. [Leave Ledger](https://erpnext.com/docs/user/manual/en/human-resources/leave-ledger-entry) +1. [Staffing Plan](https://erpnext.com/docs/user/manual/en/human-resources/staffing-plan) ### CRM -1. [Promotional Scheme](/docs/user/manual/en/accounts/promotional-schemes) -1. [SLA](/docs/user/manual/en/support/service-level-agreement) -1. [Exotel Call Integration](/docs/user/manual/en/erpnext_integration/exotel_integration) -1. [Email Campaign](/docs/user/manual/en/CRM/email-campaign) +1. [Promotional Scheme](https://erpnext.com/docs/user/manual/en/accounts/promotional-schemes) +1. [SLA](https://erpnext.com/docs/user/manual/en/support/service-level-agreement) +1. [Exotel Call Integration](https://erpnext.com/docs/user/manual/en/erpnext_integration/exotel_integration) +1. [Email Campaign](https://erpnext.com/docs/user/manual/en/CRM/email-campaign) ### Domain Specific Features -1. [Learning Management System](/docs/user/manual/en/education/setting-up-lms) -1. [Quality Management System](/docs/user/manual/en/quality-management) -1. [Production Planning Enhancements](/docs/user/manual/en/manufacturing/production-plan/planning-for-material-requests) -1. [Project Template](/docs/user/manual/en/projects/project-template) +1. [Learning Management System](https://erpnext.com/docs/user/manual/en/education/setting-up-lms) +1. [Quality Management System](https://erpnext.com/docs/user/manual/en/quality-management) +1. [Production Planning Enhancements](https://erpnext.com/docs/user/manual/en/manufacturing/production-plan/planning-for-material-requests) +1. [Project Template](https://erpnext.com/docs/user/manual/en/projects/project-template) ### New Reports -1. [Bank Remittance](/docs/user/manual/en/human-resources/human-resources-reports#bank-remittance-report) -1. [BOM Explorer](/docs/user/manual/en/stock/articles/bom_explorer) -1. [Billing Summary Report](/docs/user/manual/en/projects/reports/billing_summary_reports) +1. [Bank Remittance](https://erpnext.com/docs/user/manual/en/human-resources/human-resources-reports#bank-remittance-report) +1. [BOM Explorer](https://erpnext.com/docs/user/manual/en/stock/articles/bom_explorer) +1. [Billing Summary Report](https://erpnext.com/docs/user/manual/en/projects/reports/billing_summary_reports) 1. [Procurement Tracker Report](docs/user/manual/en/buying/articles/procurement-tracker-report) -1. [Loan Repayment](/docs/user/manual/en/human-resources/human-resources-reports#loan-repayment-report) -1. [GSTR-3B](/docs/user/manual/en/regional/india/gst-3b-report) -1. [Sales Partner](/docs/user/manual/en/selling/sales-partner#sales-partner-reports) -1. [Sales Partner Target Variance based on Item Group](sales-partner-target-variance-based-on-item-group) +1. [Loan Repayment](https://erpnext.com/docs/user/manual/en/human-resources/human-resources-reports#loan-repayment-report) +1. [GSTR-3B](https://erpnext.com/docs/user/manual/en/regional/india/gst-3b-report) +1. [Sales Partner](https://erpnext.com/docs/user/manual/en/selling/sales-partner#sales-partner-reports) +1. [Sales Partner Target Variance based on Item Group](https://erpnext.com/docs/user/manual/en/selling/sales-partner#sales-partner-target-variance-based-on-item-group) From 8b08684e07a571182108d7c332118a1bfc330bf4 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 24 Jul 2019 16:10:34 +0530 Subject: [PATCH 008/124] fix: more url fixes --- erpnext/change_log/v12/v12_0_0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/change_log/v12/v12_0_0.md b/erpnext/change_log/v12/v12_0_0.md index 198e3d77d6..c2f33a8b7a 100644 --- a/erpnext/change_log/v12/v12_0_0.md +++ b/erpnext/change_log/v12/v12_0_0.md @@ -8,7 +8,7 @@ ### Stock 1. [Serialized & Batched Item Reconciliation](https://erpnext.com/docs/user/manual/en/setting-up/stock-reconciliation#12-for-serialized-items) -1. [Auto Fetch Serialized Items](/version-12/release-notes/features#new-upload-dialog) +1. [Auto Fetch Serialized Items](https://erpnext.com/version-12/release-notes/features#new-upload-dialog) 1. [Item Tax Templates](https://erpnext.com/docs/user/manual/en/accounts/item-tax-template) ### HR From 192db7d6233482434b7b55b05ba94596158308de Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 24 Jul 2019 16:22:37 +0530 Subject: [PATCH 009/124] fix: url fixes for changelog --- erpnext/change_log/v12/v12_0_0.md | 52 +++++++++++++++---------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/erpnext/change_log/v12/v12_0_0.md b/erpnext/change_log/v12/v12_0_0.md index dcbc9a00dd..c2f33a8b7a 100644 --- a/erpnext/change_log/v12/v12_0_0.md +++ b/erpnext/change_log/v12/v12_0_0.md @@ -1,41 +1,41 @@ # Version 12 Release Notes ### Accounting -1. [Accounting Dimensions](/docs/user/manual/en/accounts/accounting-dimensions) -1. [Chart of Accounts Importer](/docs/user/manual/en/setting-up/chart-of-accounts-importer) -1. [Invoice Discounting](/docs/user/manual/en/accounts/invoice_discounting) +1. [Accounting Dimensions](https://erpnext.com/docs/user/manual/en/accounts/accounting-dimensions) +1. [Chart of Accounts Importer](https://erpnext.com/docs/user/manual/en/setting-up/chart-of-accounts-importer) +1. [Invoice Discounting](https://erpnext.com/docs/user/manual/en/accounts/invoice_discounting) 1. [Tally Migrator](https://github.com/frappe/erpnext/pull/17405) ### Stock -1. [Serialized & Batched Item Reconciliation](/docs/user/manual/en/setting-up/stock-reconciliation#12-for-serialized-items) -1. [Auto Fetch Serialized Items](/version-12/release-notes/features#new-upload-dialog) -1. [Item Tax Templates](/docs/user/manual/en/accounts/item-tax-template) +1. [Serialized & Batched Item Reconciliation](https://erpnext.com/docs/user/manual/en/setting-up/stock-reconciliation#12-for-serialized-items) +1. [Auto Fetch Serialized Items](https://erpnext.com/version-12/release-notes/features#new-upload-dialog) +1. [Item Tax Templates](https://erpnext.com/docs/user/manual/en/accounts/item-tax-template) ### HR -1. [Auto Attendance](/docs/user/manual/en/human-resources/auto-attendance) -1. [Employee Skill Map](/docs/user/manual/en/human-resources/employee_skill_map) -1. [Encrypted Salary Slips](/docs/user/manual/en/human-resources/hr-settings#24-encrypt-salary-slips-in-emails) -1. [Leave Ledger](/docs/user/manual/en/human-resources/leave-ledger-entry) -1. [Staffing Plan](/docs/user/manual/en/human-resources/staffing-plan) +1. [Auto Attendance](https://erpnext.com/docs/user/manual/en/human-resources/auto-attendance) +1. [Employee Skill Map](https://erpnext.com/docs/user/manual/en/human-resources/employee_skill_map) +1. [Encrypted Salary Slips](https://erpnext.com/docs/user/manual/en/human-resources/hr-settings#24-encrypt-salary-slips-in-emails) +1. [Leave Ledger](https://erpnext.com/docs/user/manual/en/human-resources/leave-ledger-entry) +1. [Staffing Plan](https://erpnext.com/docs/user/manual/en/human-resources/staffing-plan) ### CRM -1. [Promotional Scheme](/docs/user/manual/en/accounts/promotional-schemes) -1. [SLA](/docs/user/manual/en/support/service-level-agreement) -1. [Exotel Call Integration](/docs/user/manual/en/erpnext_integration/exotel_integration) -1. [Email Campaign](/docs/user/manual/en/CRM/email-campaign) +1. [Promotional Scheme](https://erpnext.com/docs/user/manual/en/accounts/promotional-schemes) +1. [SLA](https://erpnext.com/docs/user/manual/en/support/service-level-agreement) +1. [Exotel Call Integration](https://erpnext.com/docs/user/manual/en/erpnext_integration/exotel_integration) +1. [Email Campaign](https://erpnext.com/docs/user/manual/en/CRM/email-campaign) ### Domain Specific Features -1. [Learning Management System](/docs/user/manual/en/education/setting-up-lms) -1. [Quality Management System](/docs/user/manual/en/quality-management) -1. [Production Planning Enhancements](/docs/user/manual/en/manufacturing/production-plan/planning-for-material-requests) -1. [Project Template](/docs/user/manual/en/projects/project-template) +1. [Learning Management System](https://erpnext.com/docs/user/manual/en/education/setting-up-lms) +1. [Quality Management System](https://erpnext.com/docs/user/manual/en/quality-management) +1. [Production Planning Enhancements](https://erpnext.com/docs/user/manual/en/manufacturing/production-plan/planning-for-material-requests) +1. [Project Template](https://erpnext.com/docs/user/manual/en/projects/project-template) ### New Reports -1. [Bank Remittance](/docs/user/manual/en/human-resources/human-resources-reports#bank-remittance-report) -1. [BOM Explorer](/docs/user/manual/en/stock/articles/bom_explorer) -1. [Billing Summary Report](/docs/user/manual/en/projects/reports/billing_summary_reports) +1. [Bank Remittance](https://erpnext.com/docs/user/manual/en/human-resources/human-resources-reports#bank-remittance-report) +1. [BOM Explorer](https://erpnext.com/docs/user/manual/en/stock/articles/bom_explorer) +1. [Billing Summary Report](https://erpnext.com/docs/user/manual/en/projects/reports/billing_summary_reports) 1. [Procurement Tracker Report](docs/user/manual/en/buying/articles/procurement-tracker-report) -1. [Loan Repayment](/docs/user/manual/en/human-resources/human-resources-reports#loan-repayment-report) -1. [GSTR-3B](/docs/user/manual/en/regional/india/gst-3b-report) -1. [Sales Partner](/docs/user/manual/en/selling/sales-partner#sales-partner-reports) -1. [Sales Partner Target Variance based on Item Group](sales-partner-target-variance-based-on-item-group) +1. [Loan Repayment](https://erpnext.com/docs/user/manual/en/human-resources/human-resources-reports#loan-repayment-report) +1. [GSTR-3B](https://erpnext.com/docs/user/manual/en/regional/india/gst-3b-report) +1. [Sales Partner](https://erpnext.com/docs/user/manual/en/selling/sales-partner#sales-partner-reports) +1. [Sales Partner Target Variance based on Item Group](https://erpnext.com/docs/user/manual/en/selling/sales-partner#sales-partner-target-variance-based-on-item-group) From 89339bb80c3ff90b6bf273f1a55a183071c9e4f1 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Wed, 24 Jul 2019 21:32:55 +0530 Subject: [PATCH 010/124] fix: GSTR-1 query fix --- erpnext/regional/report/gstr_1/gstr_1.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index e8c170e721..2da1085732 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -161,8 +161,9 @@ class Gstr1Report(object): "gst_category": ["in", ["Registered Regular", "Deemed Export", "SEZ"]] }) - conditions += """ and ifnull(gst_category, '') != 'Overseas' and is_return != 1 - and customer in ({0})""".format(", ".join([frappe.db.escape(c.name) for c in customers])) + if customers: + conditions += """ and ifnull(gst_category, '') != 'Overseas' and is_return != 1 + and customer in ({0})""".format(", ".join([frappe.db.escape(c.name) for c in customers])) if self.filters.get("type_of_business") in ("B2C Large", "B2C Small"): b2c_limit = frappe.db.get_single_value('GST Settings', 'b2c_limit') @@ -174,11 +175,11 @@ class Gstr1Report(object): "gst_category": ["in", ["Unregistered"]] }) - if self.filters.get("type_of_business") == "B2C Large": + if self.filters.get("type_of_business") == "B2C Large" and customers: conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2) and grand_total > {0} and is_return != 1 and customer in ({1})""".\ format(flt(b2c_limit), ", ".join([frappe.db.escape(c.name) for c in customers])) - elif self.filters.get("type_of_business") == "B2C Small": + elif self.filters.get("type_of_business") == "B2C Small" and customers: conditions += """ and ( SUBSTR(place_of_supply, 1, 2) = SUBSTR(company_gstin, 1, 2) or grand_total <= {0}) and is_return != 1 and customer in ({1})""".\ From 53dc0c52cacf2a53a71cad845b16f28a7776ab91 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 25 Jul 2019 12:23:40 +0530 Subject: [PATCH 011/124] Dynamic link issue fix in Bank reconciliation statement --- .../bank_reconciliation_statement.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py index 1923f78cf8..63317c52d8 100644 --- a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py +++ b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py @@ -58,8 +58,7 @@ def get_columns(): { "fieldname": "payment_document", "label": _("Payment Document Type"), - "fieldtype": "Link", - "options": "DocType", + "fieldtype": "Data", "width": 220 }, { From 029de1a244ccad4ad2dc4c51f7815bd6f5361fd8 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 24 Jul 2019 15:18:52 +0530 Subject: [PATCH 012/124] fix(travis): Remove unnecessary commands --- .travis.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index a8a0d82614..ace0bfb243 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,12 +14,6 @@ services: install: # fix mongodb travis error - - sudo rm /etc/apt/sources.list.d/mongodb*.list - - pip install flake8==3.3.0 - - flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics - - sudo rm /etc/apt/sources.list.d/docker.list - - sudo apt-get install hhvm && rm -rf /home/travis/.kiex/ - - sudo apt-get purge -y mysql-common mysql-server mysql-client - nvm install 10 - pip install python-coveralls - wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py From e0e78fb0e2407e1fcdf16962c6399705acb70a45 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 13:42:43 +0530 Subject: [PATCH 013/124] fix(travis): Restructure build matrix --- .travis.yml | 36 +++++++++++++++++++++++++----------- travis/run-tests.sh | 12 ------------ 2 files changed, 25 insertions(+), 23 deletions(-) delete mode 100755 travis/run-tests.sh diff --git a/.travis.yml b/.travis.yml index ace0bfb243..0660779b2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,34 @@ -language: python dist: trusty -python: - - "2.7" - - "3.6" - -env: - - TEST_TYPE="Server Side Test" - - TEST_TYPE="Patch Test" +language: python services: - mysql +jobs: + include: + - name: "Python 2.7 Server Side Test" + python: 2.7 + script: bench run-tests --app erpnext --coverage + + - name: "Python 3.6 Server Side Test" + python: 3.6 + script: bench run-tests --app erpnext --coverage + + - name: "Python 2.7 Patch Test" + python: 2.7 + before_script: + - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz + - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis + script: bench migrate + + - name: "Python 3.6 Patch Test" + python: 3.6 + before_script: + - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz + - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis + script: bench migrate + install: # fix mongodb travis error - nvm install 10 @@ -38,8 +55,5 @@ before_script: - bench start & - sleep 10 -script: - - bash $TRAVIS_BUILD_DIR/travis/run-tests.sh - after_script: - coveralls -b apps/erpnext -d ../../sites/.coverage diff --git a/travis/run-tests.sh b/travis/run-tests.sh deleted file mode 100755 index 7cfd64833b..0000000000 --- a/travis/run-tests.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -set -e - -if [[ $TEST_TYPE == 'Server Side Test' ]]; then - bench run-tests --app erpnext --coverage - -elif [[ $TEST_TYPE == 'Patch Test' ]]; then - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis - bench migrate -fi From 9b24a4201798d09ee5c79ecb4054c24bb2d989c0 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:09:34 +0530 Subject: [PATCH 014/124] fix(travis): Use MariaDB 10.3 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0660779b2d..1561d6ca0f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,8 @@ dist: trusty language: python -services: - - mysql +addons: + mariadb: 10.3 jobs: include: From 2fb9e8a94d749e38358b80dce70b8feef91fa16b Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:10:06 +0530 Subject: [PATCH 015/124] fix(travis): Install coverall after tests --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1561d6ca0f..c51c6b078e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,9 +30,7 @@ jobs: script: bench migrate install: - # fix mongodb travis error - nvm install 10 - - pip install python-coveralls - wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py - sudo python install.py --develop --user travis --without-bench-setup - sudo pip install -e ~/bench @@ -56,4 +54,5 @@ before_script: - sleep 10 after_script: + - pip install python-coveralls - coveralls -b apps/erpnext -d ../../sites/.coverage From 3f6ac2d993939043685331bb315f26141dac9fde Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:11:18 +0530 Subject: [PATCH 016/124] fix(travis): Do not execute install.py --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index c51c6b078e..047a98640f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,10 +30,11 @@ jobs: script: bench migrate install: + - cd ~ - nvm install 10 - - wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py - - sudo python install.py --develop --user travis --without-bench-setup - - sudo pip install -e ~/bench + + - git clone https://github.com/frappe/bench --depth 1 + - pip install -e ./bench - rm $TRAVIS_BUILD_DIR/.git/shallow - bash $TRAVIS_BUILD_DIR/travis/bench_init.sh From 23f24d13dd1c37ecbcccff7f8e4a66841324bfd8 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:15:30 +0530 Subject: [PATCH 017/124] fix(travis): Remove travis/bench_init.sh --- .travis.yml | 5 +++-- travis/bench_init.sh | 8 -------- 2 files changed, 3 insertions(+), 10 deletions(-) delete mode 100755 travis/bench_init.sh diff --git a/.travis.yml b/.travis.yml index 047a98640f..e0a2ead3d5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,8 +36,9 @@ install: - git clone https://github.com/frappe/bench --depth 1 - pip install -e ./bench - - rm $TRAVIS_BUILD_DIR/.git/shallow - - bash $TRAVIS_BUILD_DIR/travis/bench_init.sh + - git clone https://github.com/frappe/frappe --branch $TRAVIS_BRANCH --depth 1 + - bench init --frappe-path ~/frappe --python $(which python) frappe-bench + - cp -r $TRAVIS_BUILD_DIR/test_sites/test_site ~/frappe-bench/sites/ before_script: diff --git a/travis/bench_init.sh b/travis/bench_init.sh deleted file mode 100755 index f96269b919..0000000000 --- a/travis/bench_init.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -cd ~/ -curl -I https://github.com/frappe/frappe/tree/$TRAVIS_BRANCH | head -n 1 | cut -d $' ' -f2 | ( - read response; - [ $response == '200' ] && branch=$TRAVIS_BRANCH || branch='develop'; - bench init frappe-bench --frappe-path https://github.com/frappe/frappe.git --frappe-branch $branch --python $(which python) -) From e2b16e3edbebaae0746d83077eb32c226b6f9f29 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:18:05 +0530 Subject: [PATCH 018/124] fix(travis): Remove unused files --- .travis.yml | 3 ++- {test_sites/test_site => .travis}/site_config.json | 3 +-- test_sites/apps.txt | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) rename {test_sites/test_site => .travis}/site_config.json (81%) delete mode 100644 test_sites/apps.txt diff --git a/.travis.yml b/.travis.yml index e0a2ead3d5..108df91e40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,8 @@ install: - git clone https://github.com/frappe/frappe --branch $TRAVIS_BRANCH --depth 1 - bench init --frappe-path ~/frappe --python $(which python) frappe-bench - - cp -r $TRAVIS_BUILD_DIR/test_sites/test_site ~/frappe-bench/sites/ + - mkdir ~/frappe-bench/sites/test_site + - cp -r $TRAVIS_BUILD_DIR/.travis/site_config.json ~/frappe-bench/sites/test_site/ before_script: - mysql -u root -ptravis -e 'create database test_frappe' diff --git a/test_sites/test_site/site_config.json b/.travis/site_config.json similarity index 81% rename from test_sites/test_site/site_config.json rename to .travis/site_config.json index 7a4d106508..695f6c3517 100644 --- a/test_sites/test_site/site_config.json +++ b/.travis/site_config.json @@ -6,8 +6,7 @@ "mail_login": "test@example.com", "mail_password": "test", "admin_password": "admin", - "run_selenium_tests": 1, "root_password": "travis", - "host_name": "http://localhost:8000", + "host_name": "http://test_site:8000", "install_apps": ["erpnext"] } \ No newline at end of file diff --git a/test_sites/apps.txt b/test_sites/apps.txt deleted file mode 100644 index ee6454915c..0000000000 --- a/test_sites/apps.txt +++ /dev/null @@ -1 +0,0 @@ -erpnext \ No newline at end of file From 185e2a2fd8926e96e0311cbaff0c95acb57f50d7 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:19:30 +0530 Subject: [PATCH 019/124] fix(travis): Setup MariaDB --- .travis.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 108df91e40..5ecede08e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,9 +43,15 @@ install: - cp -r $TRAVIS_BUILD_DIR/.travis/site_config.json ~/frappe-bench/sites/test_site/ before_script: - - mysql -u root -ptravis -e 'create database test_frappe' - - echo "USE mysql;\nCREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe';\nFLUSH PRIVILEGES;\n" | mysql -u root -ptravis - - echo "USE mysql;\nGRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost';\n" | mysql -u root -ptravis + - mysql -u root -e "SET GLOBAL character_set_server = 'utf8mb4'" + - mysql -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'" + + - mysql -u root -e "CREATE DATABASE test_frappe" + - mysql -u root -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'" + - mysql -u root -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'" + + - mysql -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'" + - mysql -u root -e "FLUSH PRIVILEGES" - cd ~/frappe-bench - bench get-app erpnext $TRAVIS_BUILD_DIR From fb2ec7186da073c79954e4723479258d547e0253 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:21:19 +0530 Subject: [PATCH 020/124] fix(travis): Do not use use_site --- .travis.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5ecede08e8..9840ad5e15 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,31 +3,32 @@ dist: trusty language: python addons: + hosts: test_site mariadb: 10.3 jobs: include: - name: "Python 2.7 Server Side Test" python: 2.7 - script: bench run-tests --app erpnext --coverage + script: bench --site test_site run-tests --app erpnext --coverage - name: "Python 3.6 Server Side Test" python: 3.6 - script: bench run-tests --app erpnext --coverage + script: bench --site test_site run-tests --app erpnext --coverage - name: "Python 2.7 Patch Test" python: 2.7 before_script: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis - script: bench migrate + script: bench --site test_site migrate - name: "Python 3.6 Patch Test" python: 3.6 before_script: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis - script: bench migrate + - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis + script: bench --site test_site migrate install: - cd ~ @@ -55,9 +56,8 @@ before_script: - cd ~/frappe-bench - bench get-app erpnext $TRAVIS_BUILD_DIR - - bench use test_site - - bench reinstall --mariadb-root-username root --mariadb-root-password travis --yes - - bench scheduler disable + - bench --site test_site reinstall --mariadb-root-username root --mariadb-root-password travis --yes + - bench --site test_site scheduler disable - sed -i 's/9000/9001/g' sites/common_site_config.json - bench start & - sleep 10 From 1e9e471714c04b06cab77353132cfa377dc0eff0 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:21:54 +0530 Subject: [PATCH 021/124] fix(travis): Do not disable scheduler using CLI --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9840ad5e15..cd593a8aed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,6 @@ before_script: - cd ~/frappe-bench - bench get-app erpnext $TRAVIS_BUILD_DIR - bench --site test_site reinstall --mariadb-root-username root --mariadb-root-password travis --yes - - bench --site test_site scheduler disable - sed -i 's/9000/9001/g' sites/common_site_config.json - bench start & - sleep 10 From 903e87899b6e94bef3cba133271a0a249d8bbc81 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:23:24 +0530 Subject: [PATCH 022/124] fix(travis): Execute get-app and reinstall after bench start --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index cd593a8aed..d3581e2b8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,11 +55,11 @@ before_script: - mysql -u root -e "FLUSH PRIVILEGES" - cd ~/frappe-bench - - bench get-app erpnext $TRAVIS_BUILD_DIR - - bench --site test_site reinstall --mariadb-root-username root --mariadb-root-password travis --yes - sed -i 's/9000/9001/g' sites/common_site_config.json - bench start & - sleep 10 + - bench get-app erpnext $TRAVIS_BUILD_DIR + - bench --site test_site reinstall --mariadb-root-username root --mariadb-root-password travis --yes after_script: - pip install python-coveralls From e4f78a0b6a208de4583bc81281dd9595ed17d8cd Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:23:43 +0530 Subject: [PATCH 023/124] perf(travis): Do not waste 10 seconds --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d3581e2b8d..23627f51f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,6 @@ before_script: - cd ~/frappe-bench - sed -i 's/9000/9001/g' sites/common_site_config.json - bench start & - - sleep 10 - bench get-app erpnext $TRAVIS_BUILD_DIR - bench --site test_site reinstall --mariadb-root-username root --mariadb-root-password travis --yes From 7c44adad3eb7c58f2011f5fbeffc11a1c046ffbd Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:25:53 +0530 Subject: [PATCH 024/124] fix(travis): Use MariaDB credentials from site_config.json --- .travis.yml | 2 +- .travis/site_config.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 23627f51f0..54d77db7c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,7 +58,7 @@ before_script: - sed -i 's/9000/9001/g' sites/common_site_config.json - bench start & - bench get-app erpnext $TRAVIS_BUILD_DIR - - bench --site test_site reinstall --mariadb-root-username root --mariadb-root-password travis --yes + - bench --site test_site reinstall --yes after_script: - pip install python-coveralls diff --git a/.travis/site_config.json b/.travis/site_config.json index 695f6c3517..dae80095d4 100644 --- a/.travis/site_config.json +++ b/.travis/site_config.json @@ -6,6 +6,7 @@ "mail_login": "test@example.com", "mail_password": "test", "admin_password": "admin", + "root_login": "root", "root_password": "travis", "host_name": "http://test_site:8000", "install_apps": ["erpnext"] From 30628b016b8b7226c38abc17332e47a885e19b5e Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:27:20 +0530 Subject: [PATCH 025/124] perf(travis): Remove unnecessary processes from Procfile --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 54d77db7c6..2637d978e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,12 @@ before_script: - mysql -u root -e "FLUSH PRIVILEGES" - cd ~/frappe-bench - - sed -i 's/9000/9001/g' sites/common_site_config.json + + - sed -i 's/watch:/# watch:/g' Procfile + - sed -i 's/schedule:/# schedule:/g' Procfile + - sed -i 's/socketio:/# socketio:/g' Procfile + - sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile + - bench start & - bench get-app erpnext $TRAVIS_BUILD_DIR - bench --site test_site reinstall --yes From e31284189f3caa769f94ffea11aaf340ac1ee37e Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:28:15 +0530 Subject: [PATCH 026/124] perf(travis): Do not build assets --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2637d978e4..e3d432a5ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,7 +38,7 @@ install: - pip install -e ./bench - git clone https://github.com/frappe/frappe --branch $TRAVIS_BRANCH --depth 1 - - bench init --frappe-path ~/frappe --python $(which python) frappe-bench + - bench init --skip-assets --frappe-path ~/frappe --python $(which python) frappe-bench - mkdir ~/frappe-bench/sites/test_site - cp -r $TRAVIS_BUILD_DIR/.travis/site_config.json ~/frappe-bench/sites/test_site/ From 50e2d4aa6a73d4fd5025d2b737631b8d39cd87f2 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:36:22 +0530 Subject: [PATCH 027/124] perf(travis): Use travis optimizations --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index e3d432a5ae..ee385d0e08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,12 @@ dist: trusty language: python +git: + depth: 1 + +cache: + - pip + addons: hosts: test_site mariadb: 10.3 From 6076443b6be47261a1fe784dd34871601afa7b08 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:38:07 +0530 Subject: [PATCH 028/124] fix(travis): Execute get-app before bench start --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ee385d0e08..2f7637372e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -67,8 +67,8 @@ before_script: - sed -i 's/socketio:/# socketio:/g' Procfile - sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile - - bench start & - bench get-app erpnext $TRAVIS_BUILD_DIR + - bench start & - bench --site test_site reinstall --yes after_script: From 7b39aa7f91462b6076ca3c89fd0280af10f9b53d Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:39:30 +0530 Subject: [PATCH 029/124] fix(travis): Merge install and before_script --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2f7637372e..fb941f3ff3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,7 +49,6 @@ install: - mkdir ~/frappe-bench/sites/test_site - cp -r $TRAVIS_BUILD_DIR/.travis/site_config.json ~/frappe-bench/sites/test_site/ -before_script: - mysql -u root -e "SET GLOBAL character_set_server = 'utf8mb4'" - mysql -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'" From ac431c8e333a72b1c8faf9bcbe31c7301557d52a Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:50:46 +0530 Subject: [PATCH 030/124] fix(travis): Use --site parameter --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fb941f3ff3..9b51c85eca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ jobs: python: 2.7 before_script: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis + - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis script: bench --site test_site migrate - name: "Python 3.6 Patch Test" From 0046357b864c53cda22ccc0202c1623a24e2bfa0 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:51:12 +0530 Subject: [PATCH 031/124] fix(travis): Remove redundant arguments --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9b51c85eca..53c67fe15d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,14 +26,14 @@ jobs: python: 2.7 before_script: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis + - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz script: bench --site test_site migrate - name: "Python 3.6 Patch Test" python: 3.6 before_script: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis + - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz script: bench --site test_site migrate install: From b6906c58d1ae6d7c6febdf196e1b098eb5dec8f0 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 22:40:26 +0530 Subject: [PATCH 032/124] fix(travis): Install wkhtmltopdf --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 53c67fe15d..40afeee8d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -59,6 +59,11 @@ install: - mysql -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'" - mysql -u root -e "FLUSH PRIVILEGES" + - wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz + - tar -xf /tmp/wkhtmltox.tar.xz -C /tmp + - sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf + - sudo chmod o+x /usr/local/bin/wkhtmltopdf + - cd ~/frappe-bench - sed -i 's/watch:/# watch:/g' Procfile From 0d333894c930b96878e374b3bb474a5e2d5329f9 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 23:37:43 +0530 Subject: [PATCH 033/124] perf(tests): Use setUpClass and tearDownClass instead of setUp and tearDown --- .../doctype/purchase_invoice/test_purchase_invoice.py | 7 +++++-- .../accounts/doctype/sales_invoice/test_sales_invoice.py | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index b4d584fbde..6deee38148 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -20,11 +20,13 @@ test_dependencies = ["Item", "Cost Center", "Payment Term", "Payment Terms Templ test_ignore = ["Serial No"] class TestPurchaseInvoice(unittest.TestCase): - def setUp(self): + @classmethod + def setUpClass(self): unlink_payment_on_cancel_of_invoice() frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1) - def tearDown(self): + @classmethod + def tearDownClass(self): unlink_payment_on_cancel_of_invoice(0) def test_gl_entries_without_perpetual_inventory(self): @@ -91,6 +93,7 @@ class TestPurchaseInvoice(unittest.TestCase): pi_doc = frappe.get_doc('Purchase Invoice', pi_doc.name) self.assertRaises(frappe.LinkExistsError, pi_doc.cancel) + unlink_payment_on_cancel_of_invoice() def test_purchase_invoice_for_blocked_supplier(self): supplier = frappe.get_doc('Supplier', '_Test Supplier') diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 52470fde95..dff55947df 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -29,10 +29,12 @@ class TestSalesInvoice(unittest.TestCase): w.submit() return w - def setUp(self): + @classmethod + def setUpClass(self): unlink_payment_on_cancel_of_invoice() - def tearDown(self): + @classmethod + def tearDownClass(self): unlink_payment_on_cancel_of_invoice(0) def test_timestamp_change(self): @@ -135,6 +137,7 @@ class TestSalesInvoice(unittest.TestCase): unlink_payment_on_cancel_of_invoice(0) si = frappe.get_doc('Sales Invoice', si.name) self.assertRaises(frappe.LinkExistsError, si.cancel) + unlink_payment_on_cancel_of_invoice() def test_sales_invoice_calculation_export_currency(self): si = frappe.copy_doc(test_records[2]) From 8773d931be206dc702d3b56e3aabc5a5d1ef63f4 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 26 Jul 2019 00:38:51 +0530 Subject: [PATCH 034/124] perf(tests): Do not unnecessarily create companies --- erpnext/tests/test_notifications.py | 44 ++++++++++------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/erpnext/tests/test_notifications.py b/erpnext/tests/test_notifications.py index 596bc80dee..1fd90beef0 100644 --- a/erpnext/tests/test_notifications.py +++ b/erpnext/tests/test_notifications.py @@ -2,45 +2,31 @@ # MIT License. See license.txt from __future__ import unicode_literals +import frappe import unittest from frappe.desk import notifications from frappe.test_runner import make_test_objects class TestNotifications(unittest.TestCase): - def setUp(self): - test_records_company = [ - { - "abbr": "_TC6", - "company_name": "_Test Company 6", - "country": "India", - "default_currency": "INR", - "doctype": "Company", - "domain": "Manufacturing", - "monthly_sales_target": 2000, - "chart_of_accounts": "Standard" - }, - { - "abbr": "_TC7", - "company_name": "_Test Company 7", - "country": "United States", - "default_currency": "USD", - "doctype": "Company", - "domain": "Retail", - "monthly_sales_target": 10000, - "total_monthly_sales": 1000, - "chart_of_accounts": "Standard" - }, - ] - - make_test_objects('Company', test_records=test_records_company, reset=True) - def test_get_notifications_for_targets(self): ''' Test notification config entries for targets as percentages ''' + company = frappe.get_all("Company")[0] + frappe.db.set_value("Company", company.name, "monthly_sales_target", 10000) + frappe.db.set_value("Company", company.name, "total_monthly_sales", 1000) + config = notifications.get_notification_config() doc_target_percents = notifications.get_notifications_for_targets(config, {}) - self.assertEqual(doc_target_percents['Company']['_Test Company 7'], 10) - self.assertEqual(doc_target_percents['Company']['_Test Company 6'], 0) + + self.assertEqual(doc_target_percents['Company'][company.name], 10) + + frappe.db.set_value("Company", company.name, "monthly_sales_target", 2000) + frappe.db.set_value("Company", company.name, "total_monthly_sales", 0) + + config = notifications.get_notification_config() + doc_target_percents = notifications.get_notifications_for_targets(config, {}) + + self.assertEqual(doc_target_percents['Company'][company.name], 0) From d1bb274c22836202bb6aef67ff9a512f4e40e866 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 26 Jul 2019 01:09:01 +0530 Subject: [PATCH 035/124] perf(tests): Use country with lesser fixtures --- .../report/procurement_tracker/test_procurement_tracker.py | 2 +- erpnext/hr/doctype/staffing_plan/test_staffing_plan.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py index 4a13f385bb..bebf0ccec5 100644 --- a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py +++ b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py @@ -30,7 +30,7 @@ class TestProcurementTracker(unittest.TestCase): company_name="_Test Procurement Company", abbr="_TPC", default_currency="INR", - country="India" + country="Pakistan" )).insert() warehouse = create_warehouse("_Test Procurement Warehouse", company="_Test Procurement Company") mr = make_material_request(company="_Test Procurement Company", warehouse=warehouse) diff --git a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py index 4a0ce1800a..9ba6d5e63f 100644 --- a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py +++ b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py @@ -92,5 +92,5 @@ def make_company(): company.abbr = "_TC10" company.parent_company = "_Test Company" company.default_currency = "INR" - company.country = "India" + company.country = "Pakistan" company.insert() \ No newline at end of file From bd69f43322455b7a40fe4a30d1076eeda0420c07 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 26 Jul 2019 03:05:40 +0530 Subject: [PATCH 036/124] fix(stock): Fix travis builds --- .../stock/doctype/stock_reconciliation/stock_reconciliation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index d9e62c7931..98a8c59483 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -327,7 +327,8 @@ class StockReconciliation(StockController): if sl_entries: sl_entries.reverse() - self.make_sl_entries(sl_entries) + allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock") + self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock) # repost future entries for selected item_code, warehouse for entries in existing_entries: From f4314a25b633ca8db9b7ffabd5c957cd09b6a356 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 26 Jul 2019 03:06:23 +0530 Subject: [PATCH 037/124] perf(travis): Use setUpClass instead of setUp --- .../test_stock_reconciliation.py | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index f0c71cf39a..ededc4d8b4 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -17,10 +17,11 @@ from erpnext.stock.utils import get_stock_balance, get_incoming_rate, get_availa from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos class TestStockReconciliation(unittest.TestCase): - def setUp(self): + @classmethod + def setUpClass(self): create_batch_or_serial_no_items() frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) - self.insert_existing_sle() + insert_existing_sle() def test_reco_for_fifo(self): self._test_reco_sle_gle("FIFO") @@ -97,18 +98,6 @@ class TestStockReconciliation(unittest.TestCase): self.assertEqual(["_Test Stock Reco Item", "_Test Warehouse Ledger 1 - _TC", 100], [items[0]["item_code"], items[0]["warehouse"], items[0]["qty"]]) - def insert_existing_sle(self): - from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry - - make_stock_entry(posting_date="2012-12-15", posting_time="02:00", item_code="_Test Item", - target="_Test Warehouse - _TC", qty=10, basic_rate=700) - - make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item", - source="_Test Warehouse - _TC", qty=15) - - make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item", - target="_Test Warehouse - _TC", qty=15, basic_rate=1200) - def test_stock_reco_for_serialized_item(self): set_perpetual_inventory() @@ -218,6 +207,18 @@ class TestStockReconciliation(unittest.TestCase): for d in to_delete_records: frappe.delete_doc("Stock Reconciliation", d) +def insert_existing_sle(): + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry + + make_stock_entry(posting_date="2012-12-15", posting_time="02:00", item_code="_Test Item", + target="_Test Warehouse - _TC", qty=10, basic_rate=700) + + make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item", + source="_Test Warehouse - _TC", qty=15) + + make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item", + target="_Test Warehouse - _TC", qty=15, basic_rate=1200) + def create_batch_or_serial_no_items(): create_warehouse("_Test Warehouse for Stock Reco1", {"is_group": 0, "parent_warehouse": "_Test Warehouse Group - _TC"}) From f2fb461e40d21ded1fe1ee14f293f4494a338f74 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 26 Jul 2019 03:51:45 +0530 Subject: [PATCH 038/124] perf(tests): Remove unnecessary tearDown code --- .../doctype/stock_settings/test_stock_settings.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/erpnext/stock/doctype/stock_settings/test_stock_settings.py b/erpnext/stock/doctype/stock_settings/test_stock_settings.py index 1e83ec2f49..42a78f723d 100644 --- a/erpnext/stock/doctype/stock_settings/test_stock_settings.py +++ b/erpnext/stock/doctype/stock_settings/test_stock_settings.py @@ -8,16 +8,7 @@ import unittest class TestStockSettings(unittest.TestCase): def setUp(self): - settings = frappe.get_single('Stock Settings') - settings.clean_description_html = 0 - settings.save() - - frappe.delete_doc('Item', 'Item for description test') - - def tearDown(self): - settings = frappe.get_single('Stock Settings') - settings.clean_description_html = 1 - settings.save() + frappe.db.set_value("Stock Settings", None, "clean_description_html", 0) def test_settings(self): item = frappe.get_doc(dict( From 6998412990b4574e1b737a6e508491f632764a7a Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Fri, 26 Jul 2019 08:15:45 +0530 Subject: [PATCH 039/124] fix(Account): Pass parent currency to child currency In a scenario where Parent Company Account's Currency is different from it's default currency, the Account Currency of Child would be set from the default currency of Company which might be wrong --- erpnext/accounts/doctype/account/account.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index 68efe37719..0e57b3f198 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -123,7 +123,9 @@ class Account(NestedSet): doc.flags.ignore_root_company_validation = True doc.update({ "company": company, - "account_currency": None, + # parent account's currency should be passed down to child account's curreny + # if it is None, it picks it up from default company currency, which might be unintended + "account_currency": self.account_currency, "parent_account": parent_acc_name_map[company] }) doc.save() From 4d53992b354eebe87b00c250c558eaa163ae2de5 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Wed, 10 Jul 2019 14:49:25 +0530 Subject: [PATCH 040/124] fix: Changed columns to new dict form --- .../stock/report/stock_ageing/stock_ageing.py | 79 +++++++++++++++++-- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 969284598c..f81e1c0b91 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -45,14 +45,83 @@ def get_average_age(fifo_queue, to_date): return (age_qty / total_qty) if total_qty else 0.0 def get_columns(filters): - columns = [_("Item Code") + ":Link/Item:100", _("Item Name") + "::100", _("Description") + "::200", - _("Item Group") + ":Link/Item Group:100", _("Brand") + ":Link/Brand:100"] + columns = [ + { + "label": _("Item Code"), + "fieldname": "item_code", + "fieldtype": "Link", + "options": "Item", + "width": 100 + }, + { + "label": _("Item Name"), + "fieldname": "item_name", + "fieldtype": "Data", + "width": 100 + }, + { + "label": _("Description"), + "fieldname": "description", + "fieldtype": "Data", + "width": 200 + }, + { + "label": _("Item Group"), + "fieldname": "item_group", + "fieldtype": "Link", + "options": "Item Group", + "width": 100 + }, + { + "label": _("Brand"), + "fieldname": "brand", + "fieldtype": "Link", + "options": "Brand", + "width": 100 + }] if filters.get("show_ageing_warehouse_wise"): - columns.extend([_("Warehouse") + ":Link/Warehouse:100"]) + columns +=[{ + "label": _("Warehouse"), + "fieldname": "warehouse", + "fieldtype": "Link", + "options": "Warehouse", + "width": 100 + }] - columns.extend([_("Available Qty") + ":Float:100", _("Average Age") + ":Float:100", - _("Earliest") + ":Int:80", _("Latest") + ":Int:80", _("UOM") + ":Link/UOM:100"]) + columns.extend([ + { + "label": _("Available Qty"), + "fieldname": "qty", + "fieldtype": "Float", + "width": 100 + }, + { + "label": _("Average Age"), + "fieldname": "average_age", + "fieldtype": "Float", + "width": 100 + }, + { + "label": _("Earliest"), + "fieldname": "earliest", + "fieldtype": "Int", + "width": 80 + }, + { + "label": _("Latest"), + "fieldname": "latest", + "fieldtype": "Int", + "width": 80 + }, + { + "label": _("UOM"), + "fieldname": "uom", + "fieldtype": "Link", + "options": "UOM", + "width": 100 + } + ]) return columns From f7733be322533f977f6171fd7b002164d3bf13ef Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 13 Jul 2019 21:58:32 +0530 Subject: [PATCH 041/124] fix: Enhancement in stock ageing report --- .../stock/report/stock_ageing/stock_ageing.js | 4 +- .../stock/report/stock_ageing/stock_ageing.py | 37 ++++++++++++++----- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.js b/erpnext/stock/report/stock_ageing/stock_ageing.js index aad8df426a..ccde61a167 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.js +++ b/erpnext/stock/report/stock_ageing/stock_ageing.js @@ -37,8 +37,8 @@ frappe.query_reports["Stock Ageing"] = { "options": "Brand" }, { - "fieldname":"show_ageing_warehouse_wise", - "label": __("Show Ageing Warehouse-wise"), + "fieldname":"show_warehouse_wise_stock", + "label": __("Show Warehouse-wise Stock"), "fieldtype": "Check", "default": 0 } diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index f81e1c0b91..54498934b3 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -14,7 +14,7 @@ def execute(filters=None): to_date = filters["to_date"] data = [] for item, item_dict in iteritems(item_details): - fifo_queue = item_dict["fifo_queue"] + fifo_queue = sorted(item_dict["fifo_queue"], key=lambda x: x[1]) details = item_dict["details"] if not fifo_queue: continue @@ -25,7 +25,7 @@ def execute(filters=None): row = [details.name, details.item_name, details.description, details.item_group, details.brand] - if filters.get("show_ageing_warehouse_wise"): + if filters.get("show_warehouse_wise_stock"): row.append(details.warehouse) row.extend([item_dict.get("total_qty"), average_age, @@ -80,7 +80,7 @@ def get_columns(filters): "width": 100 }] - if filters.get("show_ageing_warehouse_wise"): + if filters.get("show_warehouse_wise_stock"): columns +=[{ "label": _("Warehouse"), "fieldname": "warehouse", @@ -127,16 +127,34 @@ def get_columns(filters): def get_fifo_queue(filters): item_details = {} - for d in get_stock_ledger_entries(filters): - key = (d.name, d.warehouse) if filters.get('show_ageing_warehouse_wise') else d.name + transfered_item_details = {} + + sle = get_stock_ledger_entries(filters) + + for d in sle: + key = (d.name, d.warehouse) if filters.get('show_warehouse_wise_stock') else d.name item_details.setdefault(key, {"details": d, "fifo_queue": []}) fifo_queue = item_details[key]["fifo_queue"] + transfered_item_details.setdefault((d.voucher_no, d.name), []) + if d.voucher_type == "Stock Reconciliation": d.actual_qty = flt(d.qty_after_transaction) - flt(item_details[key].get("qty_after_transaction", 0)) if d.actual_qty > 0: - fifo_queue.append([d.actual_qty, d.posting_date]) + if filters.get('show_warehouse_wise_stock') and transfered_item_details.get((d.voucher_no, d.name)): + qty_to_add = d.actual_qty + while qty_to_add: + batch = transfered_item_details[(d.voucher_no, d.name)][0] + if 0 < batch[0] <= qty_to_add: + qty_to_add -= batch[0] + fifo_queue.append(batch) + transfered_item_details[((d.voucher_no, d.name))].pop(0) + else: + batch[0] -= qty_to_add + fifo_queue.append([qty_to_add, batch[1]]) + else: + fifo_queue.append([d.actual_qty, d.posting_date]) else: qty_to_pop = abs(d.actual_qty) while qty_to_pop: @@ -145,10 +163,11 @@ def get_fifo_queue(filters): # if batch qty > 0 # not enough or exactly same qty in current batch, clear batch qty_to_pop -= batch[0] - fifo_queue.pop(0) + transfered_item_details[(d.voucher_no, d.name)].append(fifo_queue.pop(0)) else: # all from current batch batch[0] -= qty_to_pop + transfered_item_details[(d.voucher_no, d.name)].append([qty_to_pop, batch[1]]) qty_to_pop = 0 item_details[key]["qty_after_transaction"] = d.qty_after_transaction @@ -163,7 +182,7 @@ def get_fifo_queue(filters): def get_stock_ledger_entries(filters): return frappe.db.sql("""select item.name, item.item_name, item_group, brand, description, item.stock_uom, - actual_qty, posting_date, voucher_type, qty_after_transaction, warehouse + actual_qty, posting_date, voucher_type, voucher_no, qty_after_transaction, warehouse from `tabStock Ledger Entry` sle, (select name, item_name, description, stock_uom, brand, item_group from `tabItem` {item_conditions}) item @@ -171,7 +190,7 @@ def get_stock_ledger_entries(filters): company = %(company)s and posting_date <= %(to_date)s {sle_conditions} - order by posting_date, posting_time, sle.creation"""\ + order by posting_date, posting_time, sle.creation, actual_qty"""\ .format(item_conditions=get_item_conditions(filters), sle_conditions=get_sle_conditions(filters)), filters, as_dict=True) From e3a2ab184e3e168b15d89543987085fa649407ac Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 16 Jul 2019 16:08:50 +0530 Subject: [PATCH 042/124] fix: Consider serial no and batches in Stock ageing report --- .../stock/report/stock_ageing/stock_ageing.py | 69 +++++++++++++------ 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 54498934b3..7529ae6aa7 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -16,8 +16,9 @@ def execute(filters=None): for item, item_dict in iteritems(item_details): fifo_queue = sorted(item_dict["fifo_queue"], key=lambda x: x[1]) details = item_dict["details"] - if not fifo_queue: continue + if not fifo_queue or (not item_dict.get("total_qty")): continue + print(fifo_queue) average_age = get_average_age(fifo_queue, to_date) earliest_age = date_diff(to_date, fifo_queue[0][1]) latest_age = date_diff(to_date, fifo_queue[-1][1]) @@ -39,8 +40,13 @@ def get_average_age(fifo_queue, to_date): batch_age = age_qty = total_qty = 0.0 for batch in fifo_queue: batch_age = date_diff(to_date, batch[1]) - age_qty += batch_age * batch[0] - total_qty += batch[0] + + if type(batch[0]) in ['int', 'float']: + age_qty += batch_age * batch[0] + total_qty += batch[0] + else: + age_qty += batch_age * 1 + total_qty += 1 return (age_qty / total_qty) if total_qty else 0.0 @@ -128,6 +134,7 @@ def get_columns(filters): def get_fifo_queue(filters): item_details = {} transfered_item_details = {} + serial_no_batch_purchase_details = {} sle = get_stock_ledger_entries(filters) @@ -142,7 +149,7 @@ def get_fifo_queue(filters): d.actual_qty = flt(d.qty_after_transaction) - flt(item_details[key].get("qty_after_transaction", 0)) if d.actual_qty > 0: - if filters.get('show_warehouse_wise_stock') and transfered_item_details.get((d.voucher_no, d.name)): + if transfered_item_details.get((d.voucher_no, d.name)): qty_to_add = d.actual_qty while qty_to_add: batch = transfered_item_details[(d.voucher_no, d.name)][0] @@ -154,21 +161,43 @@ def get_fifo_queue(filters): batch[0] -= qty_to_add fifo_queue.append([qty_to_add, batch[1]]) else: - fifo_queue.append([d.actual_qty, d.posting_date]) - else: - qty_to_pop = abs(d.actual_qty) - while qty_to_pop: - batch = fifo_queue[0] if fifo_queue else [0, None] - if 0 < batch[0] <= qty_to_pop: - # if batch qty > 0 - # not enough or exactly same qty in current batch, clear batch - qty_to_pop -= batch[0] - transfered_item_details[(d.voucher_no, d.name)].append(fifo_queue.pop(0)) + if d.serial_no or d.batch_no: + if d.serial_no: + for no in d.serial_no.split("\n"): + if serial_no_batch_purchase_details.get(no): + fifo_queue.append([no, serial_no_batch_purchase_details.get(no)]) + else: + serial_no_batch_purchase_details.setdefault(no, d.posting_date) + fifo_queue.append([no, d.posting_date]) + else: + if serial_no_batch_purchase_details.get(d.batch_no): + fifo_queue.append([d.batch_no, serial_no_batch_purchase_details.get(d.batch_no)]) + else: + serial_no_batch_purchase_details.setdefault(d.batch_no, d.posting_date) + fifo_queue.append([d.batch_no, d.posting_date]) + else: - # all from current batch - batch[0] -= qty_to_pop - transfered_item_details[(d.voucher_no, d.name)].append([qty_to_pop, batch[1]]) - qty_to_pop = 0 + fifo_queue.append([d.actual_qty, d.posting_date]) + else: + if d.serial_no or d.batch_no: + serial_no_list = d.serial_no.split("\n") + for serial_no in fifo_queue: + if serial_no[0] in serial_no_list: + fifo_queue.remove(serial_no) + else: + qty_to_pop = abs(d.actual_qty) + while qty_to_pop: + batch = fifo_queue[0] if fifo_queue else [0, None] + if 0 < batch[0] <= qty_to_pop: + # if batch qty > 0 + # not enough or exactly same qty in current batch, clear batch + qty_to_pop -= batch[0] + transfered_item_details[(d.voucher_no, d.name)].append(fifo_queue.pop(0)) + else: + # all from current batch + batch[0] -= qty_to_pop + transfered_item_details[(d.voucher_no, d.name)].append([qty_to_pop, batch[1]]) + qty_to_pop = 0 item_details[key]["qty_after_transaction"] = d.qty_after_transaction @@ -182,7 +211,7 @@ def get_fifo_queue(filters): def get_stock_ledger_entries(filters): return frappe.db.sql("""select item.name, item.item_name, item_group, brand, description, item.stock_uom, - actual_qty, posting_date, voucher_type, voucher_no, qty_after_transaction, warehouse + actual_qty, posting_date, voucher_type, voucher_no, serial_no, batch_no, qty_after_transaction, warehouse from `tabStock Ledger Entry` sle, (select name, item_name, description, stock_uom, brand, item_group from `tabItem` {item_conditions}) item @@ -190,7 +219,7 @@ def get_stock_ledger_entries(filters): company = %(company)s and posting_date <= %(to_date)s {sle_conditions} - order by posting_date, posting_time, sle.creation, actual_qty"""\ + order by posting_date, posting_time, sle.creation, actual_qty""" #nosec .format(item_conditions=get_item_conditions(filters), sle_conditions=get_sle_conditions(filters)), filters, as_dict=True) From 1495c9599a22ac51eb7ffc81c4d67b4e9a23d388 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 22 Jul 2019 15:30:18 +0530 Subject: [PATCH 043/124] fix: Remove batch --- .../stock/report/stock_ageing/stock_ageing.py | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 7529ae6aa7..790cd8fc26 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -6,6 +6,7 @@ import frappe from frappe import _ from frappe.utils import date_diff, flt from six import iteritems +from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos def execute(filters=None): @@ -18,7 +19,6 @@ def execute(filters=None): details = item_dict["details"] if not fifo_queue or (not item_dict.get("total_qty")): continue - print(fifo_queue) average_age = get_average_age(fifo_queue, to_date) earliest_age = date_diff(to_date, fifo_queue[0][1]) latest_age = date_diff(to_date, fifo_queue[-1][1]) @@ -151,39 +151,27 @@ def get_fifo_queue(filters): if d.actual_qty > 0: if transfered_item_details.get((d.voucher_no, d.name)): qty_to_add = d.actual_qty - while qty_to_add: - batch = transfered_item_details[(d.voucher_no, d.name)][0] - if 0 < batch[0] <= qty_to_add: - qty_to_add -= batch[0] - fifo_queue.append(batch) - transfered_item_details[((d.voucher_no, d.name))].pop(0) - else: - batch[0] -= qty_to_add - fifo_queue.append([qty_to_add, batch[1]]) + batch = transfered_item_details[(d.voucher_no, d.name)][0] + fifo_queue.append(batch) + transfered_item_details[((d.voucher_no, d.name))].pop(0) else: - if d.serial_no or d.batch_no: + if d.serial_no: if d.serial_no: - for no in d.serial_no.split("\n"): + for no in get_serial_nos(d.serial_no): if serial_no_batch_purchase_details.get(no): fifo_queue.append([no, serial_no_batch_purchase_details.get(no)]) else: serial_no_batch_purchase_details.setdefault(no, d.posting_date) fifo_queue.append([no, d.posting_date]) - else: - if serial_no_batch_purchase_details.get(d.batch_no): - fifo_queue.append([d.batch_no, serial_no_batch_purchase_details.get(d.batch_no)]) - else: - serial_no_batch_purchase_details.setdefault(d.batch_no, d.posting_date) - fifo_queue.append([d.batch_no, d.posting_date]) - else: fifo_queue.append([d.actual_qty, d.posting_date]) else: if d.serial_no or d.batch_no: - serial_no_list = d.serial_no.split("\n") - for serial_no in fifo_queue: - if serial_no[0] in serial_no_list: - fifo_queue.remove(serial_no) + if d.serial_no: + serial_no_list = d.serial_no.split("\n") + for serial_no in fifo_queue: + if serial_no[0] in serial_no_list: + fifo_queue.remove(serial_no) else: qty_to_pop = abs(d.actual_qty) while qty_to_pop: From 7fdab021b64790972065df540469f1cb22ec2a24 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 22 Jul 2019 15:56:41 +0530 Subject: [PATCH 044/124] fix: Use get_serial_no and remove batch --- erpnext/stock/report/stock_ageing/stock_ageing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 790cd8fc26..91ba463683 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -166,9 +166,9 @@ def get_fifo_queue(filters): else: fifo_queue.append([d.actual_qty, d.posting_date]) else: - if d.serial_no or d.batch_no: + if d.serial_no: if d.serial_no: - serial_no_list = d.serial_no.split("\n") + serial_no_list = get_serial_nos(d.serial_no) for serial_no in fifo_queue: if serial_no[0] in serial_no_list: fifo_queue.remove(serial_no) From 06f99cae3660824b5dba3605fb4ce1060ecccc3b Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 23 Jul 2019 08:30:09 +0530 Subject: [PATCH 045/124] fix: Fixes in stock ageing report --- .../stock/report/stock_ageing/stock_ageing.py | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 91ba463683..83a1d7b62b 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -148,30 +148,28 @@ def get_fifo_queue(filters): if d.voucher_type == "Stock Reconciliation": d.actual_qty = flt(d.qty_after_transaction) - flt(item_details[key].get("qty_after_transaction", 0)) + serial_no_list = get_serial_nos(d.serial_no) if d.serial_no else [] + if d.actual_qty > 0: if transfered_item_details.get((d.voucher_no, d.name)): - qty_to_add = d.actual_qty batch = transfered_item_details[(d.voucher_no, d.name)][0] fifo_queue.append(batch) transfered_item_details[((d.voucher_no, d.name))].pop(0) else: - if d.serial_no: - if d.serial_no: - for no in get_serial_nos(d.serial_no): - if serial_no_batch_purchase_details.get(no): - fifo_queue.append([no, serial_no_batch_purchase_details.get(no)]) - else: - serial_no_batch_purchase_details.setdefault(no, d.posting_date) - fifo_queue.append([no, d.posting_date]) + if serial_no_list: + for serial_no in serial_no_list: + if serial_no_batch_purchase_details.get(serial_no): + fifo_queue.append([serial_no, serial_no_batch_purchase_details.get(serial_no)]) + else: + serial_no_batch_purchase_details.setdefault(serial_no, d.posting_date) + fifo_queue.append([serial_no, d.posting_date]) else: fifo_queue.append([d.actual_qty, d.posting_date]) else: - if d.serial_no: - if d.serial_no: - serial_no_list = get_serial_nos(d.serial_no) - for serial_no in fifo_queue: - if serial_no[0] in serial_no_list: - fifo_queue.remove(serial_no) + if serial_no_list: + for serial_no in fifo_queue: + if serial_no[0] in serial_no_list: + fifo_queue.remove(serial_no) else: qty_to_pop = abs(d.actual_qty) while qty_to_pop: From ecd4d3883e77c5a620078b285c6a2726cdee53a2 Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Fri, 26 Jul 2019 13:29:14 +0550 Subject: [PATCH 046/124] bumped to version 12.0.1 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 020f843c1a..a9348c11f4 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '12.0.0' +__version__ = '12.0.1' def get_default_company(user=None): '''Get default company for user''' From 3844a98c42d464532ceaaa624fba237bc3d5dbdb Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sun, 26 May 2019 18:18:21 +0530 Subject: [PATCH 047/124] fix: Pro rata calculation is not working for WDV depreciation method --- erpnext/assets/doctype/asset/asset.js | 15 ++- erpnext/assets/doctype/asset/asset.py | 109 +++++++----------- .../asset_settings/asset_settings.json | 71 +----------- 3 files changed, 56 insertions(+), 139 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 2d78d2693d..c5cad73801 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -303,14 +303,17 @@ frappe.ui.form.on('Asset', { }, set_depreciation_rate: function(frm, row) { - if (row.total_number_of_depreciations && row.frequency_of_depreciation) { + if (row.total_number_of_depreciations && row.frequency_of_depreciation + && row.expected_value_after_useful_life) { frappe.call({ method: "get_depreciation_rate", doc: frm.doc, args: row, callback: function(r) { if (r.message) { - frappe.model.set_value(row.doctype, row.name, "rate_of_depreciation", r.message); + frappe.flags.dont_change_rate = true; + frappe.model.set_value(row.doctype, row.name, + "rate_of_depreciation", flt(r.message, precision("rate_of_depreciation", row))); } } }); @@ -338,6 +341,14 @@ frappe.ui.form.on('Asset Finance Book', { total_number_of_depreciations: function(frm, cdt, cdn) { const row = locals[cdt][cdn]; frm.events.set_depreciation_rate(frm, row); + }, + + rate_of_depreciation: function(frm, cdt, cdn) { + if(!frappe.flags.dont_change_rate) { + frappe.model.set_value(cdt, cdn, "expected_value_after_useful_life", 0); + } + + frappe.flags.dont_change_rate = false; } }); diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index c398a7342a..6475d0c4aa 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -101,7 +101,8 @@ class Asset(AccountsController): def set_depreciation_rate(self): for d in self.get("finance_books"): - d.rate_of_depreciation = self.get_depreciation_rate(d, on_validate=True) + d.rate_of_depreciation = flt(self.get_depreciation_rate(d, on_validate=True), + d.precision("rate_of_depreciation")) def make_depreciation_schedule(self): depreciation_method = [d.depreciation_method for d in self.finance_books] @@ -110,8 +111,6 @@ class Asset(AccountsController): self.schedules = [] if not self.get("schedules") and self.available_for_use_date: - total_depreciations = sum([d.total_number_of_depreciations for d in self.get('finance_books')]) - for d in self.get('finance_books'): self.validate_asset_finance_books(d) @@ -124,74 +123,55 @@ class Asset(AccountsController): end_date = add_months(d.depreciation_start_date, no_of_depreciations * cint(d.frequency_of_depreciation)) - total_days = date_diff(end_date, self.available_for_use_date) - rate_per_day = (value_after_depreciation - d.get("expected_value_after_useful_life")) / total_days + if d.depreciation_method in ("Straight Line", "Manual"): + total_days = date_diff(end_date, self.available_for_use_date) + rate_per_day = (value_after_depreciation - d.get("expected_value_after_useful_life")) / total_days number_of_pending_depreciations = cint(d.total_number_of_depreciations) - \ cint(self.number_of_depreciations_booked) from_date = self.available_for_use_date if number_of_pending_depreciations: - next_depr_date = getdate(add_months(self.available_for_use_date, - number_of_pending_depreciations * 12)) - if (cint(frappe.db.get_value("Asset Settings", None, "schedule_based_on_fiscal_year")) == 1 - and getdate(d.depreciation_start_date) < next_depr_date): + period_start_date = add_months(d.depreciation_start_date, + cint(d.frequency_of_depreciation) * -1) - number_of_pending_depreciations += 1 - for n in range(number_of_pending_depreciations): - if n == list(range(number_of_pending_depreciations))[-1]: - schedule_date = add_months(self.available_for_use_date, n * 12) - previous_scheduled_date = add_months(d.depreciation_start_date, (n-1) * 12) - depreciation_amount = \ - self.get_depreciation_amount_prorata_temporis(value_after_depreciation, - d, previous_scheduled_date, schedule_date) + for n in range(number_of_pending_depreciations): + schedule_date = add_months(d.depreciation_start_date, + n * cint(d.frequency_of_depreciation)) - elif n == list(range(number_of_pending_depreciations))[0]: - schedule_date = d.depreciation_start_date - depreciation_amount = \ - self.get_depreciation_amount_prorata_temporis(value_after_depreciation, - d, self.available_for_use_date, schedule_date) + days = date_diff(schedule_date, from_date) - else: - schedule_date = add_months(d.depreciation_start_date, n * 12) - depreciation_amount = \ - self.get_depreciation_amount_prorata_temporis(value_after_depreciation, d) + if n == 0: days += 1 - if value_after_depreciation != 0: - value_after_depreciation -= flt(depreciation_amount) + if d.depreciation_method in ("Straight Line", "Manual"): + depreciation_amount = days * rate_per_day + else: + total_days = date_diff(schedule_date, period_start_date) + period_start_date = schedule_date + depreciation_amount = self.get_depreciation_amount(value_after_depreciation, + d.total_number_of_depreciations, d) - self.append("schedules", { - "schedule_date": schedule_date, - "depreciation_amount": depreciation_amount, - "depreciation_method": d.depreciation_method, - "finance_book": d.finance_book, - "finance_book_id": d.idx - }) - else: - for n in range(number_of_pending_depreciations): - schedule_date = add_months(d.depreciation_start_date, - n * cint(d.frequency_of_depreciation)) + depreciation_amount = flt((depreciation_amount * days) / total_days, + self.precision("gross_purchase_amount")) - if d.depreciation_method in ("Straight Line", "Manual"): - days = date_diff(schedule_date, from_date) - if n == 0: days += 1 + from_date = schedule_date - depreciation_amount = days * rate_per_day - from_date = schedule_date - else: - depreciation_amount = self.get_depreciation_amount(value_after_depreciation, - d.total_number_of_depreciations, d) + if depreciation_amount: + value_after_depreciation -= flt(depreciation_amount, + self.precision("gross_purchase_amount")) - if depreciation_amount: - value_after_depreciation -= flt(depreciation_amount) + if (n == cint(number_of_pending_depreciations) - 1 and + d.expected_value_after_useful_life and + value_after_depreciation > d.expected_value_after_useful_life): + depreciation_amount += (value_after_depreciation - d.expected_value_after_useful_life) - self.append("schedules", { - "schedule_date": schedule_date, - "depreciation_amount": depreciation_amount, - "depreciation_method": d.depreciation_method, - "finance_book": d.finance_book, - "finance_book_id": d.idx - }) + self.append("schedules", { + "schedule_date": schedule_date, + "depreciation_amount": depreciation_amount, + "depreciation_method": d.depreciation_method, + "finance_book": d.finance_book, + "finance_book_id": d.idx + }) def validate_asset_finance_books(self, row): if flt(row.expected_value_after_useful_life) >= flt(self.gross_purchase_amount): @@ -261,16 +241,8 @@ class Asset(AccountsController): return flt(self.get('finance_books')[cint(idx)-1].value_after_depreciation) def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row): - if row.depreciation_method in ["Straight Line", "Manual"]: - amt = (flt(self.gross_purchase_amount) - flt(row.expected_value_after_useful_life) - - flt(self.opening_accumulated_depreciation)) - - depreciation_amount = amt * row.rate_of_depreciation - else: - depreciation_amount = flt(depreciable_value) * (flt(row.rate_of_depreciation) / 100) - value_after_depreciation = flt(depreciable_value) - depreciation_amount - if value_after_depreciation < flt(row.expected_value_after_useful_life): - depreciation_amount = flt(depreciable_value) - flt(row.expected_value_after_useful_life) + precision = self.precision("gross_purchase_amount") + depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100), precision) return depreciation_amount @@ -301,9 +273,12 @@ class Asset(AccountsController): flt(accumulated_depreciation_after_full_schedule), self.precision('gross_purchase_amount')) - if row.expected_value_after_useful_life < asset_value_after_full_schedule: + if (row.expected_value_after_useful_life and + row.expected_value_after_useful_life < asset_value_after_full_schedule): frappe.throw(_("Depreciation Row {0}: Expected value after useful life must be greater than or equal to {1}") .format(row.idx, asset_value_after_full_schedule)) + elif not row.expected_value_after_useful_life: + row.expected_value_after_useful_life = asset_value_after_full_schedule def validate_cancellation(self): if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"): diff --git a/erpnext/assets/doctype/asset_settings/asset_settings.json b/erpnext/assets/doctype/asset_settings/asset_settings.json index a3fee96f4e..edc5ce169c 100644 --- a/erpnext/assets/doctype/asset_settings/asset_settings.json +++ b/erpnext/assets/doctype/asset_settings/asset_settings.json @@ -46,75 +46,6 @@ "translatable": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "schedule_based_on_fiscal_year", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Calculate Prorated Depreciation Schedule Based on Fiscal Year", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "360", - "depends_on": "eval:doc.schedule_based_on_fiscal_year", - "description": "This value is used for pro-rata temporis calculation", - "fetch_if_empty": 0, - "fieldname": "number_of_days_in_fiscal_year", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Number of Days in Fiscal Year", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -159,7 +90,7 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2019-03-08 10:44:41.924547", + "modified": "2019-05-26 18:31:19.930563", "modified_by": "Administrator", "module": "Assets", "name": "Asset Settings", From 53f5e2e0664bf60e06a8c31601329106c6be3a05 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 28 May 2019 10:33:56 +0530 Subject: [PATCH 048/124] fixed test cases and the logic for pro rata calculation --- erpnext/assets/doctype/asset/asset.py | 146 +++++++++++---------- erpnext/assets/doctype/asset/test_asset.py | 137 +++++++++++-------- 2 files changed, 160 insertions(+), 123 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 6475d0c4aa..45d2ec2c51 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -6,7 +6,7 @@ from __future__ import unicode_literals import frappe, erpnext, math, json from frappe import _ from six import string_types -from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff +from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff, add_days from frappe.model.document import Document from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account from erpnext.assets.doctype.asset.depreciation \ @@ -105,73 +105,84 @@ class Asset(AccountsController): d.precision("rate_of_depreciation")) def make_depreciation_schedule(self): - depreciation_method = [d.depreciation_method for d in self.finance_books] - - if 'Manual' not in depreciation_method: + if 'Manual' not in [d.depreciation_method for d in self.finance_books]: self.schedules = [] - if not self.get("schedules") and self.available_for_use_date: - for d in self.get('finance_books'): - self.validate_asset_finance_books(d) + if self.get("schedules") or not self.available_for_use_date: + return - value_after_depreciation = (flt(self.gross_purchase_amount) - - flt(self.opening_accumulated_depreciation)) + for d in self.get('finance_books'): + self.validate_asset_finance_books(d) - d.value_after_depreciation = value_after_depreciation + value_after_depreciation = (flt(self.gross_purchase_amount) - + flt(self.opening_accumulated_depreciation)) - no_of_depreciations = cint(d.total_number_of_depreciations - 1) - cint(self.number_of_depreciations_booked) - end_date = add_months(d.depreciation_start_date, - no_of_depreciations * cint(d.frequency_of_depreciation)) + d.value_after_depreciation = value_after_depreciation - if d.depreciation_method in ("Straight Line", "Manual"): - total_days = date_diff(end_date, self.available_for_use_date) - rate_per_day = (value_after_depreciation - d.get("expected_value_after_useful_life")) / total_days + number_of_pending_depreciations = cint(d.total_number_of_depreciations) - \ + cint(self.number_of_depreciations_booked) - number_of_pending_depreciations = cint(d.total_number_of_depreciations) - \ - cint(self.number_of_depreciations_booked) + has_pro_rata = self.check_is_pro_rata(d) - from_date = self.available_for_use_date - if number_of_pending_depreciations: - period_start_date = add_months(d.depreciation_start_date, - cint(d.frequency_of_depreciation) * -1) + if has_pro_rata: + number_of_pending_depreciations += 1 - for n in range(number_of_pending_depreciations): - schedule_date = add_months(d.depreciation_start_date, - n * cint(d.frequency_of_depreciation)) + skip_row = False + for n in range(number_of_pending_depreciations): + # If depreciation is already completed (for double declining balance) + if skip_row: continue - days = date_diff(schedule_date, from_date) + depreciation_amount = self.get_depreciation_amount(value_after_depreciation, + d.total_number_of_depreciations, d) - if n == 0: days += 1 + if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1: + schedule_date = add_months(d.depreciation_start_date, + n * cint(d.frequency_of_depreciation)) - if d.depreciation_method in ("Straight Line", "Manual"): - depreciation_amount = days * rate_per_day - else: - total_days = date_diff(schedule_date, period_start_date) - period_start_date = schedule_date - depreciation_amount = self.get_depreciation_amount(value_after_depreciation, - d.total_number_of_depreciations, d) + # For first row + if has_pro_rata and n==0: + depreciation_amount, days = get_pro_rata_amt(d, depreciation_amount, + self.available_for_use_date, d.depreciation_start_date) + # For last row + elif has_pro_rata and n == cint(number_of_pending_depreciations) - 1: + to_date = add_months(self.available_for_use_date, + n * cint(d.frequency_of_depreciation)) - depreciation_amount = flt((depreciation_amount * days) / total_days, - self.precision("gross_purchase_amount")) + depreciation_amount, days = get_pro_rata_amt(d, + depreciation_amount, schedule_date, to_date) - from_date = schedule_date + schedule_date = add_days(schedule_date, days) - if depreciation_amount: - value_after_depreciation -= flt(depreciation_amount, - self.precision("gross_purchase_amount")) + if not depreciation_amount: continue + value_after_depreciation -= flt(depreciation_amount, + self.precision("gross_purchase_amount")) - if (n == cint(number_of_pending_depreciations) - 1 and - d.expected_value_after_useful_life and - value_after_depreciation > d.expected_value_after_useful_life): - depreciation_amount += (value_after_depreciation - d.expected_value_after_useful_life) + # Adjust depreciation amount in the last period based on the expected value after useful life + if d.expected_value_after_useful_life and ((n == cint(number_of_pending_depreciations) - 1 + and value_after_depreciation != d.expected_value_after_useful_life) + or value_after_depreciation < d.expected_value_after_useful_life): + depreciation_amount += (value_after_depreciation - d.expected_value_after_useful_life) + skip_row = True - self.append("schedules", { - "schedule_date": schedule_date, - "depreciation_amount": depreciation_amount, - "depreciation_method": d.depreciation_method, - "finance_book": d.finance_book, - "finance_book_id": d.idx - }) + if depreciation_amount > 0: + self.append("schedules", { + "schedule_date": schedule_date, + "depreciation_amount": depreciation_amount, + "depreciation_method": d.depreciation_method, + "finance_book": d.finance_book, + "finance_book_id": d.idx + }) + + def check_is_pro_rata(self, row): + has_pro_rata = False + + days = date_diff(row.depreciation_start_date, self.available_for_use_date) + 1 + total_days = get_total_days(row.depreciation_start_date, row.frequency_of_depreciation) + + if days < total_days: + has_pro_rata = True + + return has_pro_rata def validate_asset_finance_books(self, row): if flt(row.expected_value_after_useful_life) >= flt(self.gross_purchase_amount): @@ -242,22 +253,13 @@ class Asset(AccountsController): def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row): precision = self.precision("gross_purchase_amount") - depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100), precision) - - return depreciation_amount - - def get_depreciation_amount_prorata_temporis(self, depreciable_value, row, start_date=None, end_date=None): - if start_date and end_date: - prorata_temporis = min(abs(flt(date_diff(str(end_date), str(start_date)))) / flt(frappe.db.get_value("Asset Settings", None, "number_of_days_in_fiscal_year")), 1) - else: - prorata_temporis = 1 if row.depreciation_method in ("Straight Line", "Manual"): depreciation_amount = (flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)) / (cint(row.total_number_of_depreciations) - - cint(self.number_of_depreciations_booked)) * prorata_temporis + cint(self.number_of_depreciations_booked)) else: - depreciation_amount = self.get_depreciation_amount(depreciable_value, row.total_number_of_depreciations, row) + depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100), precision) return depreciation_amount @@ -387,15 +389,7 @@ class Asset(AccountsController): if isinstance(args, string_types): args = json.loads(args) - number_of_depreciations_booked = 0 - if self.is_existing_asset: - number_of_depreciations_booked = self.number_of_depreciations_booked - float_precision = cint(frappe.db.get_default("float_precision")) or 2 - tot_no_of_depreciation = flt(args.get("total_number_of_depreciations")) - flt(number_of_depreciations_booked) - - if args.get("depreciation_method") in ["Straight Line", "Manual"]: - return 1.0 / tot_no_of_depreciation if args.get("depreciation_method") == 'Double Declining Balance': return 200.0 / args.get("total_number_of_depreciations") @@ -575,3 +569,15 @@ def make_journal_entry(asset_name): def is_cwip_accounting_disabled(): return cint(frappe.db.get_single_value("Asset Settings", "disable_cwip_accounting")) + +def get_pro_rata_amt(row, depreciation_amount, from_date, to_date): + days = date_diff(to_date, from_date) + total_days = get_total_days(to_date, row.frequency_of_depreciation) + + return (depreciation_amount * flt(days)) / flt(total_days), days + +def get_total_days(date, frequency): + period_start_date = add_months(date, + cint(frequency) * -1) + + return date_diff(date, period_start_date) \ No newline at end of file diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index fceccfbd1c..481ee7d9f4 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -88,23 +88,23 @@ class TestAsset(unittest.TestCase): asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') asset = frappe.get_doc('Asset', asset_name) asset.calculate_depreciation = 1 - asset.available_for_use_date = '2020-06-06' - asset.purchase_date = '2020-06-06' + asset.available_for_use_date = '2030-01-01' + asset.purchase_date = '2030-01-01' asset.append("finance_books", { "expected_value_after_useful_life": 10000, - "next_depreciation_date": "2020-12-31", "depreciation_method": "Straight Line", "total_number_of_depreciations": 3, - "frequency_of_depreciation": 10, - "depreciation_start_date": "2020-06-06" + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" }) asset.save() + self.assertEqual(asset.status, "Draft") expected_schedules = [ - ["2020-06-06", 147.54, 147.54], - ["2021-04-06", 44852.46, 45000.0], - ["2022-02-06", 45000.0, 90000.00] + ["2030-12-31", 30000.00, 30000.00], + ["2031-12-31", 30000.00, 60000.00], + ["2032-12-31", 30000.00, 90000.00] ] schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] @@ -118,20 +118,21 @@ class TestAsset(unittest.TestCase): asset.calculate_depreciation = 1 asset.number_of_depreciations_booked = 1 asset.opening_accumulated_depreciation = 40000 + asset.available_for_use_date = "2030-06-06" asset.append("finance_books", { "expected_value_after_useful_life": 10000, - "next_depreciation_date": "2020-12-31", "depreciation_method": "Straight Line", "total_number_of_depreciations": 3, - "frequency_of_depreciation": 10, - "depreciation_start_date": "2020-06-06" + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" }) asset.insert() self.assertEqual(asset.status, "Draft") asset.save() expected_schedules = [ - ["2020-06-06", 164.47, 40164.47], - ["2021-04-06", 49835.53, 90000.00] + ["2030-12-31", 14246.58, 54246.58], + ["2031-12-31", 25000.00, 79246.58], + ["2032-06-06", 10753.42, 90000.00] ] schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount] for d in asset.get("schedules")] @@ -145,24 +146,23 @@ class TestAsset(unittest.TestCase): asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') asset = frappe.get_doc('Asset', asset_name) asset.calculate_depreciation = 1 - asset.available_for_use_date = '2020-06-06' - asset.purchase_date = '2020-06-06' + asset.available_for_use_date = '2030-01-01' + asset.purchase_date = '2030-01-01' asset.append("finance_books", { "expected_value_after_useful_life": 10000, - "next_depreciation_date": "2020-12-31", "depreciation_method": "Double Declining Balance", "total_number_of_depreciations": 3, - "frequency_of_depreciation": 10, - "depreciation_start_date": "2020-06-06" + "frequency_of_depreciation": 12, + "depreciation_start_date": '2030-12-31' }) asset.insert() self.assertEqual(asset.status, "Draft") asset.save() expected_schedules = [ - ["2020-06-06", 66666.67, 66666.67], - ["2021-04-06", 22222.22, 88888.89], - ["2022-02-06", 1111.11, 90000.0] + ['2030-12-31', 66667.00, 66667.00], + ['2031-12-31', 22222.11, 88889.11], + ['2032-12-31', 1110.89, 90000.0] ] schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] @@ -177,23 +177,21 @@ class TestAsset(unittest.TestCase): asset.is_existing_asset = 1 asset.number_of_depreciations_booked = 1 asset.opening_accumulated_depreciation = 50000 + asset.available_for_use_date = '2030-01-01' + asset.purchase_date = '2029-11-30' asset.append("finance_books", { "expected_value_after_useful_life": 10000, - "next_depreciation_date": "2020-12-31", "depreciation_method": "Double Declining Balance", "total_number_of_depreciations": 3, - "frequency_of_depreciation": 10, - "depreciation_start_date": "2020-06-06" + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" }) asset.insert() self.assertEqual(asset.status, "Draft") - asset.save() - - asset.save() expected_schedules = [ - ["2020-06-06", 33333.33, 83333.33], - ["2021-04-06", 6666.67, 90000.0] + ["2030-12-31", 33333.50, 83333.50], + ["2031-12-31", 6666.50, 90000.0] ] schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] @@ -209,25 +207,25 @@ class TestAsset(unittest.TestCase): asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') asset = frappe.get_doc('Asset', asset_name) asset.calculate_depreciation = 1 - asset.purchase_date = '2020-01-30' + asset.purchase_date = '2030-01-30' asset.is_existing_asset = 0 - asset.available_for_use_date = "2020-01-30" + asset.available_for_use_date = "2030-01-30" asset.append("finance_books", { "expected_value_after_useful_life": 10000, "depreciation_method": "Straight Line", "total_number_of_depreciations": 3, - "frequency_of_depreciation": 10, - "depreciation_start_date": "2020-12-31" + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" }) asset.insert() asset.save() expected_schedules = [ - ["2020-12-31", 28000.0, 28000.0], - ["2021-12-31", 30000.0, 58000.0], - ["2022-12-31", 30000.0, 88000.0], - ["2023-01-30", 2000.0, 90000.0] + ["2030-12-31", 27534.25, 27534.25], + ["2031-12-31", 30000.0, 57534.25], + ["2032-12-31", 30000.0, 87534.25], + ["2033-01-30", 2465.75, 90000.0] ] schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)] @@ -266,8 +264,8 @@ class TestAsset(unittest.TestCase): self.assertEqual(asset.get("schedules")[0].journal_entry[:4], "DEPR") expected_gle = ( - ("_Test Accumulated Depreciations - _TC", 0.0, 32129.24), - ("_Test Depreciations - _TC", 32129.24, 0.0) + ("_Test Accumulated Depreciations - _TC", 0.0, 30000.0), + ("_Test Depreciations - _TC", 30000.0, 0.0) ) gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` @@ -277,15 +275,15 @@ class TestAsset(unittest.TestCase): self.assertEqual(gle, expected_gle) self.assertEqual(asset.get("value_after_depreciation"), 0) - def test_depreciation_entry_for_wdv(self): + def test_depreciation_entry_for_wdv_without_pro_rata(self): pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=8000.0, location="Test Location") asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') asset = frappe.get_doc('Asset', asset_name) asset.calculate_depreciation = 1 - asset.available_for_use_date = '2030-06-06' - asset.purchase_date = '2030-06-06' + asset.available_for_use_date = '2030-01-01' + asset.purchase_date = '2030-01-01' asset.append("finance_books", { "expected_value_after_useful_life": 1000, "depreciation_method": "Written Down Value", @@ -298,9 +296,41 @@ class TestAsset(unittest.TestCase): self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) expected_schedules = [ - ["2030-12-31", 4000.0, 4000.0], - ["2031-12-31", 2000.0, 6000.0], - ["2032-12-31", 1000.0, 7000.0], + ["2030-12-31", 4000.00, 4000.00], + ["2031-12-31", 2000.00, 6000.00], + ["2032-12-31", 1000.00, 7000.0], + ] + + schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + + def test_pro_rata_depreciation_entry_for_wdv(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=8000.0, location="Test Location") + + asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') + asset = frappe.get_doc('Asset', asset_name) + asset.calculate_depreciation = 1 + asset.available_for_use_date = '2030-06-06' + asset.purchase_date = '2030-01-01' + asset.append("finance_books", { + "expected_value_after_useful_life": 1000, + "depreciation_method": "Written Down Value", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" + }) + asset.save(ignore_permissions=True) + + self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) + + expected_schedules = [ + ["2030-12-31", 2279.45, 2279.45], + ["2031-12-31", 2860.28, 5139.73], + ["2032-12-31", 1430.14, 6569.87], + ["2033-06-06", 430.13, 7000.0], ] schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)] @@ -346,18 +376,19 @@ class TestAsset(unittest.TestCase): asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') asset = frappe.get_doc('Asset', asset_name) asset.calculate_depreciation = 1 - asset.available_for_use_date = '2020-06-06' - asset.purchase_date = '2020-06-06' + asset.available_for_use_date = nowdate() + asset.purchase_date = nowdate() asset.append("finance_books", { "expected_value_after_useful_life": 10000, "depreciation_method": "Straight Line", "total_number_of_depreciations": 3, "frequency_of_depreciation": 10, - "depreciation_start_date": "2020-06-06" + "depreciation_start_date": nowdate() }) asset.insert() asset.submit() - post_depreciation_entries(date="2021-01-01") + + post_depreciation_entries(date=add_months(nowdate(), 10)) scrap_asset(asset.name) @@ -366,9 +397,9 @@ class TestAsset(unittest.TestCase): self.assertTrue(asset.journal_entry_for_scrap) expected_gle = ( - ("_Test Accumulated Depreciations - _TC", 147.54, 0.0), + ("_Test Accumulated Depreciations - _TC", 30000.0, 0.0), ("_Test Fixed Asset - _TC", 0.0, 100000.0), - ("_Test Gain/Loss on Asset Disposal - _TC", 99852.46, 0.0) + ("_Test Gain/Loss on Asset Disposal - _TC", 70000.0, 0.0) ) gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` @@ -412,9 +443,9 @@ class TestAsset(unittest.TestCase): self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold") expected_gle = ( - ("_Test Accumulated Depreciations - _TC", 23051.47, 0.0), + ("_Test Accumulated Depreciations - _TC", 20392.16, 0.0), ("_Test Fixed Asset - _TC", 0.0, 100000.0), - ("_Test Gain/Loss on Asset Disposal - _TC", 51948.53, 0.0), + ("_Test Gain/Loss on Asset Disposal - _TC", 54607.84, 0.0), ("Debtors - _TC", 25000.0, 0.0) ) From e666b882e731fd52611c46eafcecb41968cd2b9b Mon Sep 17 00:00:00 2001 From: Michelle Alva <50285544+michellealva@users.noreply.github.com> Date: Sat, 27 Jul 2019 10:03:18 +0530 Subject: [PATCH 049/124] fix: added payroll period in HR module (#18500) --- erpnext/config/hr.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/config/hr.py b/erpnext/config/hr.py index 0367755595..bb055df3a3 100644 --- a/erpnext/config/hr.py +++ b/erpnext/config/hr.py @@ -160,6 +160,10 @@ def get_data(): "name": "Salary Slip", "onboard": 1, }, + { + "type": "doctype", + "name": "Payroll Period", + }, { "type": "doctype", "name": "Salary Component", From f0f4dbd5f84bedaa16c53ea488a2f288b16c4f09 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Sat, 27 Jul 2019 10:05:33 +0530 Subject: [PATCH 050/124] fix(payroll-entry): show make bank entry button when manually submitting salary slip (#18498) --- erpnext/hr/doctype/payroll_entry/payroll_entry.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.py b/erpnext/hr/doctype/payroll_entry/payroll_entry.py index d8dd5c644b..38c36d9461 100644 --- a/erpnext/hr/doctype/payroll_entry/payroll_entry.py +++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.py @@ -12,6 +12,16 @@ from erpnext.accounts.utils import get_fiscal_year from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee class PayrollEntry(Document): + def onload(self): + if not self.docstatus==1: + return + + # check if salary slips were manually submitted + entries = frappe.db.count("Salary Slip", {'payroll_entry': self.name, 'docstatus': 1}, ['name']) + if cint(entries) == len(self.employees) and not self.salary_slips_submitted: + self.db_set("salary_slips_submitted", 1) + self.reload() + def on_submit(self): self.create_salary_slips() From 82a9118cb2a3b2d25be7440c65133442fd0ee1de Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Sat, 27 Jul 2019 13:14:21 +0550 Subject: [PATCH 051/124] bumped to version 12.0.2 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index a9348c11f4..04f741e14b 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '12.0.1' +__version__ = '12.0.2' def get_default_company(user=None): '''Get default company for user''' From b590f8931093de81a805bef429292afd90758b44 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 14 Jul 2019 19:28:56 +0530 Subject: [PATCH 052/124] fix: Default Accounting Dimensions in doctypes --- .../accounting_dimension/accounting_dimension.json | 9 ++++++++- erpnext/public/js/utils.js | 2 +- erpnext/public/js/utils/dimension_tree_filter.js | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json index 6a4dc5c34f..0fab74d522 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json @@ -9,6 +9,7 @@ "document_type", "label", "fieldname", + "default_dimension", "mandatory_for_bs", "mandatory_for_pl", "disabled" @@ -53,9 +54,15 @@ "fieldname": "mandatory_for_pl", "fieldtype": "Check", "label": "Mandatory For Profit and Loss Account" + }, + { + "fieldname": "default_dimension", + "fieldtype": "Dynamic Link", + "label": "Default Dimension", + "options": "document_type" } ], - "modified": "2019-07-14 17:25:01.307948", + "modified": "2019-07-14 19:16:25.405924", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting Dimension", diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 0252f38931..1c5e98eb7d 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -69,7 +69,7 @@ $.extend(erpnext, { return []; } let dimensions = await frappe.db.get_list('Accounting Dimension', { - fields: ['label', 'fieldname', 'document_type'], + fields: ['label', 'fieldname', 'document_type', 'default_dimension'], filters: { disabled: 0 } diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js index 549f95e039..4a82edda69 100644 --- a/erpnext/public/js/utils/dimension_tree_filter.js +++ b/erpnext/public/js/utils/dimension_tree_filter.js @@ -14,6 +14,9 @@ erpnext.doctypes_with_dimensions.forEach((doctype) => { onload: function(frm) { erpnext.dimension_filters.then((dimensions) => { dimensions.forEach((dimension) => { + if (dimension['default_dimension']) { + frm.set_value(dimension['fieldname'], dimension['default_dimension']); + } frappe.model.with_doctype(dimension['document_type'], () => { if (frappe.meta.has_field(dimension['document_type'], 'is_group')) { frm.set_query(dimension['fieldname'], { From 7d270edf799b316832106f478d50d11a23c60d9c Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Wed, 17 Jul 2019 15:38:21 +0530 Subject: [PATCH 053/124] fix: Added default dimension and filter in bootinfo --- .../accounting_dimension.js | 68 +++++++++++-------- .../accounting_dimension.json | 12 ++-- .../accounting_dimension.py | 8 +++ .../accounting_dimension_detail/__init__.py | 0 .../accounting_dimension_detail.json | 47 +++++++++++++ .../accounting_dimension_detail.py | 10 +++ .../journal_entry_account.json | 4 +- .../sales_invoice_item.json | 3 +- .../accounts_payable/accounts_payable.js | 15 ++-- .../accounts_payable_summary.js | 15 ++-- .../accounts_receivable.js | 15 ++-- .../accounts_receivable_summary.js | 14 ++-- .../budget_variance_report.js | 7 +- .../report/general_ledger/general_ledger.js | 15 ++-- .../profitability_analysis.js | 7 +- .../report/sales_register/sales_register.js | 15 ++-- .../report/trial_balance/trial_balance.js | 6 +- erpnext/public/js/financial_statements.js | 14 ++-- erpnext/public/js/utils.js | 14 ---- .../public/js/utils/dimension_tree_filter.js | 41 +++++++---- erpnext/startup/boot.py | 18 +++++ 21 files changed, 219 insertions(+), 129 deletions(-) create mode 100644 erpnext/accounts/doctype/accounting_dimension_detail/__init__.py create mode 100644 erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json create mode 100644 erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js index ffb6d5e597..bb4d514981 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js @@ -8,41 +8,48 @@ frappe.ui.form.on('Accounting Dimension', { frm.add_custom_button(__('Show {0}', [frm.doc.document_type]), function () { frappe.set_route("List", frm.doc.document_type); }); - } - frm.set_query('document_type', () => { - return { - filters: { - name: ['not in', ['Accounting Dimension', 'Project', 'Cost Center']] - } - }; - }); - - let button = frm.doc.disabled ? "Enable" : "Disable"; - - frm.add_custom_button(__(button), function() { - - frm.set_value('disabled', 1 - frm.doc.disabled); - - frappe.call({ - method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension", - args: { - doc: frm.doc - }, - freeze: true, - callback: function(r) { - let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled"; - frm.save(); - frappe.show_alert({message:__(message), indicator:'green'}); - } + frm.set_query('document_type', () => { + return { + filters: { + name: ['not in', ['Accounting Dimension', 'Project', 'Cost Center']] + } + }; }); - }); + + let button = frm.doc.disabled ? "Enable" : "Disable"; + + frm.add_custom_button(__(button), function() { + + frm.set_value('disabled', 1 - frm.doc.disabled); + + frappe.call({ + method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension", + args: { + doc: frm.doc + }, + freeze: true, + callback: function(r) { + let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled"; + frm.save(); + frappe.show_alert({message:__(message), indicator:'green'}); + } + }); + }); + } }, document_type: function(frm) { + frm.set_value('label', frm.doc.document_type); frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type)); + if (frm.is_new()){ + let row = frappe.model.add_child(frm.doc, "Accounting Dimension Detail", "dimension_defaults"); + row.reference_document = frm.doc.document_type; + frm.refresh_fields("dimension_defaults"); + } + frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => { if (r && r.document_type) { frm.set_df_property('document_type', 'description', "Document type is already set as dimension"); @@ -50,3 +57,10 @@ frappe.ui.form.on('Accounting Dimension', { }); }, }); + +frappe.ui.form.on('Accounting Dimension Detail', { + dimension_defaults_add: function(frm, cdt, cdn) { + let row = locals[cdt][cdn]; + row.reference_document = frm.doc.document_type; + } +}) \ No newline at end of file diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json index 0fab74d522..19fa9bf837 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json @@ -9,7 +9,7 @@ "document_type", "label", "fieldname", - "default_dimension", + "dimension_defaults", "mandatory_for_bs", "mandatory_for_pl", "disabled" @@ -56,13 +56,13 @@ "label": "Mandatory For Profit and Loss Account" }, { - "fieldname": "default_dimension", - "fieldtype": "Dynamic Link", - "label": "Default Dimension", - "options": "document_type" + "fieldname": "dimension_defaults", + "fieldtype": "Table", + "label": "Dimension Defaults", + "options": "Accounting Dimension Detail" } ], - "modified": "2019-07-14 19:16:25.405924", + "modified": "2019-07-16 18:00:11.365510", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting Dimension", diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index 314849847c..218ab596e3 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -144,6 +144,14 @@ def toggle_disabling(doc): frappe.clear_cache(doctype=doctype) + dimension_filters = frappe.db.sql(""" + SELECT label, fieldname, document_type + FROM `tabAccounting Dimension` + WHERE disabled = 0 + """, as_dict=1) + + return dimension_filters + def get_doctypes_with_dimensions(): doclist = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset", "Expense Claim", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note", "Sales Invoice Item", "Purchase Invoice Item", diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/__init__.py b/erpnext/accounts/doctype/accounting_dimension_detail/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json new file mode 100644 index 0000000000..f46a065271 --- /dev/null +++ b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json @@ -0,0 +1,47 @@ +{ + "creation": "2019-07-16 17:53:18.718831", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "company", + "reference_document", + "default_dimension" + ], + "fields": [ + { + "fieldname": "company", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Company", + "options": "Company", + "reqd": 1 + }, + { + "fieldname": "reference_document", + "fieldtype": "Link", + "hidden": 1, + "label": "Reference Document", + "options": "DocType", + "read_only": 1 + }, + { + "fieldname": "default_dimension", + "fieldtype": "Dynamic Link", + "in_list_view": 1, + "label": "Default Dimension", + "options": "reference_document", + "reqd": 1 + } + ], + "istable": 1, + "modified": "2019-07-16 18:54:52.202378", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Accounting Dimension Detail", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py new file mode 100644 index 0000000000..17cf549fc4 --- /dev/null +++ b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +# import frappe +from frappe.model.document import Document + +class AccountingDimensionDetail(Document): + pass diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json index e4acf5a03d..8728950286 100644 --- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json @@ -258,6 +258,7 @@ "print_hide": 1 }, { + "collapsible": 1, "fieldname": "accounting_dimensions_section", "fieldtype": "Section Break", "label": "Accounting Dimensions" @@ -269,12 +270,13 @@ ], "idx": 1, "istable": 1, - "modified": "2019-05-25 22:14:02.715509", + "modified": "2019-07-16 17:12:08.238334", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry Account", "owner": "Administrator", "permissions": [], + "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json index 465df277fd..779ac4f656 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -764,6 +764,7 @@ "label": "Image" }, { + "collapsible": 1, "fieldname": "accounting_dimensions_section", "fieldtype": "Section Break", "label": "Accounting Dimensions" @@ -782,7 +783,7 @@ ], "idx": 1, "istable": 1, - "modified": "2019-06-28 17:30:12.156086", + "modified": "2019-07-16 16:36:46.527606", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Item", diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js index cfcc575718..5e07d080fb 100644 --- a/erpnext/accounts/report/accounts_payable/accounts_payable.js +++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js @@ -115,13 +115,12 @@ frappe.query_reports["Accounts Payable"] = { } } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Accounts Payable"].filters.splice(9, 0 ,{ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Accounts Payable"].filters.splice(9, 0 ,{ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); + diff --git a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js index 006068a266..426de6782d 100644 --- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js +++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js @@ -99,13 +99,12 @@ frappe.query_reports["Accounts Payable Summary"] = { } } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Accounts Payable Summary"].filters.splice(9, 0 ,{ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Accounts Payable Summary"].filters.splice(9, 0 ,{ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); + diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js index 2a45454bac..816e43898a 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js @@ -173,13 +173,12 @@ frappe.query_reports["Accounts Receivable"] = { } } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Accounts Receivable"].filters.splice(9, 0 ,{ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Accounts Receivable"].filters.splice(9, 0 ,{ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); + diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js index a7c0787fcd..d63af8b3f3 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js @@ -117,13 +117,11 @@ frappe.query_reports["Accounts Receivable Summary"] = { } } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Accounts Receivable Summary"].filters.splice(9, 0 ,{ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Accounts Receivable Summary"].filters.splice(9, 0 ,{ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js index f2a33a83ee..33dc555a95 100644 --- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js +++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js @@ -63,8 +63,7 @@ frappe.query_reports["Budget Variance Report"] = { ] } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Budget Variance Report"].filters[4].options.push(dimension["document_type"]); - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Budget Variance Report"].filters[4].options.push(dimension["document_type"]); }); + diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index ea82575b80..74a1ea70ac 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -159,13 +159,12 @@ frappe.query_reports["General Ledger"] = { ] } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["General Ledger"].filters.splice(15, 0 ,{ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["General Ledger"].filters.splice(15, 0 ,{ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); + diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js index d6864b54f7..2656a7e7b5 100644 --- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js +++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js @@ -105,9 +105,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "initial_depth": 3 } - erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Profitability Analysis"].filters[1].options.push(dimension["document_type"]); - }); + frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Profitability Analysis"].filters[1].options.push(dimension["document_type"]); }); + }); diff --git a/erpnext/accounts/report/sales_register/sales_register.js b/erpnext/accounts/report/sales_register/sales_register.js index 442aa1262e..105f5a29c1 100644 --- a/erpnext/accounts/report/sales_register/sales_register.js +++ b/erpnext/accounts/report/sales_register/sales_register.js @@ -68,13 +68,12 @@ frappe.query_reports["Sales Register"] = { ] } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Sales Register"].filters.splice(7, 0 ,{ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Sales Register"].filters.splice(7, 0 ,{ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); + diff --git a/erpnext/accounts/report/trial_balance/trial_balance.js b/erpnext/accounts/report/trial_balance/trial_balance.js index 73d2ab3898..dc6d07e2bb 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.js +++ b/erpnext/accounts/report/trial_balance/trial_balance.js @@ -94,10 +94,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "parent_field": "parent_account", "initial_depth": 3 } -}); -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { + frappe.boot.dimension_filters.forEach((dimension) => { frappe.query_reports["Trial Balance"].filters.splice(5, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), @@ -107,3 +105,5 @@ erpnext.dimension_filters.then((dimensions) => { }); }); + + diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js index 89cb13d981..5feedd3e15 100644 --- a/erpnext/public/js/financial_statements.js +++ b/erpnext/public/js/financial_statements.js @@ -129,14 +129,12 @@ function get_filters(){ } ] - erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - filters.push({ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); + frappe.boot.dimension_filters.forEach((dimension) => { + filters.push({ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 1c5e98eb7d..0a363a04fd 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -63,20 +63,6 @@ $.extend(erpnext, { me.show_serial_batch_selector(grid_row.frm, grid_row.doc); }); }, - - get_dimension_filters: async function() { - if (!frappe.model.can_read('Accounting Dimension')) { - return []; - } - let dimensions = await frappe.db.get_list('Accounting Dimension', { - fields: ['label', 'fieldname', 'document_type', 'default_dimension'], - filters: { - disabled: 0 - } - }); - - return dimensions; - } }); diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js index 4a82edda69..22b4834dfb 100644 --- a/erpnext/public/js/utils/dimension_tree_filter.js +++ b/erpnext/public/js/utils/dimension_tree_filter.js @@ -7,25 +7,40 @@ erpnext.doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoi "Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation", "Travel Request", "Fees", "POS Profile"]; -erpnext.dimension_filters = erpnext.get_dimension_filters(); - erpnext.doctypes_with_dimensions.forEach((doctype) => { frappe.ui.form.on(doctype, { onload: function(frm) { - erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - if (dimension['default_dimension']) { - frm.set_value(dimension['fieldname'], dimension['default_dimension']); + frappe.boot.dimension_filters.forEach((dimension) => { + frappe.model.with_doctype(dimension['document_type'], () => { + if (frappe.meta.has_field(dimension['document_type'], 'is_group')) { + frm.set_query(dimension['fieldname'], { + "is_group": 0 + }); } - frappe.model.with_doctype(dimension['document_type'], () => { - if (frappe.meta.has_field(dimension['document_type'], 'is_group')) { - frm.set_query(dimension['fieldname'], { - "is_group": 0 - }); - } - }); }); }); + }, + + company: function(frm) { + if(frm.doc.company) { + frappe.boot.dimension_filters.forEach((dimension) => { + frm.set_value(dimension['fieldname'], frappe.boot.default_dimensions[frm.doc.company][dimension['document_type']]); + }); + } + }, + + items_add: function(frm, cdt, cdn) { + frappe.boot.dimension_filters.forEach((dimension) => { + var row = frappe.get_doc(cdt, cdn); + frm.script_manager.copy_from_first_row("items", row, [dimension['fieldname']]); + }); + }, + + accounts_add: function(frm, cdt, cdn) { + frappe.boot.dimension_filters.forEach((dimension) => { + var row = frappe.get_doc(cdt, cdn); + frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]); + }); } }); }); \ No newline at end of file diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py index 4ca43a89b8..7d70cc2349 100644 --- a/erpnext/startup/boot.py +++ b/erpnext/startup/boot.py @@ -39,6 +39,8 @@ def boot_session(bootinfo): party_account_types = frappe.db.sql(""" select name, ifnull(account_type, '') from `tabParty Type`""") bootinfo.party_account_types = frappe._dict(party_account_types) + load_dimension_filters(bootinfo) + load_default_dimensions(bootinfo) def load_country_and_currency(bootinfo): country = frappe.db.get_default("country") @@ -49,6 +51,22 @@ def load_country_and_currency(bootinfo): number_format, smallest_currency_fraction_value, symbol from tabCurrency where enabled=1""", as_dict=1, update={"doctype":":Currency"}) +def load_dimension_filters(bootinfo): + bootinfo.dimension_filters = frappe.db.sql(""" + SELECT label, fieldname, document_type + FROM `tabAccounting Dimension` + WHERE disabled = 0 + """, as_dict=1) + +def load_default_dimensions(bootinfo): + default_dimensions = frappe.db.sql("""SELECT parent, company, default_dimension + FROM `tabAccounting Dimension Detail`""", as_dict=1) + + bootinfo.default_dimensions = {} + for dimension in default_dimensions: + bootinfo.default_dimensions.setdefault(dimension['company'], {}) + bootinfo.default_dimensions[dimension['company']][dimension['parent']] = dimension['default_dimension'] + def update_page_info(bootinfo): bootinfo.page_info.update({ "Chart of Accounts": { From f1f79ff1e14308cd31ef752469278f79bc1f7cf1 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 18 Jul 2019 08:54:15 +0530 Subject: [PATCH 054/124] fix: Remove dimensions from boot --- .../accounting_dimension.json | 18 +--------- .../accounting_dimension.py | 34 ++++++++++++++----- .../accounting_dimension_detail.json | 24 +++++++++++-- erpnext/accounts/doctype/gl_entry/gl_entry.py | 16 ++++----- .../accounts_payable/accounts_payable.js | 2 +- .../accounts_payable_summary.js | 2 +- .../accounts_receivable.js | 2 +- .../accounts_receivable_summary.js | 2 +- .../budget_variance_report.js | 2 +- .../report/general_ledger/general_ledger.js | 2 +- .../profitability_analysis.js | 2 +- .../report/sales_register/sales_register.js | 2 +- .../report/trial_balance/trial_balance.js | 2 +- erpnext/public/js/financial_statements.js | 2 +- .../public/js/utils/dimension_tree_filter.js | 18 +++++++--- erpnext/startup/boot.py | 18 ---------- 16 files changed, 79 insertions(+), 69 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json index 19fa9bf837..cf6dc7a8fa 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json @@ -1,6 +1,4 @@ { - "_comments": "[]", - "_liked_by": "[]", "autoname": "field:label", "creation": "2019-05-04 18:13:37.002352", "doctype": "DocType", @@ -10,8 +8,6 @@ "label", "fieldname", "dimension_defaults", - "mandatory_for_bs", - "mandatory_for_pl", "disabled" ], "fields": [ @@ -43,18 +39,6 @@ "label": "Disable", "read_only": 1 }, - { - "default": "0", - "fieldname": "mandatory_for_bs", - "fieldtype": "Check", - "label": "Mandatory For Balance Sheet" - }, - { - "default": "0", - "fieldname": "mandatory_for_pl", - "fieldtype": "Check", - "label": "Mandatory For Profit and Loss Account" - }, { "fieldname": "dimension_defaults", "fieldtype": "Table", @@ -62,7 +46,7 @@ "options": "Accounting Dimension Detail" } ], - "modified": "2019-07-16 18:00:11.365510", + "modified": "2019-07-17 16:49:31.134385", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting Dimension", diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index 218ab596e3..90cc50d419 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -144,14 +144,6 @@ def toggle_disabling(doc): frappe.clear_cache(doctype=doctype) - dimension_filters = frappe.db.sql(""" - SELECT label, fieldname, document_type - FROM `tabAccounting Dimension` - WHERE disabled = 0 - """, as_dict=1) - - return dimension_filters - def get_doctypes_with_dimensions(): doclist = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset", "Expense Claim", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note", "Sales Invoice Item", "Purchase Invoice Item", @@ -163,9 +155,33 @@ def get_doctypes_with_dimensions(): return doclist def get_accounting_dimensions(as_list=True): - accounting_dimensions = frappe.get_all("Accounting Dimension", fields=["label", "fieldname", "mandatory_for_pl", "mandatory_for_bs", "disabled"], filters={"disabled": 0}) + accounting_dimensions = frappe.get_all("Accounting Dimension", fields=["label", "fieldname", "disabled"]) if as_list: return [d.fieldname for d in accounting_dimensions] else: return accounting_dimensions + +def get_checks_for_pl_and_bs_accounts(): + dimensions = frappe.db.sql("""SELECT parent, company, mandatory_for_pl, mandatory_for_bs + FROM `tabAccounting Dimension Detail`""", as_dict=1) + + return dimensions + +@frappe.whitelist() +def get_dimension_filters(): + dimension_filters = frappe.db.sql(""" + SELECT label, fieldname, document_type + FROM `tabAccounting Dimension` + WHERE disabled = 0 + """, as_dict=1) + + default_dimensions = frappe.db.sql("""SELECT parent, company, default_dimension + FROM `tabAccounting Dimension Detail`""", as_dict=1) + + default_dimensions_map = {} + for dimension in default_dimensions: + default_dimensions_map.setdefault(dimension['company'], {}) + default_dimensions_map[dimension['company']][dimension['parent']] = dimension['default_dimension'] + + return dimension_filters, default_dimensions_map diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json index f46a065271..1ccef6cc7a 100644 --- a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json +++ b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json @@ -6,10 +6,13 @@ "field_order": [ "company", "reference_document", - "default_dimension" + "default_dimension", + "mandatory_for_bs", + "mandatory_for_pl" ], "fields": [ { + "columns": 2, "fieldname": "company", "fieldtype": "Link", "in_list_view": 1, @@ -26,16 +29,33 @@ "read_only": 1 }, { + "columns": 2, "fieldname": "default_dimension", "fieldtype": "Dynamic Link", "in_list_view": 1, "label": "Default Dimension", "options": "reference_document", "reqd": 1 + }, + { + "columns": 3, + "default": "0", + "fieldname": "mandatory_for_bs", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Mandatory For Balance Sheet" + }, + { + "columns": 3, + "default": "0", + "fieldname": "mandatory_for_pl", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Mandatory For Profit and Loss Account" } ], "istable": 1, - "modified": "2019-07-16 18:54:52.202378", + "modified": "2019-07-17 23:34:33.026883", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting Dimension Detail", diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 84276eae10..80e518644d 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -12,7 +12,7 @@ from erpnext.accounts.party import validate_party_gle_currency, validate_party_f from erpnext.accounts.utils import get_account_currency from erpnext.accounts.utils import get_fiscal_year from erpnext.exceptions import InvalidAccountCurrency -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_checks_for_pl_and_bs_accounts exclude_from_linked_with = True class GLEntry(Document): @@ -86,19 +86,19 @@ class GLEntry(Document): account_type = frappe.db.get_value("Account", self.account, "report_type") - for dimension in get_accounting_dimensions(as_list=False): + for dimension in get_checks_for_pl_and_bs_accounts(): if account_type == "Profit and Loss" \ - and dimension.mandatory_for_pl and not dimension.disabled: - if not self.get(dimension.fieldname): + and self.company == dimension.company and dimension.mandatory_for_pl and not dimension.disabled: + if not self.get(frappe.scrub(dimension.parent)): frappe.throw(_("Accounting Dimension {0} is required for 'Profit and Loss' account {1}.") - .format(dimension.label, self.account)) + .format(dimension.parent, self.account)) if account_type == "Balance Sheet" \ - and dimension.mandatory_for_bs and not dimension.disabled: - if not self.get(dimension.fieldname): + and self.company == dimension.company and dimension.mandatory_for_bs and not dimension.disabled: + if not self.get(frappe.scrub(dimension.parent)): frappe.throw(_("Accounting Dimension {0} is required for 'Balance Sheet' account {1}.") - .format(dimension.label, self.account)) + .format(dimension.parent, self.account)) def check_pl_account(self): diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js index 5e07d080fb..8eb670de51 100644 --- a/erpnext/accounts/report/accounts_payable/accounts_payable.js +++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js @@ -115,7 +115,7 @@ frappe.query_reports["Accounts Payable"] = { } } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Accounts Payable"].filters.splice(9, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js index 426de6782d..5f0fdc9f2c 100644 --- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js +++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js @@ -99,7 +99,7 @@ frappe.query_reports["Accounts Payable Summary"] = { } } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Accounts Payable Summary"].filters.splice(9, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js index 816e43898a..4551973ac6 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js @@ -173,7 +173,7 @@ frappe.query_reports["Accounts Receivable"] = { } } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Accounts Receivable"].filters.splice(9, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js index d63af8b3f3..0120608a8f 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js @@ -117,7 +117,7 @@ frappe.query_reports["Accounts Receivable Summary"] = { } } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Accounts Receivable Summary"].filters.splice(9, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js index 33dc555a95..24511871fd 100644 --- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js +++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js @@ -63,7 +63,7 @@ frappe.query_reports["Budget Variance Report"] = { ] } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Budget Variance Report"].filters[4].options.push(dimension["document_type"]); }); diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index 74a1ea70ac..4a287060b3 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -159,7 +159,7 @@ frappe.query_reports["General Ledger"] = { ] } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["General Ledger"].filters.splice(15, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js index 2656a7e7b5..889ede5a82 100644 --- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js +++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js @@ -105,7 +105,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "initial_depth": 3 } - frappe.boot.dimension_filters.forEach((dimension) => { + erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Profitability Analysis"].filters[1].options.push(dimension["document_type"]); }); diff --git a/erpnext/accounts/report/sales_register/sales_register.js b/erpnext/accounts/report/sales_register/sales_register.js index 105f5a29c1..9dee656d4a 100644 --- a/erpnext/accounts/report/sales_register/sales_register.js +++ b/erpnext/accounts/report/sales_register/sales_register.js @@ -68,7 +68,7 @@ frappe.query_reports["Sales Register"] = { ] } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Sales Register"].filters.splice(7, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/accounts/report/trial_balance/trial_balance.js b/erpnext/accounts/report/trial_balance/trial_balance.js index dc6d07e2bb..f15b5b1a19 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.js +++ b/erpnext/accounts/report/trial_balance/trial_balance.js @@ -95,7 +95,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "initial_depth": 3 } - frappe.boot.dimension_filters.forEach((dimension) => { + erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Trial Balance"].filters.splice(5, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js index 5feedd3e15..63e057c39d 100644 --- a/erpnext/public/js/financial_statements.js +++ b/erpnext/public/js/financial_statements.js @@ -129,7 +129,7 @@ function get_filters(){ } ] - frappe.boot.dimension_filters.forEach((dimension) => { + erpnext.dimension_filters.forEach((dimension) => { filters.push({ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js index 22b4834dfb..9d4c435240 100644 --- a/erpnext/public/js/utils/dimension_tree_filter.js +++ b/erpnext/public/js/utils/dimension_tree_filter.js @@ -7,10 +7,18 @@ erpnext.doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoi "Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation", "Travel Request", "Fees", "POS Profile"]; +frappe.call({ + method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimension_filters", + callback: function(r){ + erpnext.dimension_filters = r.message[0]; + erpnext.default_dimensions = r.message[1]; + } +}); + erpnext.doctypes_with_dimensions.forEach((doctype) => { frappe.ui.form.on(doctype, { onload: function(frm) { - frappe.boot.dimension_filters.forEach((dimension) => { + erpnext.dimension_filters.forEach((dimension) => { frappe.model.with_doctype(dimension['document_type'], () => { if (frappe.meta.has_field(dimension['document_type'], 'is_group')) { frm.set_query(dimension['fieldname'], { @@ -23,21 +31,21 @@ erpnext.doctypes_with_dimensions.forEach((doctype) => { company: function(frm) { if(frm.doc.company) { - frappe.boot.dimension_filters.forEach((dimension) => { - frm.set_value(dimension['fieldname'], frappe.boot.default_dimensions[frm.doc.company][dimension['document_type']]); + erpnext.dimension_filters.forEach((dimension) => { + frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]); }); } }, items_add: function(frm, cdt, cdn) { - frappe.boot.dimension_filters.forEach((dimension) => { + erpnext.dimension_filters.forEach((dimension) => { var row = frappe.get_doc(cdt, cdn); frm.script_manager.copy_from_first_row("items", row, [dimension['fieldname']]); }); }, accounts_add: function(frm, cdt, cdn) { - frappe.boot.dimension_filters.forEach((dimension) => { + erpnext.dimension_filters.forEach((dimension) => { var row = frappe.get_doc(cdt, cdn); frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]); }); diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py index 7d70cc2349..4ca43a89b8 100644 --- a/erpnext/startup/boot.py +++ b/erpnext/startup/boot.py @@ -39,8 +39,6 @@ def boot_session(bootinfo): party_account_types = frappe.db.sql(""" select name, ifnull(account_type, '') from `tabParty Type`""") bootinfo.party_account_types = frappe._dict(party_account_types) - load_dimension_filters(bootinfo) - load_default_dimensions(bootinfo) def load_country_and_currency(bootinfo): country = frappe.db.get_default("country") @@ -51,22 +49,6 @@ def load_country_and_currency(bootinfo): number_format, smallest_currency_fraction_value, symbol from tabCurrency where enabled=1""", as_dict=1, update={"doctype":":Currency"}) -def load_dimension_filters(bootinfo): - bootinfo.dimension_filters = frappe.db.sql(""" - SELECT label, fieldname, document_type - FROM `tabAccounting Dimension` - WHERE disabled = 0 - """, as_dict=1) - -def load_default_dimensions(bootinfo): - default_dimensions = frappe.db.sql("""SELECT parent, company, default_dimension - FROM `tabAccounting Dimension Detail`""", as_dict=1) - - bootinfo.default_dimensions = {} - for dimension in default_dimensions: - bootinfo.default_dimensions.setdefault(dimension['company'], {}) - bootinfo.default_dimensions[dimension['company']][dimension['parent']] = dimension['default_dimension'] - def update_page_info(bootinfo): bootinfo.page_info.update({ "Chart of Accounts": { From acc0958ead357df9bcc5691af386ccbea28d90d1 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 18 Jul 2019 18:14:12 +0530 Subject: [PATCH 055/124] fix: Patch --- .../v12_0/update_ewaybill_field_position.py | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/erpnext/patches/v12_0/update_ewaybill_field_position.py b/erpnext/patches/v12_0/update_ewaybill_field_position.py index d0291d2123..c0230c4395 100644 --- a/erpnext/patches/v12_0/update_ewaybill_field_position.py +++ b/erpnext/patches/v12_0/update_ewaybill_field_position.py @@ -10,18 +10,19 @@ def execute(): field = frappe.db.get_value("Custom Field", {"dt": "Sales Invoice", "fieldname": "ewaybill"}) - ewaybill_field = frappe.get_doc("Custom Field", field) + if field: + ewaybill_field = frappe.get_doc("Custom Field", field) - ewaybill_field.flags.ignore_validate = True + ewaybill_field.flags.ignore_validate = True - ewaybill_field.update({ - 'fieldname': 'ewaybill', - 'label': 'e-Way Bill No.', - 'fieldtype': 'Data', - 'depends_on': 'eval:(doc.docstatus === 1)', - 'allow_on_submit': 1, - 'insert_after': 'tax_id', - 'translatable': 0 - }) + ewaybill_field.update({ + 'fieldname': 'ewaybill', + 'label': 'e-Way Bill No.', + 'fieldtype': 'Data', + 'depends_on': 'eval:(doc.docstatus === 1)', + 'allow_on_submit': 1, + 'insert_after': 'tax_id', + 'translatable': 0 + }) - ewaybill_field.save() \ No newline at end of file + ewaybill_field.save() \ No newline at end of file From 22a4857a3c305c3f92a73be286ceaf9c1b34214a Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 18 Jul 2019 18:29:34 +0530 Subject: [PATCH 056/124] fix: Codacy Fixes --- .../doctype/accounting_dimension/accounting_dimension.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js index bb4d514981..d5f39b5cd3 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js @@ -63,4 +63,4 @@ frappe.ui.form.on('Accounting Dimension Detail', { let row = locals[cdt][cdn]; row.reference_document = frm.doc.document_type; } -}) \ No newline at end of file +}); \ No newline at end of file From 5dfe4df23b8dd282fdbda33ab7ce4ae4970bdf6a Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 20 Jul 2019 17:53:29 +0530 Subject: [PATCH 057/124] fix: Set query fix --- .../accounting_dimension/accounting_dimension.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js index d5f39b5cd3..88b11dd678 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js @@ -4,19 +4,19 @@ frappe.ui.form.on('Accounting Dimension', { refresh: function(frm) { + frm.set_query('document_type', () => { + return { + filters: { + name: ['not in', ['Accounting Dimension', 'Project', 'Cost Center', 'Accounting Dimension Detail']] + } + }; + }); + if (!frm.is_new()) { frm.add_custom_button(__('Show {0}', [frm.doc.document_type]), function () { frappe.set_route("List", frm.doc.document_type); }); - frm.set_query('document_type', () => { - return { - filters: { - name: ['not in', ['Accounting Dimension', 'Project', 'Cost Center']] - } - }; - }); - let button = frm.doc.disabled ? "Enable" : "Disable"; frm.add_custom_button(__(button), function() { From 1c1f6f90bb8280a92b5090954a1615ea08ee24c3 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 22 Jul 2019 12:41:48 +0530 Subject: [PATCH 058/124] fix: Test Cases for accounting dimensions --- .../test_accounting_dimension.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py index 527ddcc80f..7de7c108a2 100644 --- a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py @@ -28,11 +28,20 @@ class TestAccountingDimension(unittest.TestCase): "doctype": "Accounting Dimension", "document_type": "Location", "mandatory_for_pl": 1 - }).insert() + }) + + dimension1.append("dimension_defaults", { + "company": "_Test Company", + "reference_document": "Location", + "default_dimension": "Block 1", + "mandatory_for_pl": 1 + }) + + dimension1.insert() + dimension1.save() else: dimension1 = frappe.get_doc("Accounting Dimension", "Location") dimension1.disabled = 0 - dimension1.mandatory_for_pl = 1 dimension1.save() def test_dimension_against_sales_invoice(self): From 3d15128b91038b476fe1440e7ebd2f04ae61fc2a Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 23 Jul 2019 08:32:37 +0530 Subject: [PATCH 059/124] fix: Test cases for accounting dimensions --- .../doctype/accounting_dimension/test_accounting_dimension.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py index 7de7c108a2..c75ba825a4 100644 --- a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py @@ -27,14 +27,13 @@ class TestAccountingDimension(unittest.TestCase): dimension1 = frappe.get_doc({ "doctype": "Accounting Dimension", "document_type": "Location", - "mandatory_for_pl": 1 }) dimension1.append("dimension_defaults", { "company": "_Test Company", "reference_document": "Location", "default_dimension": "Block 1", - "mandatory_for_pl": 1 + "mandatory_for_bs": 1 }) dimension1.insert() From 82661372f72f1905380ffe06d6318b246a62a0e2 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Fri, 26 Jul 2019 09:12:30 +0530 Subject: [PATCH 060/124] fix: Add accounting dimensions to subscription and opening invoice tool --- .../accounting_dimension.py | 7 +- .../opening_invoice_creation_tool.json | 14 +- .../opening_invoice_creation_tool.py | 8 + .../opening_invoice_creation_tool_item.json | 15 +- .../doctype/subscription/subscription.json | 1099 ++++------------- .../doctype/subscription/subscription.py | 13 + .../subscription_plan/subscription_plan.json | 723 ++--------- erpnext/patches.txt | 1 + ...counting_dimensions_in_missing_doctypes.py | 38 + .../public/js/utils/dimension_tree_filter.js | 5 +- 10 files changed, 440 insertions(+), 1483 deletions(-) create mode 100644 erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index 90cc50d419..61f699f6ab 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -96,13 +96,13 @@ def delete_accounting_dimension(doc): frappe.db.sql(""" DELETE FROM `tabCustom Field` - WHERE fieldname = %s + WHERE fieldname = %s AND dt IN (%s)""" % #nosec ('%s', ', '.join(['%s']* len(doclist))), tuple([doc.fieldname] + doclist)) frappe.db.sql(""" DELETE FROM `tabProperty Setter` - WHERE field_name = %s + WHERE field_name = %s AND doc_type IN (%s)""" % #nosec ('%s', ', '.join(['%s']* len(doclist))), tuple([doc.fieldname] + doclist)) @@ -150,7 +150,8 @@ def get_doctypes_with_dimensions(): "Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item", "Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule", "Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation", - "Travel Request", "Fees", "POS Profile"] + "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item", "Subscription", + "Subscription Plan"] return doclist diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json index 7d2d5a11a8..bc9241802d 100644 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json +++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json @@ -10,7 +10,9 @@ "create_missing_party", "column_break_3", "invoice_type", + "accounting_dimensions_section", "cost_center", + "dimension_col_break", "section_break_4", "invoices" ], @@ -59,11 +61,21 @@ "fieldtype": "Link", "label": "Cost Center", "options": "Cost Center" + }, + { + "collapsible": 1, + "fieldname": "accounting_dimensions_section", + "fieldtype": "Section Break", + "label": "Accounting Dimensions" + }, + { + "fieldname": "dimension_col_break", + "fieldtype": "Column Break" } ], "hide_toolbar": 1, "issingle": 1, - "modified": "2019-06-13 11:45:31.405267", + "modified": "2019-07-25 14:57:33.187689", "modified_by": "Administrator", "module": "Accounts", "name": "Opening Invoice Creation Tool", diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py index 5fa7b48c09..ce8aba75b2 100644 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py +++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py @@ -7,6 +7,7 @@ import frappe from frappe import _, scrub from frappe.utils import flt, nowdate from frappe.model.document import Document +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions class OpeningInvoiceCreationTool(Document): @@ -173,6 +174,13 @@ class OpeningInvoiceCreationTool(Document): "currency": frappe.get_cached_value('Company', self.company, "default_currency") }) + accounting_dimension = get_accounting_dimensions() + + for dimension in accounting_dimension: + args.update({ + dimension: item.get(dimension) + }) + if self.invoice_type == "Sales": args["is_pos"] = 0 diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json b/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json index afa7229e53..4ce8cb95b1 100644 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json +++ b/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json @@ -15,7 +15,9 @@ "outstanding_amount", "column_break_4", "qty", - "cost_center" + "accounting_dimensions_section", + "cost_center", + "dimension_col_break" ], "fields": [ { @@ -92,10 +94,19 @@ "fieldtype": "Link", "label": "Cost Center", "options": "Cost Center" + }, + { + "fieldname": "accounting_dimensions_section", + "fieldtype": "Section Break", + "label": "Accounting Dimensions" + }, + { + "fieldname": "dimension_col_break", + "fieldtype": "Column Break" } ], "istable": 1, - "modified": "2019-06-13 11:48:08.324063", + "modified": "2019-07-25 15:00:00.460695", "modified_by": "Administrator", "module": "Accounts", "name": "Opening Invoice Creation Tool Item", diff --git a/erpnext/accounts/doctype/subscription/subscription.json b/erpnext/accounts/doctype/subscription/subscription.json index c9305164f0..29cb62a397 100644 --- a/erpnext/accounts/doctype/subscription/subscription.json +++ b/erpnext/accounts/doctype/subscription/subscription.json @@ -1,926 +1,245 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "ACC-SUB-.YYYY.-.#####", - "beta": 0, - "creation": "2017-07-18 17:50:43.967266", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "autoname": "ACC-SUB-.YYYY.-.#####", + "creation": "2017-07-18 17:50:43.967266", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "customer", + "cb_1", + "status", + "subscription_period", + "start", + "cancelation_date", + "trial_period_start", + "trial_period_end", + "column_break_11", + "current_invoice_start", + "current_invoice_end", + "days_until_due", + "cancel_at_period_end", + "generate_invoice_at_period_start", + "sb_4", + "plans", + "sb_1", + "tax_template", + "sb_2", + "apply_additional_discount", + "cb_2", + "additional_discount_percentage", + "additional_discount_amount", + "sb_3", + "invoices", + "accounting_dimensions_section", + "dimension_col_break" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "customer", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Customer", - "length": 0, - "no_copy": 0, - "options": "Customer", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 1, - "translatable": 0, - "unique": 0 - }, + "fieldname": "customer", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Customer", + "options": "Customer", + "reqd": 1, + "set_only_once": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cb_1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "cb_1", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Status", - "length": 0, - "no_copy": 0, - "options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "status", + "fieldtype": "Select", + "label": "Status", + "options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "subscription_period", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Subscription Period", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "subscription_period", + "fieldtype": "Section Break", + "label": "Subscription Period" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "start", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Subscription Start Date", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 1, - "translatable": 0, - "unique": 0 - }, + "fieldname": "start", + "fieldtype": "Date", + "label": "Subscription Start Date", + "set_only_once": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cancelation_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Cancelation Date", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "cancelation_date", + "fieldtype": "Date", + "label": "Cancelation Date", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "trial_period_start", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Trial Period Start Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 1, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "trial_period_start", + "fieldtype": "Date", + "label": "Trial Period Start Date", + "set_only_once": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.trial_period_start", - "fieldname": "trial_period_end", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Trial Period End Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 1, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.trial_period_start", + "fieldname": "trial_period_end", + "fieldtype": "Date", + "label": "Trial Period End Date", + "set_only_once": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_11", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_11", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "current_invoice_start", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Current Invoice Start Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "current_invoice_start", + "fieldtype": "Date", + "label": "Current Invoice Start Date", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "current_invoice_end", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Current Invoice End Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "current_invoice_end", + "fieldtype": "Date", + "label": "Current Invoice End Date", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "description": "Number of days that the subscriber has to pay invoices generated by this subscription", - "fieldname": "days_until_due", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Days Until Due", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "description": "Number of days that the subscriber has to pay invoices generated by this subscription", + "fieldname": "days_until_due", + "fieldtype": "Int", + "label": "Days Until Due" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cancel_at_period_end", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Cancel At End Of Period", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "cancel_at_period_end", + "fieldtype": "Check", + "label": "Cancel At End Of Period" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "generate_invoice_at_period_start", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Generate Invoice At Beginning Of Period", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "generate_invoice_at_period_start", + "fieldtype": "Check", + "label": "Generate Invoice At Beginning Of Period" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "sb_4", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Plans", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "sb_4", + "fieldtype": "Section Break", + "label": "Plans" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "plans", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Plans", - "length": 0, - "no_copy": 0, - "options": "Subscription Plan Detail", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "plans", + "fieldtype": "Table", + "label": "Plans", + "options": "Subscription Plan Detail", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sb_1", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Taxes", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "sb_1", + "fieldtype": "Section Break", + "label": "Taxes" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "tax_template", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Sales Taxes and Charges Template", - "length": 0, - "no_copy": 0, - "options": "Sales Taxes and Charges Template", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "tax_template", + "fieldtype": "Link", + "label": "Sales Taxes and Charges Template", + "options": "Sales Taxes and Charges Template" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "description": "", - "fieldname": "sb_2", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Discounts", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "sb_2", + "fieldtype": "Section Break", + "label": "Discounts" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "apply_additional_discount", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Apply Additional Discount On", - "length": 0, - "no_copy": 0, - "options": "\nGrand Total\nNet total", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "apply_additional_discount", + "fieldtype": "Select", + "label": "Apply Additional Discount On", + "options": "\nGrand Total\nNet total" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "cb_2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "cb_2", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "additional_discount_percentage", - "fieldtype": "Percent", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Additional DIscount Percentage", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "additional_discount_percentage", + "fieldtype": "Percent", + "label": "Additional DIscount Percentage" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "depends_on": "", - "fieldname": "additional_discount_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Additional DIscount Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "fieldname": "additional_discount_amount", + "fieldtype": "Currency", + "label": "Additional DIscount Amount" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "depends_on": "eval:doc.invoices", - "fieldname": "sb_3", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Invoices", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.invoices", + "fieldname": "sb_3", + "fieldtype": "Section Break", + "label": "Invoices" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "depends_on": "", - "fieldname": "invoices", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Invoices", - "length": 0, - "no_copy": 0, - "options": "Subscription Invoice", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "collapsible": 1, + "fieldname": "invoices", + "fieldtype": "Table", + "label": "Invoices", + "options": "Subscription Invoice" + }, + { + "collapsible": 1, + "fieldname": "accounting_dimensions_section", + "fieldtype": "Section Break", + "label": "Accounting Dimensions" + }, + { + "fieldname": "dimension_col_break", + "fieldtype": "Column Break" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-10-14 10:38:55.545540", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Subscription", - "name_case": "", - "owner": "Administrator", + ], + "modified": "2019-07-25 18:45:38.579579", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Subscription", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts User", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "share": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "share": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 -} + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 858359eccb..6d01897e8f 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -9,6 +9,7 @@ from frappe import _ from frappe.model.document import Document from frappe.utils.data import nowdate, getdate, cint, add_days, date_diff, get_last_day, add_to_date, flt from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions class Subscription(Document): @@ -241,6 +242,15 @@ class Subscription(Document): invoice.posting_date = self.current_invoice_start invoice.customer = self.customer + ## Add dimesnions in invoice for subscription: + accounting_dimensions = get_accounting_dimensions() + + for dimension in accounting_dimensions: + if self.get(dimension): + invoice.update({ + dimension: self.get(dimension) + }) + # Subscription is better suited for service items. I won't update `update_stock` # for that reason items_list = self.get_items_from_plans(self.plans, prorate) @@ -280,6 +290,9 @@ class Subscription(Document): invoice.save() invoice.submit() + for dimension in accounting_dimensions: + invoice.load_from_db() + return invoice def get_items_from_plans(self, plans, prorate=0): diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json index 453521d04d..9f79066235 100644 --- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json +++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json @@ -1,612 +1,163 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 1, - "autoname": "field:plan_name", - "beta": 0, - "creation": "2018-02-24 11:31:23.066506", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "allow_rename": 1, + "autoname": "field:plan_name", + "creation": "2018-02-24 11:31:23.066506", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "plan_name", + "currency", + "column_break_3", + "item", + "section_break_5", + "price_determination", + "column_break_7", + "cost", + "price_list", + "section_break_11", + "billing_interval", + "column_break_13", + "billing_interval_count", + "payment_plan_section", + "payment_plan_id", + "column_break_16", + "payment_gateway", + "accounting_dimensions_section", + "dimension_col_break" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "plan_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Plan Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "fieldname": "plan_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Plan Name", + "reqd": 1, "unique": 1 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "currency", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Currency", - "length": 0, - "no_copy": 0, - "options": "Currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "currency", + "fieldtype": "Link", + "label": "Currency", + "options": "Currency" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "item", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Item", - "length": 0, - "no_copy": 0, - "options": "Item", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "item", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item", + "options": "Item", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_5", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_5", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fieldname": "price_determination", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Price Determination", - "length": 0, - "no_copy": 0, - "options": "\nFixed rate\nBased on price list", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "price_determination", + "fieldtype": "Select", + "label": "Price Determination", + "options": "\nFixed rate\nBased on price list", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_7", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_7", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.price_determination==\"Fixed rate\"", - "fieldname": "cost", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Cost", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.price_determination==\"Fixed rate\"", + "fieldname": "cost", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Cost" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.price_determination==\"Based on price list\"", - "fieldname": "price_list", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Price List", - "length": 0, - "no_copy": 0, - "options": "Price List", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.price_determination==\"Based on price list\"", + "fieldname": "price_list", + "fieldtype": "Link", + "label": "Price List", + "options": "Price List" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_11", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_11", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Day", - "fieldname": "billing_interval", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Billing Interval", - "length": 0, - "no_copy": 0, - "options": "Day\nWeek\nMonth\nYear", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Day", + "fieldname": "billing_interval", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Billing Interval", + "options": "Day\nWeek\nMonth\nYear", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_13", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "1", - "description": "Number of intervals for the interval field e.g if Interval is 'Days' and Billing Interval Count is 3, invoices will be generated every 3 days", - "fieldname": "billing_interval_count", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Billing Interval Count", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "1", + "description": "Number of intervals for the interval field e.g if Interval is 'Days' and Billing Interval Count is 3, invoices will be generated every 3 days", + "fieldname": "billing_interval_count", + "fieldtype": "Int", + "label": "Billing Interval Count", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_plan_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Plan", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "payment_plan_section", + "fieldtype": "Section Break", + "label": "Payment Plan" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_plan_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Plan", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "payment_plan_id", + "fieldtype": "Data", + "label": "Payment Plan" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_16", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_16", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_gateway", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Gateway", - "length": 0, - "no_copy": 0, - "options": "Payment Gateway Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "payment_gateway", + "fieldtype": "Link", + "label": "Payment Gateway", + "options": "Payment Gateway Account" + }, + { + "collapsible": 1, + "fieldname": "accounting_dimensions_section", + "fieldtype": "Section Break", + "label": "Accounting Dimensions" + }, + { + "fieldname": "dimension_col_break", + "fieldtype": "Column Break" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-06-20 16:59:54.082358", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Subscription Plan", - "name_case": "", - "owner": "Administrator", + ], + "modified": "2019-07-25 18:35:04.362556", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Subscription Plan", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0 + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 398c6020a0..33d4f55ae0 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -624,4 +624,5 @@ erpnext.patches.v11_1.update_default_supplier_in_item_defaults erpnext.patches.v12_0.update_due_date_in_gle erpnext.patches.v12_0.add_default_buying_selling_terms_in_company erpnext.patches.v12_0.update_ewaybill_field_position +erpnext.patches.v12_0.create_accounting_dimensions_in_missing_doctypes erpnext.patches.v11_1.set_status_for_material_request_type_manufacture diff --git a/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py b/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py new file mode 100644 index 0000000000..1796c53c14 --- /dev/null +++ b/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py @@ -0,0 +1,38 @@ +from __future__ import unicode_literals +import frappe +from frappe.custom.doctype.custom_field.custom_field import create_custom_field + +def execute(): + accounting_dimensions = frappe.db.sql("""select fieldname, label, document_type, disabled from + `tabAccounting Dimension`""", as_dict=1) + + if not accounting_dimensions: + return + + count = 1 + for d in accounting_dimensions: + + if count%2 == 0: + insert_after_field = 'dimension_col_break' + else: + insert_after_field = 'accounting_dimensions_section' + + for doctype in ["Subscription Plan", "Subscription", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item"]: + + field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname}) + + if field: + continue + + df = { + "fieldname": d.fieldname, + "label": d.label, + "fieldtype": "Link", + "options": d.document_type, + "insert_after": insert_after_field + } + + create_custom_field(doctype, df) + frappe.clear_cache(doctype=doctype) + + count += 1 \ No newline at end of file diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js index 9d4c435240..10855ea3e6 100644 --- a/erpnext/public/js/utils/dimension_tree_filter.js +++ b/erpnext/public/js/utils/dimension_tree_filter.js @@ -5,7 +5,7 @@ erpnext.doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoi "Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item", "Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule", "Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation", - "Travel Request", "Fees", "POS Profile"]; + "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item"]; frappe.call({ method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimension_filters", @@ -25,6 +25,9 @@ erpnext.doctypes_with_dimensions.forEach((doctype) => { "is_group": 0 }); } + if (frm.is_new() && frappe.meta.has_field(doctype, 'company') && frm.doc.company) { + frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]); + } }); }); }, From 724be6eca27f167f872f19d777934d84503fb2ee Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 27 Jul 2019 19:06:36 +0530 Subject: [PATCH 061/124] fix: GL entry validation fix --- .../doctype/accounting_dimension/accounting_dimension.py | 5 +++-- .../accounting_dimension/test_accounting_dimension.py | 1 - erpnext/accounts/doctype/gl_entry/gl_entry.py | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index 61f699f6ab..1f418de47b 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -164,8 +164,9 @@ def get_accounting_dimensions(as_list=True): return accounting_dimensions def get_checks_for_pl_and_bs_accounts(): - dimensions = frappe.db.sql("""SELECT parent, company, mandatory_for_pl, mandatory_for_bs - FROM `tabAccounting Dimension Detail`""", as_dict=1) + dimensions = frappe.db.sql("""SELECT p.label, p.disabled, p.fieldname, c.company, c.mandatory_for_pl, c.mandatory_for_bs + FROM `tabAccounting Dimension`p ,`tabAccounting Dimension Detail` c + WHERE p.name = c.parent""", as_dict=1) return dimensions diff --git a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py index c75ba825a4..104880f6f3 100644 --- a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py @@ -108,7 +108,6 @@ def disable_dimension(): dimension1.save() dimension2 = frappe.get_doc("Accounting Dimension", "Location") - dimension2.mandatory_for_pl = 0 dimension2.disabled = 1 dimension2.save() diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 80e518644d..4944c8f76f 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -90,15 +90,15 @@ class GLEntry(Document): if account_type == "Profit and Loss" \ and self.company == dimension.company and dimension.mandatory_for_pl and not dimension.disabled: - if not self.get(frappe.scrub(dimension.parent)): + if not self.get(frappe.scrub(dimension.fieldname)): frappe.throw(_("Accounting Dimension {0} is required for 'Profit and Loss' account {1}.") - .format(dimension.parent, self.account)) + .format(dimension.label, self.account)) if account_type == "Balance Sheet" \ and self.company == dimension.company and dimension.mandatory_for_bs and not dimension.disabled: - if not self.get(frappe.scrub(dimension.parent)): + if not self.get(frappe.scrub(dimension.fieldname)): frappe.throw(_("Accounting Dimension {0} is required for 'Balance Sheet' account {1}.") - .format(dimension.parent, self.account)) + .format(dimension.label, self.account)) def check_pl_account(self): From d9f3ba5fdacbac81391b4051152bace359523d83 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 28 Jul 2019 10:30:32 +0530 Subject: [PATCH 062/124] fix: Reload doc in patch --- .../v12_0/create_accounting_dimensions_in_missing_doctypes.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py b/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py index 1796c53c14..b71ea66594 100644 --- a/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py +++ b/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py @@ -3,6 +3,9 @@ import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_field def execute(): + + frappe.reload_doc('accounts', 'doctype', 'accounting_dimension') + accounting_dimensions = frappe.db.sql("""select fieldname, label, document_type, disabled from `tabAccounting Dimension`""", as_dict=1) From f37fb82069b7bb244b62acd2da55f0bf605c2212 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 29 Jul 2019 08:58:56 +0530 Subject: [PATCH 063/124] fix: Code cleanup --- erpnext/accounts/doctype/gl_entry/gl_entry.py | 4 ++-- erpnext/accounts/doctype/subscription/subscription.py | 3 --- erpnext/public/js/utils/dimension_tree_filter.js | 3 ++- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 4944c8f76f..078e05816d 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -90,13 +90,13 @@ class GLEntry(Document): if account_type == "Profit and Loss" \ and self.company == dimension.company and dimension.mandatory_for_pl and not dimension.disabled: - if not self.get(frappe.scrub(dimension.fieldname)): + if not self.get(dimension.fieldname): frappe.throw(_("Accounting Dimension {0} is required for 'Profit and Loss' account {1}.") .format(dimension.label, self.account)) if account_type == "Balance Sheet" \ and self.company == dimension.company and dimension.mandatory_for_bs and not dimension.disabled: - if not self.get(frappe.scrub(dimension.fieldname)): + if not self.get(dimension.fieldname): frappe.throw(_("Accounting Dimension {0} is required for 'Balance Sheet' account {1}.") .format(dimension.label, self.account)) diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 6d01897e8f..f13ca4c49e 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -290,9 +290,6 @@ class Subscription(Document): invoice.save() invoice.submit() - for dimension in accounting_dimensions: - invoice.load_from_db() - return invoice def get_items_from_plans(self, plans, prorate=0): diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js index 10855ea3e6..f1c92091a8 100644 --- a/erpnext/public/js/utils/dimension_tree_filter.js +++ b/erpnext/public/js/utils/dimension_tree_filter.js @@ -5,7 +5,8 @@ erpnext.doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoi "Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item", "Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule", "Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation", - "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item"]; + "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item", "Subscription", + "Subscription Plan"]; frappe.call({ method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimension_filters", From 107c07e5cbb63aabf5f715f3fe00cd3e8e7721d5 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 29 Jul 2019 14:57:33 +0530 Subject: [PATCH 064/124] fix: Opening balance not getting calculated in trail_balance_report --- erpnext/accounts/report/trial_balance/trial_balance.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index b6ddaa8e85..10e977acbf 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -123,11 +123,12 @@ def get_rootwise_opening_balances(filters, report_type): if accounting_dimensions: for dimension in accounting_dimensions: - additional_conditions += """ and {0} in (%({0})s) """.format(dimension) + if filters.get(dimension): + additional_conditions += """ and {0} in (%({0})s) """.format(dimension) - query_filters.update({ - dimension: filters.get(dimension) - }) + query_filters.update({ + dimension: filters.get(dimension) + }) gle = frappe.db.sql(""" select From 40e35048b87234eb82409da09f164db30ec9bbd2 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 29 Jul 2019 17:14:39 +0530 Subject: [PATCH 065/124] fix: can't compare datetime.date to unicode --- erpnext/selling/doctype/quotation/quotation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index cc73e76bf3..46009f45e4 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -34,7 +34,7 @@ class Quotation(SellingController): self.with_items = 1 def validate_valid_till(self): - if self.valid_till and self.valid_till < self.transaction_date: + if self.valid_till and getdate(self.valid_till) < getdate(self.transaction_date): frappe.throw(_("Valid till date cannot be before transaction date")) def has_sales_order(self): From 403968b2f7f458e6ce7934f93b1b3bfbeaf6fe4a Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Tue, 30 Jul 2019 13:29:07 +0550 Subject: [PATCH 066/124] bumped to version 12.0.3 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 04f741e14b..5e2669368b 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '12.0.2' +__version__ = '12.0.3' def get_default_company(user=None): '''Get default company for user''' From 1214e2d2a41b2b69149b5b96afe7fad6fa24ec87 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 30 Jul 2019 16:52:24 +0530 Subject: [PATCH 067/124] feat: BOM Comparison Tool --- erpnext/manufacturing/doctype/bom/bom.py | 50 ++++ .../page/bom_comparison_tool/__init__.py | 0 .../bom_comparison_tool.js | 218 ++++++++++++++++++ .../bom_comparison_tool.json | 30 +++ 4 files changed, 298 insertions(+) create mode 100644 erpnext/manufacturing/page/bom_comparison_tool/__init__.py create mode 100644 erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js create mode 100644 erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.json diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index a7162933bf..22c2f694f5 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -9,6 +9,7 @@ from erpnext.setup.utils import get_exchange_rate from frappe.website.website_generator import WebsiteGenerator from erpnext.stock.get_item_details import get_conversion_factor from erpnext.stock.get_item_details import get_price_list_rate +from frappe.core.doctype.version.version import get_diff import functools @@ -763,3 +764,52 @@ def add_additional_cost(stock_entry, work_order): 'description': name[0], 'amount': items.get(name[0]) }) + +@frappe.whitelist() +def get_bom_diff(bom1, bom2): + from frappe.model import table_fields + + doc1 = frappe.get_doc('BOM', bom1) + doc2 = frappe.get_doc('BOM', bom2) + + out = get_diff(doc1, doc2) + out.row_changed = [] + out.added = [] + out.removed = [] + + meta = doc1.meta + + identifiers = { + 'operations': 'operation', + 'items': 'item_code', + 'scrap_items': 'item_code', + 'exploded_items': 'item_code' + } + + for df in meta.fields: + old_value, new_value = doc1.get(df.fieldname), doc2.get(df.fieldname) + + if df.fieldtype in table_fields: + identifier = identifiers[df.fieldname] + # make maps + old_row_by_identifier, new_row_by_identifier = {}, {} + for d in old_value: + old_row_by_identifier[d.get(identifier)] = d + for d in new_value: + new_row_by_identifier[d.get(identifier)] = d + + # check rows for additions, changes + for i, d in enumerate(new_value): + if d.get(identifier) in old_row_by_identifier: + diff = get_diff(old_row_by_identifier[d.get(identifier)], d, for_child=True) + if diff and diff.changed: + out.row_changed.append((df.fieldname, i, d.get(identifier), diff.changed)) + else: + out.added.append([df.fieldname, d.as_dict()]) + + # check for deletions + for d in old_value: + if not d.get(identifier) in new_row_by_identifier: + out.removed.append([df.fieldname, d.as_dict()]) + + return out diff --git a/erpnext/manufacturing/page/bom_comparison_tool/__init__.py b/erpnext/manufacturing/page/bom_comparison_tool/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js new file mode 100644 index 0000000000..eeecdf69ae --- /dev/null +++ b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js @@ -0,0 +1,218 @@ +frappe.pages['bom-comparison-tool'].on_page_load = function(wrapper) { + var page = frappe.ui.make_app_page({ + parent: wrapper, + title: __('BOM Comparison Tool'), + single_column: true + }); + + new erpnext.BOMComparisonTool(page); +} + +erpnext.BOMComparisonTool = class BOMComparisonTool { + constructor(page) { + this.page = page; + this.make_form(); + } + + make_form() { + this.form = new frappe.ui.FieldGroup({ + fields: [ + { + label: __('BOM 1'), + fieldname: 'name1', + fieldtype: 'Link', + options: 'BOM', + change: () => this.fetch_and_render() + }, + { + fieldtype: 'Column Break' + }, + { + label: __('BOM 2'), + fieldname: 'name2', + fieldtype: 'Link', + options: 'BOM', + change: () => this.fetch_and_render() + }, + { + fieldtype: 'Section Break' + }, + { + fieldtype: 'HTML', + fieldname: 'preview' + } + ], + body: this.page.body + }); + this.form.make(); + } + + fetch_and_render() { + let { name1, name2 } = this.form.get_values(); + if (!(name1 && name2)) { + this.form.get_field('preview').html(''); + return; + } + + // set working state + this.form.get_field('preview').html(` +
+ ${__("Fetching...")} +
+ `); + + frappe.call('erpnext.manufacturing.doctype.bom.bom.get_bom_diff', { + bom1: name1, + bom2: name2 + }).then(r => { + let diff = r.message; + frappe.model.with_doctype('BOM', () => { + this.render('BOM', name1, name2, diff); + }); + }); + } + + render(doctype, name1, name2, diff) { + + let change_html = (title, doctype, changed) => { + let values_changed = this.get_changed_values(doctype, changed) + .map(change => { + let [fieldname, value1, value2] = change; + return ` + + ${frappe.meta.get_label(doctype, fieldname)} + ${value1} + ${value2} + + `; + }) + .join(''); + + return ` +

${title}

+
+ + + + + + + ${values_changed} +
${__('Field')}${name1}${name2}
+
+ `; + } + + let value_changes = change_html(__('Values Changed'), doctype, diff.changed); + + let row_changes_by_fieldname = group_items(diff.row_changed, change => change[0]); + + let table_changes = Object.keys(row_changes_by_fieldname).map(fieldname => { + let changes = row_changes_by_fieldname[fieldname]; + let df = frappe.meta.get_docfield(doctype, fieldname); + + let html = changes.map(change => { + let [fieldname, idx, item_code, changes] = change; + let df = frappe.meta.get_docfield(doctype, fieldname); + let child_doctype = df.options; + let values_changed = this.get_changed_values(child_doctype, changes); + + return values_changed.map((change, i) => { + let [fieldname, value1, value2] = change; + return ` + + ${i === 0 + ? `${item_code}` + : ''} + ${frappe.meta.get_label(child_doctype, fieldname)} + ${value1} + ${value2} + + `; + }).join(''); + }).join(''); + + return ` +

${__('Changes in {0}', [df.label])}

+ + + + + + + + ${html} +
${__('Item Code')}${__('Field')}${name1}${name2}
+ `; + }).join(''); + + let get_added_removed_html = (title, grouped_items) => { + return Object.keys(grouped_items).map(fieldname => { + let rows = grouped_items[fieldname]; + let df = frappe.meta.get_docfield(doctype, fieldname); + let fields = frappe.meta.get_docfields(df.options) + .filter(df => df.in_list_view); + + let html = rows.map(row => { + let [, doc] = row; + return ` + + + ${fields.map(df => { + return `${doc[df.fieldname]}` + }).join('')} + + `; + }).join(''); + + return ` +

${$.format(title, [df.label])}

+ + ${fields.map(df => { + return `` + }).join('')} + + ${html} +
${df.label}
+ `; + }).join(''); + } + + let added_by_fieldname = group_items(diff.added, change => change[0]); + let removed_by_fieldname = group_items(diff.removed, change => change[0]); + + let added_html = get_added_removed_html(__('Rows Added in {0}'), added_by_fieldname); + let removed_html = get_added_removed_html(__('Rows Removed in {0}'), removed_by_fieldname); + + let html = ` + ${value_changes} + ${table_changes} + ${added_html} + ${removed_html} + `; + + this.form.get_field('preview').html(html); + } + + get_changed_values(doctype, changed) { + return changed.filter(change => { + let [fieldname, value1, value2] = change; + if (!value1) value1 = ''; + if (!value2) value2 = ''; + if (value1 === value2) return false; + let df = frappe.meta.get_docfield(doctype, fieldname); + if (!df) return false; + if (df.hidden) return false; + return true; + }); + } +} + +function group_items(array, fn) { + return array.reduce((acc, item) => { + let key = fn(item); + acc[key] = acc[key] || []; + acc[key].push(item); + return acc; + }, {}); +} diff --git a/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.json b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.json new file mode 100644 index 0000000000..067a1061b8 --- /dev/null +++ b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.json @@ -0,0 +1,30 @@ +{ + "content": null, + "creation": "2019-07-29 13:24:38.201981", + "docstatus": 0, + "doctype": "Page", + "idx": 0, + "modified": "2019-07-29 13:24:38.201981", + "modified_by": "Administrator", + "module": "Manufacturing", + "name": "bom-comparison-tool", + "owner": "Administrator", + "page_name": "BOM Comparison Tool", + "restrict_to_domain": "Manufacturing", + "roles": [ + { + "role": "System Manager" + }, + { + "role": "Manufacturing User" + }, + { + "role": "Manufacturing Manager" + } + ], + "script": null, + "standard": "Yes", + "style": null, + "system_page": 0, + "title": "BOM Comparison Tool" +} \ No newline at end of file From 66064c7827db557f208caca72f87d86c614c8d38 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 30 Jul 2019 17:11:18 +0530 Subject: [PATCH 068/124] fix: Add BOM Comparison Tool to module view --- erpnext/config/manufacturing.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/erpnext/config/manufacturing.py b/erpnext/config/manufacturing.py index c79c5b8b11..2c18eeb83a 100644 --- a/erpnext/config/manufacturing.py +++ b/erpnext/config/manufacturing.py @@ -94,6 +94,13 @@ def get_data(): "name": "BOM Update Tool", "description": _("Replace BOM and update latest price in all BOMs"), }, + { + "type": "page", + "label": _("BOM Comparison Tool"), + "name": "bom-comparison-tool", + "description": _("Compare BOMs for changes in Raw Materials and Operations"), + "data_doctype": "BOM" + }, ] }, { From a4ada938345b8a2e824d278124c3b0ba52d60f96 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 30 Jul 2019 17:11:34 +0530 Subject: [PATCH 069/124] fix: Field labels --- erpnext/manufacturing/doctype/bom/bom.json | 2458 ++++---------------- 1 file changed, 459 insertions(+), 1999 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.json b/erpnext/manufacturing/doctype/bom/bom.json index 7865a2476f..a0faeb5fb5 100644 --- a/erpnext/manufacturing/doctype/bom/bom.json +++ b/erpnext/manufacturing/doctype/bom/bom.json @@ -1,2068 +1,528 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 0, - "beta": 0, - "creation": "2013-01-22 15:11:38", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 0, + "allow_import": 1, + "creation": "2013-01-22 15:11:38", + "doctype": "DocType", + "document_type": "Setup", + "field_order": [ + "item", + "item_name", + "image", + "uom", + "quantity", + "cb0", + "is_active", + "is_default", + "with_operations", + "inspection_required", + "allow_alternative_item", + "allow_same_item_multiple_times", + "set_rate_of_sub_assembly_item_based_on_bom", + "quality_inspection_template", + "currency_detail", + "company", + "transfer_material_against", + "conversion_rate", + "column_break_12", + "currency", + "rm_cost_as_per", + "buying_price_list", + "operations_section", + "routing", + "operations", + "materials_section", + "items", + "scrap_section", + "scrap_items", + "costing", + "operating_cost", + "raw_material_cost", + "scrap_material_cost", + "cb1", + "base_operating_cost", + "base_raw_material_cost", + "base_scrap_material_cost", + "total_cost_of_bom", + "total_cost", + "column_break_26", + "base_total_cost", + "more_info_section", + "project", + "amended_from", + "col_break23", + "section_break_25", + "description", + "column_break_27", + "section_break0", + "exploded_items", + "website_section", + "show_in_website", + "route", + "website_image", + "thumbnail", + "sb_web_spec", + "web_long_description", + "show_items", + "show_operations" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Item to be manufactured or repacked", - "fetch_if_empty": 0, - "fieldname": "item", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Item", - "length": 0, - "no_copy": 0, - "oldfieldname": "item", - "oldfieldtype": "Link", - "options": "Item", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "description": "Item to be manufactured or repacked", + "fieldname": "item", + "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Item", + "oldfieldname": "item", + "oldfieldtype": "Link", + "options": "Item", + "reqd": 1, + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_from": "item.item_name", - "fetch_if_empty": 0, - "fieldname": "item_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Item Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "item.item_name", + "fieldname": "item_name", + "fieldtype": "Data", + "in_global_search": 1, + "label": "Item Name", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "item.image", - "fetch_if_empty": 0, - "fieldname": "image", - "fieldtype": "Attach Image", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Image", - "length": 0, - "no_copy": 0, - "options": "image", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "item.image", + "fieldname": "image", + "fieldtype": "Attach Image", + "hidden": 1, + "label": "Image", + "options": "image", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "item.stock_uom", - "fetch_if_empty": 0, - "fieldname": "uom", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Item UOM", - "length": 0, - "no_copy": 0, - "options": "UOM", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "item.stock_uom", + "fieldname": "uom", + "fieldtype": "Link", + "label": "Item UOM", + "options": "UOM", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "1", - "description": "Quantity of item obtained after manufacturing / repacking from given quantities of raw materials", - "fetch_if_empty": 0, - "fieldname": "quantity", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Quantity", - "length": 0, - "no_copy": 0, - "oldfieldname": "quantity", - "oldfieldtype": "Currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "1", + "description": "Quantity of item obtained after manufacturing / repacking from given quantities of raw materials", + "fieldname": "quantity", + "fieldtype": "Float", + "label": "Quantity", + "oldfieldname": "quantity", + "oldfieldtype": "Currency", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "cb0", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "cb0", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "1", - "fetch_if_empty": 0, - "fieldname": "is_active", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Is Active", - "length": 0, - "no_copy": 1, - "oldfieldname": "is_active", - "oldfieldtype": "Select", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "default": "1", + "fieldname": "is_active", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Is Active", + "no_copy": 1, + "oldfieldname": "is_active", + "oldfieldtype": "Select" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "1", - "fetch_if_empty": 0, - "fieldname": "is_default", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Is Default", - "length": 0, - "no_copy": 1, - "oldfieldname": "is_default", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "default": "1", + "fieldname": "is_default", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Is Default", + "no_copy": 1, + "oldfieldname": "is_default", + "oldfieldtype": "Check" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Manage cost of operations", - "fetch_if_empty": 0, - "fieldname": "with_operations", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "With Operations", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "description": "Manage cost of operations", + "fieldname": "with_operations", + "fieldtype": "Check", + "ignore_user_permissions": 1, + "label": "With Operations" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "inspection_required", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Inspection Required", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "inspection_required", + "fieldtype": "Check", + "label": "Inspection Required" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "allow_alternative_item", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Allow Alternative Item", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "allow_alternative_item", + "fieldtype": "Check", + "label": "Allow Alternative Item" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "allow_same_item_multiple_times", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Allow Same Item Multiple Times", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "allow_same_item_multiple_times", + "fieldtype": "Check", + "label": "Allow Same Item Multiple Times" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "1", - "fetch_if_empty": 0, - "fieldname": "set_rate_of_sub_assembly_item_based_on_bom", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Set rate of sub-assembly item based on BOM", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "default": "1", + "fieldname": "set_rate_of_sub_assembly_item_based_on_bom", + "fieldtype": "Check", + "label": "Set rate of sub-assembly item based on BOM" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "inspection_required", - "fetch_if_empty": 0, - "fieldname": "quality_inspection_template", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Quality Inspection Template", - "length": 0, - "no_copy": 0, - "options": "Quality Inspection Template", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "inspection_required", + "fieldname": "quality_inspection_template", + "fieldtype": "Link", + "label": "Quality Inspection Template", + "options": "Quality Inspection Template" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "currency_detail", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "currency_detail", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 1, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company", + "remember_last_selected_value": 1, + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fetch_if_empty": 0, - "fieldname": "transfer_material_against", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Transfer Material Against", - "length": 0, - "no_copy": 0, - "options": "\nWork Order\nJob Card", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "transfer_material_against", + "fieldtype": "Select", + "label": "Transfer Material Against", + "options": "\nWork Order\nJob Card" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "conversion_rate", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Conversion Rate", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "9", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "conversion_rate", + "fieldtype": "Float", + "label": "Conversion Rate", + "precision": "9", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "column_break_12", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_12", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "currency", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Currency", - "length": 0, - "no_copy": 0, - "options": "Currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "currency", + "fieldtype": "Link", + "label": "Currency", + "options": "Currency", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Valuation Rate", - "fetch_if_empty": 0, - "fieldname": "rm_cost_as_per", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Rate Of Materials Based On", - "length": 0, - "no_copy": 0, - "options": "Valuation Rate\nLast Purchase Rate\nPrice List", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "default": "Valuation Rate", + "fieldname": "rm_cost_as_per", + "fieldtype": "Select", + "label": "Rate Of Materials Based On", + "options": "Valuation Rate\nLast Purchase Rate\nPrice List" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.rm_cost_as_per===\"Price List\"", - "fetch_if_empty": 0, - "fieldname": "buying_price_list", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Price List", - "length": 0, - "no_copy": 0, - "options": "Price List", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "depends_on": "eval:doc.rm_cost_as_per===\"Price List\"", + "fieldname": "buying_price_list", + "fieldtype": "Link", + "label": "Price List", + "options": "Price List" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "description": "", - "fetch_if_empty": 0, - "fieldname": "operations_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Operations", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "operations_section", + "fieldtype": "Section Break", + "label": "Operations", + "oldfieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "routing", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Routing", - "length": 0, - "no_copy": 0, - "options": "Routing", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "routing", + "fieldtype": "Link", + "label": "Routing", + "options": "Routing" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "operations", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Operations", - "length": 0, - "no_copy": 0, - "oldfieldname": "bom_operations", - "oldfieldtype": "Table", - "options": "BOM Operation", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "operations", + "fieldtype": "Table", + "label": "Operations", + "oldfieldname": "bom_operations", + "oldfieldtype": "Table", + "options": "BOM Operation" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "materials_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Materials", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "materials_section", + "fieldtype": "Section Break", + "label": "Materials", + "oldfieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "items", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Items", - "length": 0, - "no_copy": 0, - "oldfieldname": "bom_materials", - "oldfieldtype": "Table", - "options": "BOM Item", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "items", + "fieldtype": "Table", + "label": "Items", + "oldfieldname": "bom_materials", + "oldfieldtype": "Table", + "options": "BOM Item", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "scrap_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Scrap", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "fieldname": "scrap_section", + "fieldtype": "Section Break", + "label": "Scrap" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "scrap_items", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Scrap Items", - "length": 0, - "no_copy": 0, - "options": "BOM Scrap Item", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "scrap_items", + "fieldtype": "Table", + "label": "Scrap Items", + "options": "BOM Scrap Item" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "costing", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Costing", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "costing", + "fieldtype": "Section Break", + "label": "Costing", + "oldfieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "operating_cost", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Operating Cost", - "length": 0, - "no_copy": 0, - "options": "currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "operating_cost", + "fieldtype": "Currency", + "label": "Operating Cost", + "options": "currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "raw_material_cost", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Raw Material Cost", - "length": 0, - "no_copy": 0, - "options": "currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "raw_material_cost", + "fieldtype": "Currency", + "label": "Raw Material Cost", + "options": "currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "scrap_material_cost", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Scrap Material Cost", - "length": 0, - "no_copy": 0, - "options": "currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "scrap_material_cost", + "fieldtype": "Currency", + "label": "Scrap Material Cost", + "options": "currency", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "cb1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "cb1", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "base_operating_cost", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Operating Cost (Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "base_operating_cost", + "fieldtype": "Currency", + "label": "Operating Cost (Company Currency)", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "base_raw_material_cost", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Raw Material Cost(Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "base_raw_material_cost", + "fieldtype": "Currency", + "label": "Raw Material Cost (Company Currency)", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "base_scrap_material_cost", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Scrap Material Cost(Company Currency)", - "length": 0, - "no_copy": 1, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "base_scrap_material_cost", + "fieldtype": "Data", + "label": "Scrap Material Cost(Company Currency)", + "no_copy": 1, + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "total_cost_of_bom", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "total_cost_of_bom", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "total_cost", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Total Cost", - "length": 0, - "no_copy": 0, - "options": "currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "total_cost", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Total Cost", + "options": "currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "column_break_26", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_26", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "base_total_cost", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Total Cost(Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "base_total_cost", + "fieldtype": "Currency", + "label": "Total Cost (Company Currency)", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "more_info_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "more_info_section", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "project", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Project", - "length": 0, - "no_copy": 0, - "oldfieldname": "project", - "oldfieldtype": "Link", - "options": "Project", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "project", + "fieldtype": "Link", + "label": "Project", + "oldfieldname": "project", + "oldfieldtype": "Link", + "options": "Project" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "amended_from", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amended From", - "length": 0, - "no_copy": 1, - "options": "BOM", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "amended_from", + "fieldtype": "Link", + "ignore_user_permissions": 1, + "label": "Amended From", + "no_copy": 1, + "options": "BOM", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "col_break23", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "col_break23", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "section_break_25", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_25", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "item.description", - "fetch_if_empty": 0, - "fieldname": "description", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Item Description", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "item.description", + "fieldname": "description", + "fieldtype": "Small Text", + "label": "Item Description", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "column_break_27", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_27", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.__islocal", - "fetch_if_empty": 0, - "fieldname": "section_break0", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Materials Required (Exploded)", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:!doc.__islocal", + "fieldname": "section_break0", + "fieldtype": "Section Break", + "label": "Materials Required (Exploded)" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "exploded_items", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Exploded_items", - "length": 0, - "no_copy": 1, - "oldfieldname": "flat_bom_details", - "oldfieldtype": "Table", - "options": "BOM Explosion Item", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "exploded_items", + "fieldtype": "Table", + "label": "Exploded Items", + "no_copy": 1, + "oldfieldname": "flat_bom_details", + "oldfieldtype": "Table", + "options": "BOM Explosion Item", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "website_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Website", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "fieldname": "website_section", + "fieldtype": "Section Break", + "label": "Website" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, - "fieldname": "show_in_website", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Show in Website", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "default": "0", + "fieldname": "show_in_website", + "fieldtype": "Check", + "label": "Show in Website" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "route", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Route", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "route", + "fieldtype": "Small Text", + "label": "Route" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "show_in_website", - "description": "Item Image (if not slideshow)", - "fetch_if_empty": 0, - "fieldname": "website_image", - "fieldtype": "Attach Image", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Image", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "depends_on": "show_in_website", + "description": "Item Image (if not slideshow)", + "fieldname": "website_image", + "fieldtype": "Attach Image", + "label": "Image" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "thumbnail", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Thumbnail", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "thumbnail", + "fieldtype": "Data", + "label": "Thumbnail", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "collapsible_depends_on": "website_items", - "columns": 0, - "depends_on": "show_in_website", - "fetch_if_empty": 0, - "fieldname": "sb_web_spec", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Website Specifications", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "collapsible_depends_on": "website_items", + "depends_on": "show_in_website", + "fieldname": "sb_web_spec", + "fieldtype": "Section Break", + "label": "Website Specifications" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "show_in_website", - "fetch_if_empty": 0, - "fieldname": "web_long_description", - "fieldtype": "Text Editor", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Website Description", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "depends_on": "show_in_website", + "fieldname": "web_long_description", + "fieldtype": "Text Editor", + "label": "Website Description" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "show_in_website", - "fetch_if_empty": 0, - "fieldname": "show_items", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Show Items", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "default": "0", + "depends_on": "show_in_website", + "fieldname": "show_items", + "fieldtype": "Check", + "label": "Show Items" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:(doc.show_in_website && doc.with_operations)", - "fetch_if_empty": 0, - "fieldname": "show_operations", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Show Operations", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "allow_on_submit": 1, + "default": "0", + "depends_on": "eval:(doc.show_in_website && doc.with_operations)", + "fieldname": "show_operations", + "fieldtype": "Check", + "label": "Show Operations" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-sitemap", - "idx": 1, - "image_field": "image", - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-05-01 16:36:05.197126", - "modified_by": "Administrator", - "module": "Manufacturing", - "name": "BOM", - "owner": "Administrator", + ], + "icon": "fa fa-sitemap", + "idx": 1, + "image_field": "image", + "is_submittable": 1, + "modified": "2019-07-30 17:00:09.665068", + "modified_by": "Administrator", + "module": "Manufacturing", + "name": "BOM", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Manufacturing Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Manufacturing Manager", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Manufacturing User", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Manufacturing User", + "share": 1, + "submit": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "item, item_name", - "show_name_in_global_search": 1, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "search_fields": "item, item_name", + "show_name_in_global_search": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file From f650cb8e4bdbfc34210cb624eabc1b93deca8ced Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 30 Jul 2019 17:46:15 +0530 Subject: [PATCH 070/124] style: Indent and missing semicolon --- .../bom_comparison_tool.js | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js index eeecdf69ae..11648226a8 100644 --- a/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js +++ b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js @@ -112,18 +112,19 @@ erpnext.BOMComparisonTool = class BOMComparisonTool { let df = frappe.meta.get_docfield(doctype, fieldname); let html = changes.map(change => { - let [fieldname, idx, item_code, changes] = change; + let [fieldname,, item_code, changes] = change; let df = frappe.meta.get_docfield(doctype, fieldname); let child_doctype = df.options; let values_changed = this.get_changed_values(child_doctype, changes); return values_changed.map((change, i) => { let [fieldname, value1, value2] = change; + let th = i === 0 + ? `${item_code}` + : ''; return ` - ${i === 0 - ? `${item_code}` - : ''} + ${th} ${frappe.meta.get_label(child_doctype, fieldname)} ${value1} ${value2} @@ -155,23 +156,17 @@ erpnext.BOMComparisonTool = class BOMComparisonTool { let html = rows.map(row => { let [, doc] = row; - return ` - - - ${fields.map(df => { - return `${doc[df.fieldname]}` - }).join('')} - - `; + let cells = fields + .map(df => `${doc[df.fieldname]}`) + .join(''); + return `${cells}`; }).join(''); + let header = fields.map(df => `${df.label}`).join(''); return `

${$.format(title, [df.label])}

- ${fields.map(df => { - return `` - }).join('')} - + ${header} ${html}
${df.label}
`; @@ -206,7 +201,7 @@ erpnext.BOMComparisonTool = class BOMComparisonTool { return true; }); } -} +}; function group_items(array, fn) { return array.reduce((acc, item) => { From 548293ad0893560c41acd5bbf22d37b1a8e4941f Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 30 Jul 2019 18:49:19 +0530 Subject: [PATCH 071/124] fix: Check zero valuation rate only for valid doctypes --- erpnext/stock/stock_ledger.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index ff5b026695..5fda2a4007 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -363,8 +363,17 @@ class update_entries_after(object): self.stock_queue.append([0, sle.incoming_rate or sle.outgoing_rate or self.valuation_rate]) def check_if_allow_zero_valuation_rate(self, voucher_type, voucher_detail_no): - ref_item_dt = voucher_type + (" Detail" if voucher_type == "Stock Entry" else " Item") - return frappe.db.get_value(ref_item_dt, voucher_detail_no, "allow_zero_valuation_rate") + ref_item_dt = "" + + if voucher_type == "Stock Entry": + ref_item_dt = voucher_type + " Detail" + elif voucher_type in ["Purchase Invoice", "Sales Invoice", "Delivery Note", "Purchase Receipt"]: + ref_item_dt = voucher_type + " Item" + + if ref_item_dt: + return frappe.db.get_value(ref_item_dt, voucher_detail_no, "allow_zero_valuation_rate") + else: + return 0 def get_sle_before_datetime(self): """get previous stock ledger entry before current time-bucket""" From 862363521bfc898b7fd2a724827354de4add5013 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 23 Jul 2019 16:05:29 +0530 Subject: [PATCH 072/124] fix: scrap item not adding while doing finished good entry --- erpnext/stock/doctype/stock_entry/stock_entry.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index f40560a57f..b5303327f6 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -802,13 +802,13 @@ class StockEntry(StockController): self.add_to_stock_entry_detail(item_dict) - if self.purpose != "Send to Subcontractor": - scrap_item_dict = self.get_bom_scrap_material(self.fg_completed_qty) - for item in itervalues(scrap_item_dict): - if self.pro_doc and self.pro_doc.scrap_warehouse: - item["to_warehouse"] = self.pro_doc.scrap_warehouse + if self.purpose != "Send to Subcontractor" and self.purpose == "Manufacture": + scrap_item_dict = self.get_bom_scrap_material(self.fg_completed_qty) + for item in itervalues(scrap_item_dict): + if self.pro_doc and self.pro_doc.scrap_warehouse: + item["to_warehouse"] = self.pro_doc.scrap_warehouse - self.add_to_stock_entry_detail(scrap_item_dict, bom_no=self.bom_no) + self.add_to_stock_entry_detail(scrap_item_dict, bom_no=self.bom_no) # fetch the serial_no of the first stock entry for the second stock entry if self.work_order and self.purpose == "Manufacture": From b65c761b16f65a8c29b88e106f672ac1363d54ac Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Wed, 31 Jul 2019 15:58:01 +0530 Subject: [PATCH 073/124] fix: Enhancement in credit note (#18510) * fix: Credit note enhancement * Fix: Print format for Sales Invoice Return * fix: Zero quantity validation fix for credit note --- .../doctype/sales_invoice/sales_invoice.js | 14 +- .../sales_invoice_return/__init__.py | 0 .../sales_invoice_return.html | 129 ++++++++++++++++++ .../sales_invoice_return.json | 24 ++++ erpnext/controllers/accounts_controller.py | 4 +- erpnext/controllers/taxes_and_totals.py | 7 +- .../public/js/controllers/taxes_and_totals.js | 8 +- 7 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 erpnext/accounts/print_format/sales_invoice_return/__init__.py create mode 100644 erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html create mode 100644 erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 1fe6895601..74e9186e37 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -44,6 +44,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte this.frm.toggle_reqd("due_date", !this.frm.doc.is_return); + if (this.frm.doc.is_return) { + this.frm.return_print_format = "Sales Invoice Return"; + } + this.show_general_ledger(); if(doc.update_stock) this.show_stock_ledger(); @@ -148,16 +152,24 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte }, set_default_print_format: function() { - // set default print format to POS type + // set default print format to POS type or Credit Note if(cur_frm.doc.is_pos) { if(cur_frm.pos_print_format) { cur_frm.meta._default_print_format = cur_frm.meta.default_print_format; cur_frm.meta.default_print_format = cur_frm.pos_print_format; } + } else if(cur_frm.doc.is_return) { + if(cur_frm.return_print_format) { + cur_frm.meta._default_print_format = cur_frm.meta.default_print_format; + cur_frm.meta.default_print_format = cur_frm.return_print_format; + } } else { if(cur_frm.meta._default_print_format) { cur_frm.meta.default_print_format = cur_frm.meta._default_print_format; cur_frm.meta._default_print_format = null; + } else if(in_list([cur_frm.pos_print_format, cur_frm.return_print_format], cur_frm.meta.default_print_format)) { + cur_frm.meta.default_print_format = null; + cur_frm.meta._default_print_format = null; } } }, diff --git a/erpnext/accounts/print_format/sales_invoice_return/__init__.py b/erpnext/accounts/print_format/sales_invoice_return/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html new file mode 100644 index 0000000000..889b7f71aa --- /dev/null +++ b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html @@ -0,0 +1,129 @@ +{%- from "templates/print_formats/standard_macros.html" import add_header, render_field, print_value, fieldmeta, + get_width, get_align_class -%} + +{%- macro render_currency(df, doc) -%} +
+
+ +
+
+ {% if doc.get(df.fieldname) != None -%} + {{ frappe.utils.fmt_money((doc[df.fieldname])|int|abs, currency=doc.currency) }} + {% endif %} +
+
+{%- endmacro -%} + +{%- macro render_taxes(df, doc) -%} + {%- set data = doc.get(df.fieldname)[df.start:df.end] -%} +
+
+
+ {%- for charge in data -%} + {%- if (charge.tax_amount or doc.flags.print_taxes_with_zero_amount) and (not charge.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%} +
+
+
+
+ {{ frappe.utils.fmt_money((charge.tax_amount)|int|abs, currency=doc.currency) }} +
+
+ {%- endif -%} + {%- endfor -%} +
+
+{%- endmacro -%} + +{%- macro render_table(df, doc) -%} + {%- set table_meta = frappe.get_meta(df.options) -%} + {%- set data = doc.get(df.fieldname)[df.start:df.end] -%} + {%- if doc.print_templates and + doc.print_templates.get(df.fieldname) -%} + {% include doc.print_templates[df.fieldname] %} + {%- else -%} + {%- if data -%} + {%- set visible_columns = get_visible_columns(doc.get(df.fieldname), + table_meta, df) -%} +
+ + + + + {% for tdf in visible_columns %} + {% if (data and not data[0].flags.compact_item_print) or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %} + + {% endif %} + {% endfor %} + + + + {% for d in data %} + + + {% for tdf in visible_columns %} + {% if not d.flags.compact_item_print or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %} + + {% else %} +
{{ print_value(tdf, d, doc, visible_columns) }}
+ {% endif %} + {% endif %} + {% endfor %} + + {% endfor %} + +
{{ _("Sr") }} + {{ _(tdf.label) }}
{{ d.idx }} + {% if tdf.fieldtype == 'Currency' %} +
{{ frappe.utils.fmt_money((d[tdf.fieldname])|int|abs, currency=doc.currency) }}
+
+ {%- endif -%} + {%- endif -%} +{%- endmacro -%} + +{% for page in layout %} +
+
+ {{ add_header(loop.index, layout|len, doc, letter_head, no_letterhead, footer, print_settings) }} +
+ + {% if print_settings.repeat_header_footer %} + + {% endif %} + + {% for section in page %} +
+ {% if section.columns.fields %} + {%- if doc._line_breaks and loop.index != 1 -%}
{%- endif -%} + {%- if doc._show_section_headings and section.label and section.has_data -%} +

{{ _(section.label) }}

+ {% endif %} + {%- endif -%} + {% for column in section.columns %} +
+ {% for df in column.fields %} + {% if df.fieldname == 'taxes' %} + {{ render_taxes(df, doc) }} + {% elif df.fieldtype == 'Currency' %} + {{ render_currency(df, doc) }} + {% elif df.fieldtype =='Table' %} + {{ render_table(df, doc)}} + {% elif doc[df.fieldname] %} + {{ render_field(df, doc) }} + {% endif %} + {% endfor %} +
+ {% endfor %} +
+ {% endfor %} +
+{% endfor %} diff --git a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json new file mode 100644 index 0000000000..352b5498e6 --- /dev/null +++ b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json @@ -0,0 +1,24 @@ +{ + "align_labels_right": 1, + "creation": "2019-07-24 20:13:30.259953", + "custom_format": 0, + "default_print_language": "en-US", + "disabled": 0, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype": "Print Format", + "font": "Default", + "html": "", + "idx": 0, + "line_breaks": 1, + "modified": "2019-07-24 20:13:30.259953", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Sales Invoice Return", + "owner": "Administrator", + "print_format_builder": 0, + "print_format_type": "Jinja", + "raw_printing": 0, + "show_section_headings": 1, + "standard": "Yes" +} \ No newline at end of file diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index ca59a396b8..288aa082c5 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -60,7 +60,9 @@ class AccountsController(TransactionBase): def validate(self): - self.validate_qty_is_not_zero() + if not self.get('is_return'): + self.validate_qty_is_not_zero() + if self.get("_action") and self._action != "update_after_submit": self.set_missing_values(for_validate=True) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 8d24e7a316..b774037266 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -81,7 +81,12 @@ class calculate_taxes_and_totals(object): item.discount_amount = item.price_list_rate - item.rate item.net_rate = item.rate - item.amount = flt(item.rate * item.qty, item.precision("amount")) + + if not item.qty and self.doc.is_return: + item.amount = flt(-1 * item.rate, item.precision("amount")) + else: + item.amount = flt(item.rate * item.qty, item.precision("amount")) + item.net_amount = item.amount self._set_in_company_currency(item, ["price_list_rate", "rate", "net_rate", "amount", "net_amount"]) diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 91800cd9a9..7cf2181e42 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -92,7 +92,13 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ $.each(this.frm.doc["items"] || [], function(i, item) { frappe.model.round_floats_in(item); item.net_rate = item.rate; - item.amount = flt(item.rate * item.qty, precision("amount", item)); + + if ((!item.qty) && me.frm.doc.is_return) { + item.amount = flt(item.rate * -1, precision("amount", item)); + } else { + item.amount = flt(item.rate * item.qty, precision("amount", item)); + } + item.net_amount = item.amount; item.item_tax_amount = 0.0; item.total_weight = flt(item.weight_per_unit * item.stock_qty); From d9e482759c31a09ec55c16506937c470b137148a Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Thu, 1 Aug 2019 12:53:19 +0530 Subject: [PATCH 074/124] style: Missing semicolon --- .../page/bom_comparison_tool/bom_comparison_tool.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js index 11648226a8..7152d3dff6 100644 --- a/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js +++ b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js @@ -171,7 +171,7 @@ erpnext.BOMComparisonTool = class BOMComparisonTool { `; }).join(''); - } + }; let added_by_fieldname = group_items(diff.added, change => change[0]); let removed_by_fieldname = group_items(diff.removed, change => change[0]); From c16ef32b6bf874d8d16f21ed11172032a9b59c2c Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 1 Aug 2019 13:24:48 +0530 Subject: [PATCH 075/124] fix: Payment Order link fix in bank dashboard --- erpnext/accounts/doctype/bank/bank_dashboard.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/accounts/doctype/bank/bank_dashboard.py b/erpnext/accounts/doctype/bank/bank_dashboard.py index 432404155d..e047b9aad0 100644 --- a/erpnext/accounts/doctype/bank/bank_dashboard.py +++ b/erpnext/accounts/doctype/bank/bank_dashboard.py @@ -6,6 +6,9 @@ from frappe import _ def get_data(): return { 'fieldname': 'bank', + 'non_standard_fieldnames': { + 'Paymnet Order': 'company_bank' + }, 'transactions': [ { 'label': _('Bank Deatils'), From 0313dc0f8cc07f1ba548495a1cb8ec0d8a429a39 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 2 Aug 2019 14:12:36 +0530 Subject: [PATCH 076/124] fix: task not updated issue --- erpnext/projects/doctype/task/task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 50557f1551..492eabe89e 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -145,7 +145,7 @@ class Task(NestedSet): def populate_depends_on(self): if self.parent_task: - parent = frappe.get_cached_doc('Task', self.parent_task) + parent = frappe.get_doc('Task', self.parent_task) if not self.name in [row.task for row in parent.depends_on]: parent.append("depends_on", { "doctype": "Task Depends On", From 968da1cd21e0b19a85b60e2b3b7bd494a51ab597 Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Fri, 2 Aug 2019 14:47:59 +0550 Subject: [PATCH 077/124] bumped to version 12.0.4 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 5e2669368b..260478f730 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '12.0.3' +__version__ = '12.0.4' def get_default_company(user=None): '''Get default company for user''' From dadd049cbf23f5e09b323d26c2cdf0763bae77e8 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 2 Aug 2019 19:11:31 +0530 Subject: [PATCH 078/124] fix: add serial no button not working for the delivery note --- erpnext/public/js/utils.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 0a363a04fd..ffc5e6ad36 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -60,7 +60,15 @@ $.extend(erpnext, { var me = this; $btn.on("click", function() { - me.show_serial_batch_selector(grid_row.frm, grid_row.doc); + let callback = ''; + let on_close = ''; + + if (grid_row.doc.serial_no) { + grid_row.doc.has_serial_no = true; + } + + me.show_serial_batch_selector(grid_row.frm, grid_row.doc, + callback, on_close, true); }); }, }); From e45102b91325d7fb64f97de8ee23e60527d56958 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Fri, 2 Aug 2019 21:46:28 +0530 Subject: [PATCH 079/124] fix: Show correct label instead of showing undefined (#18560) --- .../doctype/sales_order/sales_order.js | 55 ++++++++++++------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 39dda92e3e..2e5f255a90 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -255,27 +255,44 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( }); return; } else { - var fields = [ - {fieldtype:'Table', fieldname: 'items', - description: __('Select BOM and Qty for Production'), - fields: [ - {fieldtype:'Read Only', fieldname:'item_code', - label: __('Item Code'), in_list_view:1}, - {fieldtype:'Link', fieldname:'bom', options: 'BOM', reqd: 1, - label: __('Select BOM'), in_list_view:1, get_query: function(doc) { - return {filters: {item: doc.item_code}}; - }}, - {fieldtype:'Float', fieldname:'pending_qty', reqd: 1, - label: __('Qty'), in_list_view:1}, - {fieldtype:'Data', fieldname:'sales_order_item', reqd: 1, - label: __('Sales Order Item'), hidden:1} - ], - data: r.message, - get_data: function() { - return r.message + const fields = [{ + label: 'Items', + fieldtype: 'Table', + fieldname: 'items', + description: __('Select BOM and Qty for Production'), + fields: [{ + fieldtype: 'Read Only', + fieldname: 'item_code', + label: __('Item Code'), + in_list_view: 1 + }, { + fieldtype: 'Link', + fieldname: 'bom', + options: 'BOM', + reqd: 1, + label: __('Select BOM'), + in_list_view: 1, + get_query: function (doc) { + return { filters: { item: doc.item_code } }; } + }, { + fieldtype: 'Float', + fieldname: 'pending_qty', + reqd: 1, + label: __('Qty'), + in_list_view: 1 + }, { + fieldtype: 'Data', + fieldname: 'sales_order_item', + reqd: 1, + label: __('Sales Order Item'), + hidden: 1 + }], + data: r.message, + get_data: () => { + return r.message } - ] + }] var d = new frappe.ui.Dialog({ title: __('Select Items to Manufacture'), fields: fields, From b0916a35dc0049105acb3b2b62a579353e57d33a Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 3 Aug 2019 10:17:44 +0530 Subject: [PATCH 080/124] fix: Remove payment order from bank dashboard --- erpnext/accounts/doctype/bank/bank_dashboard.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/erpnext/accounts/doctype/bank/bank_dashboard.py b/erpnext/accounts/doctype/bank/bank_dashboard.py index 432404155d..4a1dad8952 100644 --- a/erpnext/accounts/doctype/bank/bank_dashboard.py +++ b/erpnext/accounts/doctype/bank/bank_dashboard.py @@ -10,9 +10,6 @@ def get_data(): { 'label': _('Bank Deatils'), 'items': ['Bank Account', 'Bank Guarantee'] - }, - { - 'items': ['Payment Order'] } ] } From a49907925067d899ea1058ef2daa6b1c96f4a038 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 3 Aug 2019 10:27:33 +0530 Subject: [PATCH 081/124] fix: Remove non standard fieldname --- erpnext/accounts/doctype/bank/bank_dashboard.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/erpnext/accounts/doctype/bank/bank_dashboard.py b/erpnext/accounts/doctype/bank/bank_dashboard.py index 42838c9748..4a1dad8952 100644 --- a/erpnext/accounts/doctype/bank/bank_dashboard.py +++ b/erpnext/accounts/doctype/bank/bank_dashboard.py @@ -6,9 +6,6 @@ from frappe import _ def get_data(): return { 'fieldname': 'bank', - 'non_standard_fieldnames': { - 'Paymnet Order': 'company_bank' - }, 'transactions': [ { 'label': _('Bank Deatils'), From 8bf19ce81a615227ce7b85252aabb41c28039c6e Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 3 Aug 2019 13:40:37 +0530 Subject: [PATCH 082/124] fix: Error handling in taxes and totals --- erpnext/controllers/taxes_and_totals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index b774037266..d2db9d005a 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -82,7 +82,7 @@ class calculate_taxes_and_totals(object): item.net_rate = item.rate - if not item.qty and self.doc.is_return: + if not item.qty and self.doc.get("is_return"): item.amount = flt(-1 * item.rate, item.precision("amount")) else: item.amount = flt(item.rate * item.qty, item.precision("amount")) From c92e8236518944165c760bc2359db00eed78a514 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 5 Aug 2019 10:02:32 +0530 Subject: [PATCH 083/124] fix(employee-advance): update employee advance on change in expense claim (#18590) * fix(employee-advance): update employee advance on rejection/cancellation of expense claim * fix(expense-claim): display appropriate buttons only if linked transactions are valid --- .../employee_advance/employee_advance.py | 19 +++++++++++++------ .../hr/doctype/expense_claim/expense_claim.js | 4 ++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py index 1c8b5f9662..7b7c0a77e0 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.py +++ b/erpnext/hr/doctype/employee_advance/employee_advance.py @@ -64,13 +64,20 @@ class EmployeeAdvance(Document): def update_claimed_amount(self): claimed_amount = frappe.db.sql(""" - select sum(ifnull(allocated_amount, 0)) - from `tabExpense Claim Advance` - where employee_advance = %s and docstatus=1 and allocated_amount > 0 - """, self.name)[0][0] or 0 + SELECT sum(ifnull(allocated_amount, 0)) + FROM `tabExpense Claim Advance` eca, `tabExpense Claim` ec + WHERE + eca.employee_advance = %s + AND ec.approval_status="Approved" + AND ec.name = eca.parent + AND ec.docstatus=1 + AND eca.allocated_amount > 0 + """, self.name, debug=1)[0][0] or 0 - if claimed_amount: - frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount)) + frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount)) + self.reload() + self.set_status() + frappe.db.set_value("Employee Advance", self.name, "status", self.status) @frappe.whitelist() def get_due_advance_amount(employee, posting_date): diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js index 40bec6d4d7..6d3a28e5e2 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/expense_claim.js @@ -183,7 +183,7 @@ frappe.ui.form.on("Expense Claim", { refresh: function(frm) { frm.trigger("toggle_fields"); - if(frm.doc.docstatus == 1) { + if(frm.doc.docstatus === 1 && frm.doc.approval_status !== "Rejected") { frm.add_custom_button(__('Accounting Ledger'), function() { frappe.route_options = { voucher_no: frm.doc.name, @@ -194,7 +194,7 @@ frappe.ui.form.on("Expense Claim", { }, __("View")); } - if (frm.doc.docstatus===1 + if (frm.doc.docstatus===1 && !cint(frm.doc.is_paid) && cint(frm.doc.grand_total) > 0 && (cint(frm.doc.total_amount_reimbursed) < cint(frm.doc.total_sanctioned_amount)) && frappe.model.can_create("Payment Entry")) { frm.add_custom_button(__('Payment'), From a813571c17de62714dfc3f8a64724983e899aed2 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 5 Aug 2019 10:05:28 +0530 Subject: [PATCH 084/124] Update employee_advance.py --- erpnext/hr/doctype/employee_advance/employee_advance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py index 7b7c0a77e0..7813da78ca 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.py +++ b/erpnext/hr/doctype/employee_advance/employee_advance.py @@ -72,7 +72,7 @@ class EmployeeAdvance(Document): AND ec.name = eca.parent AND ec.docstatus=1 AND eca.allocated_amount > 0 - """, self.name, debug=1)[0][0] or 0 + """, self.name)[0][0] or 0 frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount)) self.reload() From 580fa486420b6ed93b197ecd545e3fe8e63226e1 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Mon, 5 Aug 2019 10:08:35 +0530 Subject: [PATCH 085/124] fix: Quotation list in customer portal (#18579) * fix: Quotation list in customer portal Customers were not able to see their quotations because of the recent customer field removal from quotation * fix: Remove duplicate code --- .../controllers/website_list_for_contact.py | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py index ed48fd1ab4..187eaed107 100644 --- a/erpnext/controllers/website_list_for_contact.py +++ b/erpnext/controllers/website_list_for_contact.py @@ -77,7 +77,7 @@ def get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_len if or_filters: for r in frappe.get_list(doctype, fields=fields,filters=filters, or_filters=or_filters, - limit_start=limit_start, limit_page_length=limit_page_length, + limit_start=limit_start, limit_page_length=limit_page_length, ignore_permissions=ignore_permissions, order_by=order_by): data.append(r) @@ -130,38 +130,56 @@ def get_customers_suppliers(doctype, user): suppliers = [] meta = frappe.get_meta(doctype) + customer_field_name = get_customer_field_name(doctype) + + has_customer_field = meta.has_field(customer_field_name) + has_supplier_field = meta.has_field('supplier') + if has_common(["Supplier", "Customer"], frappe.get_roles(user)): contacts = frappe.db.sql(""" - select + select `tabContact`.email_id, `tabDynamic Link`.link_doctype, `tabDynamic Link`.link_name - from + from `tabContact`, `tabDynamic Link` where `tabContact`.name=`tabDynamic Link`.parent and `tabContact`.email_id =%s """, user, as_dict=1) - customers = [c.link_name for c in contacts if c.link_doctype == 'Customer'] \ - if meta.get_field("customer") else None - suppliers = [c.link_name for c in contacts if c.link_doctype == 'Supplier'] \ - if meta.get_field("supplier") else None + customers = [c.link_name for c in contacts if c.link_doctype == 'Customer'] + suppliers = [c.link_name for c in contacts if c.link_doctype == 'Supplier'] elif frappe.has_permission(doctype, 'read', user=user): - customers = [customer.name for customer in frappe.get_list("Customer")] \ - if meta.get_field("customer") else None - suppliers = [supplier.name for supplier in frappe.get_list("Customer")] \ - if meta.get_field("supplier") else None + customer_list = frappe.get_list("Customer") + customers = suppliers = [customer.name for customer in customer_list] - return customers, suppliers + return customers if has_customer_field else None, \ + suppliers if has_supplier_field else None def has_website_permission(doc, ptype, user, verbose=False): doctype = doc.doctype customers, suppliers = get_customers_suppliers(doctype, user) if customers: - return frappe.get_all(doctype, filters=[(doctype, "customer", "in", customers), - (doctype, "name", "=", doc.name)]) and True or False + return frappe.db.exists(doctype, filters=get_customer_filter(doc, customers)) elif suppliers: fieldname = 'suppliers' if doctype == 'Request for Quotation' else 'supplier' - return frappe.get_all(doctype, filters=[(doctype, fieldname, "in", suppliers), - (doctype, "name", "=", doc.name)]) and True or False + return frappe.db.exists(doctype, filters={ + 'name': doc.name, + fieldname: ["in", suppliers] + }) else: return False + +def get_customer_filter(doc, customers): + doctype = doc.doctype + filters = frappe._dict() + filters.name = doc.name + filters[get_customer_field_name(doctype)] = ['in', customers] + if doctype == 'Quotation': + filters.party_type = 'Customer' + return filters + +def get_customer_field_name(doctype): + if doctype == 'Quotation': + return 'party_name' + else: + return 'customer' \ No newline at end of file From b4678d3f21f633e0c1c512d9d7759b3bb6459889 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 5 Aug 2019 10:09:32 +0530 Subject: [PATCH 086/124] chore: Remove package-lock.json (#18564) Yarn uses yarn.lock --- package-lock.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 48e341a095..0000000000 --- a/package-lock.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "lockfileVersion": 1 -} From 65ad4287b646b93619bdd774c8f0aac7d1c9187f Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Mon, 5 Aug 2019 10:10:38 +0530 Subject: [PATCH 087/124] fix: Customer price list not honored in shopping cart (#18557) --- erpnext/shopping_cart/cart.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py index 62bde420a8..0922f3d1a0 100644 --- a/erpnext/shopping_cart/cart.py +++ b/erpnext/shopping_cart/cart.py @@ -251,13 +251,12 @@ def _get_cart_quotation(party=None): if quotation: qdoc = frappe.get_doc("Quotation", quotation[0].name) else: - [company, price_list] = frappe.db.get_value("Shopping Cart Settings", None, ["company", "price_list"]) + company = frappe.db.get_value("Shopping Cart Settings", None, ["company"]) qdoc = frappe.get_doc({ "doctype": "Quotation", "naming_series": get_shopping_cart_settings().quotation_series or "QTN-CART-", "quotation_to": party.doctype, "company": company, - "selling_price_list": price_list, "order_type": "Shopping Cart", "status": "Draft", "docstatus": 0, From 713d4bb1ba94af8e34ba40736e3bc4b27116a87b Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Mon, 5 Aug 2019 10:12:17 +0530 Subject: [PATCH 088/124] fix: Type error handling while getting material request items (#18550) * fix: Type error handling while getting material request items * fix: Remove flt --- .../doctype/production_plan/production_plan.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 3a77e2f209..8334f6b869 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -430,7 +430,7 @@ def download_raw_materials(production_plan): continue item_list.append(['', '', '', '', bin_dict.get('warehouse'), - bin_dict.get('projected_qty'), bin_dict.get('actual_qty')]) + bin_dict.get('projected_qty', 0), bin_dict.get('actual_qty', 0)]) build_csv_response(item_list, doc.name) @@ -507,8 +507,8 @@ def get_material_request_items(row, sales_order, required_qty = 0 if ignore_existing_ordered_qty or bin_dict.get("projected_qty", 0) < 0: required_qty = total_qty - elif total_qty > bin_dict.get("projected_qty"): - required_qty = total_qty - bin_dict.get("projected_qty") + elif total_qty > bin_dict.get("projected_qty", 0): + required_qty = total_qty - bin_dict.get("projected_qty", 0) if required_qty > 0 and required_qty < row['min_order_qty']: required_qty = row['min_order_qty'] item_group_defaults = get_item_group_defaults(row.item_code, company) From 8b0302bab9c4f91629654d1897d82f6f3bf3b244 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Mon, 5 Aug 2019 10:14:19 +0530 Subject: [PATCH 089/124] fix: Make conversion rate optional for non itemized items (#18540) --- erpnext/buying/utils.py | 14 ++++++++------ erpnext/controllers/buying_controller.py | 4 +++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/erpnext/buying/utils.py b/erpnext/buying/utils.py index 981ee5dcef..8c0a1e56f7 100644 --- a/erpnext/buying/utils.py +++ b/erpnext/buying/utils.py @@ -30,7 +30,9 @@ def update_last_purchase_rate(doc, is_submit): # for it to be considered for latest purchase rate if flt(d.conversion_factor): last_purchase_rate = flt(d.base_rate) / flt(d.conversion_factor) - else: + # Check if item code is present + # Conversion factor should not be mandatory for non itemized items + elif d.item_code: frappe.throw(_("UOM Conversion factor is required in row {0}").format(d.idx)) # update last purchsae rate @@ -84,13 +86,13 @@ def get_linked_material_requests(items): items = json.loads(items) mr_list = [] for item in items: - material_request = frappe.db.sql("""SELECT distinct mr.name AS mr_name, - (mr_item.qty - mr_item.ordered_qty) AS qty, + material_request = frappe.db.sql("""SELECT distinct mr.name AS mr_name, + (mr_item.qty - mr_item.ordered_qty) AS qty, mr_item.item_code AS item_code, - mr_item.name AS mr_item + mr_item.name AS mr_item FROM `tabMaterial Request` mr, `tabMaterial Request Item` mr_item WHERE mr.name = mr_item.parent - AND mr_item.item_code = %(item)s + AND mr_item.item_code = %(item)s AND mr.material_request_type = 'Purchase' AND mr.per_ordered < 99.99 AND mr.docstatus = 1 @@ -98,6 +100,6 @@ def get_linked_material_requests(items): ORDER BY mr_item.item_code ASC""",{"item": item}, as_dict=1) if material_request: mr_list.append(material_request) - + return mr_list diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 0b4d38ce5c..588f74dbc9 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -395,7 +395,9 @@ class BuyingController(StockController): def set_qty_as_per_stock_uom(self): for d in self.get("items"): if d.meta.get_field("stock_qty"): - if not d.conversion_factor: + # Check if item code is present + # Conversion factor should not be mandatory for non itemized items + if not d.conversion_factor and d.item_code: frappe.throw(_("Row {0}: Conversion Factor is mandatory").format(d.idx)) d.stock_qty = flt(d.qty) * flt(d.conversion_factor) From 9accae3ddcaad03b0d8c4b1d38a882aa8a7b6385 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 5 Aug 2019 10:16:25 +0530 Subject: [PATCH 090/124] fix(sales-order): update items (#18536) * fix(sales-order): update items * fix: minor changes --- erpnext/controllers/accounts_controller.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 288aa082c5..4a89c5b123 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1192,6 +1192,10 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil .format(child_item.idx, child_item.item_code)) else: child_item.rate = flt(d.get("rate")) + if child_item.price_list_rate: + child_item.discount_percentage = flt((1 - flt(child_item.rate) / flt(child_item.price_list_rate)) * 100.0, \ + child_item.precision("discount_percentage")) + child_item.flags.ignore_validate_update_after_submit = True if new_child_flag: child_item.idx = len(parent.items) + 1 From 7e1987ed48156571cdc6ae1745e9711366a069f2 Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Mon, 5 Aug 2019 10:18:57 +0530 Subject: [PATCH 091/124] feat: validate cwip accounts for journal Entry (#18518) --- erpnext/accounts/general_ledger.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 9a014840eb..be1448df3a 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -93,6 +93,7 @@ def check_if_in_list(gle, gl_map, dimensions=None): def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False): if not from_repost: validate_account_for_perpetual_inventory(gl_map) + validate_cwip_accounts(gl_map) round_off_debit_credit(gl_map) @@ -123,6 +124,16 @@ def validate_account_for_perpetual_inventory(gl_map): frappe.throw(_("Account: {0} can only be updated via Stock Transactions") .format(entry.account), StockAccountInvalidTransaction) +def validate_cwip_accounts(gl_map): + if not cint(frappe.db.get_value("Asset Settings", None, "disable_cwip_accounting")) \ + and gl_map[0].voucher_type == "Journal Entry": + cwip_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount + where account_type = 'Capital Work in Progress' and is_group=0""")] + + for entry in gl_map: + if entry.account in cwip_accounts: + frappe.throw(_("Account: {0} is capital Work in progress and can not be updated by Journal Entry").format(entry.account)) + def round_off_debit_credit(gl_map): precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"), currency=frappe.get_cached_value('Company', gl_map[0].company, "default_currency")) From 08df6bda41a1414a051e49f7a1f48a339b577890 Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Mon, 5 Aug 2019 10:27:25 +0530 Subject: [PATCH 092/124] fix: query (#18468) --- .../doctype/payment_entry/payment_entry.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 368389807d..da6b167880 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -648,13 +648,18 @@ def get_orders_to_be_billed(posting_date, party_type, party, orders = [] if voucher_type: - ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total" + if party_account_currency == company_currency: + grand_total_field = "base_grand_total" + rounded_total_field = "base_rounded_total" + else: + grand_total_field = "grand_total" + rounded_total_field = "rounded_total" orders = frappe.db.sql(""" select name as voucher_no, - {ref_field} as invoice_amount, - ({ref_field} - advance_paid) as outstanding_amount, + if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) as invoice_amount, + (if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) - advance_paid) as outstanding_amount, transaction_date as posting_date from `tab{voucher_type}` @@ -663,13 +668,14 @@ def get_orders_to_be_billed(posting_date, party_type, party, and docstatus = 1 and company = %s and ifnull(status, "") != "Closed" - and {ref_field} > advance_paid + and if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) > advance_paid and abs(100 - per_billed) > 0.01 {condition} order by transaction_date, name """.format(**{ - "ref_field": ref_field, + "rounded_total_field": rounded_total_field, + "grand_total_field": grand_total_field, "voucher_type": voucher_type, "party_type": scrub(party_type), "condition": condition From 9601b6c60106690dccdaa499bfa54a4214ff6737 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 5 Aug 2019 10:40:23 +0530 Subject: [PATCH 093/124] feat: added checkbox 'Update Consumed Material Cost In Project' in work order to don't update the consumed material cost in the project for the subassembely work orders (#18533) --- .../production_plan/production_plan.py | 3 +- .../doctype/work_order/work_order.json | 986 +++++++++--------- .../stock/doctype/stock_entry/stock_entry.py | 4 + 3 files changed, 509 insertions(+), 484 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 8334f6b869..650ab137a0 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -320,7 +320,8 @@ class ProductionPlan(Document): 'qty': data.get("stock_qty") * item.get("qty"), 'production_plan': self.name, 'company': self.company, - 'fg_warehouse': item.get("fg_warehouse") + 'fg_warehouse': item.get("fg_warehouse"), + 'update_consumed_material_cost_in_project': 0 }) work_order = self.create_work_order(data) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.json b/erpnext/manufacturing/doctype/work_order/work_order.json index 1534b5929d..63c95e7c21 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.json +++ b/erpnext/manufacturing/doctype/work_order/work_order.json @@ -1,484 +1,504 @@ { - "allow_import": 1, - "autoname": "naming_series:", - "creation": "2013-01-10 16:34:16", - "doctype": "DocType", - "document_type": "Setup", - "field_order": [ - "item", - "naming_series", - "status", - "production_item", - "item_name", - "image", - "bom_no", - "allow_alternative_item", - "use_multi_level_bom", - "skip_transfer", - "column_break1", - "company", - "qty", - "material_transferred_for_manufacturing", - "produced_qty", - "sales_order", - "project", - "from_wip_warehouse", - "warehouses", - "wip_warehouse", - "fg_warehouse", - "column_break_12", - "scrap_warehouse", - "required_items_section", - "required_items", - "time", - "planned_start_date", - "actual_start_date", - "column_break_13", - "planned_end_date", - "actual_end_date", - "expected_delivery_date", - "operations_section", - "transfer_material_against", - "operations", - "section_break_22", - "planned_operating_cost", - "actual_operating_cost", - "additional_operating_cost", - "column_break_24", - "total_operating_cost", - "more_info", - "description", - "stock_uom", - "column_break2", - "material_request", - "material_request_item", - "sales_order_item", - "production_plan", - "production_plan_item", - "product_bundle_item", - "amended_from" - ], - "fields": [ - { - "fieldname": "item", - "fieldtype": "Section Break", - "options": "fa fa-gift" - }, - { - "fieldname": "naming_series", - "fieldtype": "Select", - "label": "Series", - "options": "MFG-WO-.YYYY.-", - "print_hide": 1, - "reqd": 1, - "set_only_once": 1 - }, - { - "default": "Draft", - "depends_on": "eval:!doc.__islocal", - "fieldname": "status", - "fieldtype": "Select", - "label": "Status", - "no_copy": 1, - "oldfieldname": "status", - "oldfieldtype": "Select", - "options": "\nDraft\nSubmitted\nNot Started\nIn Process\nCompleted\nStopped\nCancelled", - "read_only": 1, - "reqd": 1, - "search_index": 1 - }, - { - "fieldname": "production_item", - "fieldtype": "Link", - "in_global_search": 1, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Item To Manufacture", - "oldfieldname": "production_item", - "oldfieldtype": "Link", - "options": "Item", - "reqd": 1 - }, - { - "depends_on": "eval:doc.production_item", - "fieldname": "item_name", - "fieldtype": "Data", - "label": "Item Name", - "read_only": 1 - }, - { - "fetch_from": "production_item.image", - "fieldname": "image", - "fieldtype": "Attach Image", - "hidden": 1, - "label": "Image", - "options": "image", - "print_hide": 1, - "read_only": 1 - }, - { - "fieldname": "bom_no", - "fieldtype": "Link", - "label": "BOM No", - "oldfieldname": "bom_no", - "oldfieldtype": "Link", - "options": "BOM", - "reqd": 1 - }, - { - "default": "0", - "fieldname": "allow_alternative_item", - "fieldtype": "Check", - "label": "Allow Alternative Item" - }, - { - "default": "1", - "description": "Plan material for sub-assemblies", - "fieldname": "use_multi_level_bom", - "fieldtype": "Check", - "label": "Use Multi-Level BOM", - "print_hide": 1 - }, - { - "default": "0", - "description": "Check if material transfer entry is not required", - "fieldname": "skip_transfer", - "fieldtype": "Check", - "label": "Skip Material Transfer to WIP Warehouse" - }, - { - "fieldname": "column_break1", - "fieldtype": "Column Break", - "oldfieldtype": "Column Break", - "width": "50%" - }, - { - "fieldname": "company", - "fieldtype": "Link", - "label": "Company", - "oldfieldname": "company", - "oldfieldtype": "Link", - "options": "Company", - "remember_last_selected_value": 1, - "reqd": 1 - }, - { - "fieldname": "qty", - "fieldtype": "Float", - "label": "Qty To Manufacture", - "oldfieldname": "qty", - "oldfieldtype": "Currency", - "reqd": 1 - }, - { - "default": "0", - "depends_on": "eval:doc.docstatus==1 && doc.skip_transfer==0", - "fieldname": "material_transferred_for_manufacturing", - "fieldtype": "Float", - "label": "Material Transferred for Manufacturing", - "no_copy": 1, - "read_only": 1 - }, - { - "default": "0", - "depends_on": "eval:doc.docstatus==1", - "fieldname": "produced_qty", - "fieldtype": "Float", - "label": "Manufactured Qty", - "no_copy": 1, - "oldfieldname": "produced_qty", - "oldfieldtype": "Currency", - "read_only": 1 - }, - { - "allow_on_submit": 1, - "fieldname": "sales_order", - "fieldtype": "Link", - "in_global_search": 1, - "label": "Sales Order", - "options": "Sales Order" - }, - { - "fieldname": "project", - "fieldtype": "Link", - "label": "Project", - "oldfieldname": "project", - "oldfieldtype": "Link", - "options": "Project" - }, - { - "default": "0", - "depends_on": "skip_transfer", - "fieldname": "from_wip_warehouse", - "fieldtype": "Check", - "label": "Backflush Raw Materials From Work-in-Progress Warehouse" - }, - { - "fieldname": "warehouses", - "fieldtype": "Section Break", - "label": "Warehouses", - "options": "fa fa-building" - }, - { - "fieldname": "wip_warehouse", - "fieldtype": "Link", - "label": "Work-in-Progress Warehouse", - "options": "Warehouse" - }, - { - "fieldname": "fg_warehouse", - "fieldtype": "Link", - "label": "Target Warehouse", - "options": "Warehouse" - }, - { - "fieldname": "column_break_12", - "fieldtype": "Column Break" - }, - { - "fieldname": "scrap_warehouse", - "fieldtype": "Link", - "label": "Scrap Warehouse", - "options": "Warehouse" - }, - { - "fieldname": "required_items_section", - "fieldtype": "Section Break", - "label": "Required Items" - }, - { - "fieldname": "required_items", - "fieldtype": "Table", - "label": "Required Items", - "no_copy": 1, - "options": "Work Order Item", - "print_hide": 1 - }, - { - "fieldname": "time", - "fieldtype": "Section Break", - "label": "Time", - "options": "fa fa-time" - }, - { - "allow_on_submit": 1, - "default": "now", - "fieldname": "planned_start_date", - "fieldtype": "Datetime", - "label": "Planned Start Date", - "reqd": 1 - }, - { - "fieldname": "actual_start_date", - "fieldtype": "Datetime", - "label": "Actual Start Date", - "read_only": 1 - }, - { - "fieldname": "column_break_13", - "fieldtype": "Column Break" - }, - { - "fieldname": "planned_end_date", - "fieldtype": "Datetime", - "label": "Planned End Date", - "no_copy": 1, - "read_only": 1 - }, - { - "fieldname": "actual_end_date", - "fieldtype": "Datetime", - "label": "Actual End Date", - "read_only": 1 - }, - { - "allow_on_submit": 1, - "fieldname": "expected_delivery_date", - "fieldtype": "Date", - "label": "Expected Delivery Date" - }, - { - "fieldname": "operations_section", - "fieldtype": "Section Break", - "label": "Operations", - "options": "fa fa-wrench" - }, - { - "default": "Work Order", - "depends_on": "operations", - "fieldname": "transfer_material_against", - "fieldtype": "Select", - "label": "Transfer Material Against", - "options": "\nWork Order\nJob Card" - }, - { - "fieldname": "operations", - "fieldtype": "Table", - "label": "Operations", - "options": "Work Order Operation", - "read_only": 1 - }, - { - "depends_on": "operations", - "fieldname": "section_break_22", - "fieldtype": "Section Break", - "label": "Operation Cost" - }, - { - "fieldname": "planned_operating_cost", - "fieldtype": "Currency", - "label": "Planned Operating Cost", - "options": "Company:company:default_currency", - "read_only": 1 - }, - { - "fieldname": "actual_operating_cost", - "fieldtype": "Currency", - "label": "Actual Operating Cost", - "no_copy": 1, - "options": "Company:company:default_currency", - "read_only": 1 - }, - { - "fieldname": "additional_operating_cost", - "fieldtype": "Currency", - "label": "Additional Operating Cost", - "no_copy": 1, - "options": "Company:company:default_currency" - }, - { - "fieldname": "column_break_24", - "fieldtype": "Column Break" - }, - { - "fieldname": "total_operating_cost", - "fieldtype": "Currency", - "label": "Total Operating Cost", - "no_copy": 1, - "options": "Company:company:default_currency", - "read_only": 1 - }, - { - "collapsible": 1, - "fieldname": "more_info", - "fieldtype": "Section Break", - "label": "More Information", - "options": "fa fa-file-text" - }, - { - "fieldname": "description", - "fieldtype": "Small Text", - "label": "Item Description", - "read_only": 1 - }, - { - "fieldname": "stock_uom", - "fieldtype": "Link", - "label": "Stock UOM", - "oldfieldname": "stock_uom", - "oldfieldtype": "Data", - "options": "UOM", - "read_only": 1 - }, - { - "fieldname": "column_break2", - "fieldtype": "Column Break", - "width": "50%" - }, - { - "description": "Manufacture against Material Request", - "fieldname": "material_request", - "fieldtype": "Link", - "label": "Material Request", - "options": "Material Request" - }, - { - "fieldname": "material_request_item", - "fieldtype": "Data", - "hidden": 1, - "label": "Material Request Item", - "read_only": 1 - }, - { - "fieldname": "sales_order_item", - "fieldtype": "Data", - "hidden": 1, - "label": "Sales Order Item", - "read_only": 1 - }, - { - "fieldname": "production_plan", - "fieldtype": "Link", - "label": "Production Plan", - "no_copy": 1, - "options": "Production Plan", - "print_hide": 1, - "read_only": 1 - }, - { - "fieldname": "production_plan_item", - "fieldtype": "Data", - "label": "Production Plan Item", - "no_copy": 1, - "print_hide": 1, - "read_only": 1 - }, - { - "fieldname": "product_bundle_item", - "fieldtype": "Link", - "label": "Product Bundle Item", - "no_copy": 1, - "options": "Item", - "print_hide": 1, - "read_only": 1 - }, - { - "fieldname": "amended_from", - "fieldtype": "Link", - "ignore_user_permissions": 1, - "label": "Amended From", - "no_copy": 1, - "oldfieldname": "amended_from", - "oldfieldtype": "Data", - "options": "Work Order", - "read_only": 1 - } - ], - "icon": "fa fa-cogs", - "idx": 1, - "image_field": "image", - "is_submittable": 1, - "modified": "2019-05-27 09:36:16.707719", - "modified_by": "Administrator", - "module": "Manufacturing", - "name": "Work Order", - "owner": "Administrator", - "permissions": [ - { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "import": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Manufacturing User", - "set_user_permissions": 1, - "share": 1, - "submit": 1, - "write": 1 - }, - { - "read": 1, - "report": 1, - "role": "Stock User" - } - ], - "sort_order": "ASC", - "title_field": "production_item", - "track_changes": 1, - "track_seen": 1 - } \ No newline at end of file + "allow_import": 1, + "autoname": "naming_series:", + "creation": "2013-01-10 16:34:16", + "doctype": "DocType", + "document_type": "Setup", + "engine": "InnoDB", + "field_order": [ + "item", + "naming_series", + "status", + "production_item", + "item_name", + "image", + "bom_no", + "column_break1", + "company", + "qty", + "material_transferred_for_manufacturing", + "produced_qty", + "sales_order", + "project", + "settings_section", + "allow_alternative_item", + "use_multi_level_bom", + "column_break_18", + "skip_transfer", + "from_wip_warehouse", + "update_consumed_material_cost_in_project", + "warehouses", + "wip_warehouse", + "fg_warehouse", + "column_break_12", + "scrap_warehouse", + "required_items_section", + "required_items", + "time", + "planned_start_date", + "actual_start_date", + "column_break_13", + "planned_end_date", + "actual_end_date", + "expected_delivery_date", + "operations_section", + "transfer_material_against", + "operations", + "section_break_22", + "planned_operating_cost", + "actual_operating_cost", + "additional_operating_cost", + "column_break_24", + "total_operating_cost", + "more_info", + "description", + "stock_uom", + "column_break2", + "material_request", + "material_request_item", + "sales_order_item", + "production_plan", + "production_plan_item", + "product_bundle_item", + "amended_from" + ], + "fields": [ + { + "fieldname": "item", + "fieldtype": "Section Break", + "options": "fa fa-gift" + }, + { + "fieldname": "naming_series", + "fieldtype": "Select", + "label": "Series", + "options": "MFG-WO-.YYYY.-", + "print_hide": 1, + "reqd": 1, + "set_only_once": 1 + }, + { + "default": "Draft", + "depends_on": "eval:!doc.__islocal", + "fieldname": "status", + "fieldtype": "Select", + "label": "Status", + "no_copy": 1, + "oldfieldname": "status", + "oldfieldtype": "Select", + "options": "\nDraft\nSubmitted\nNot Started\nIn Process\nCompleted\nStopped\nCancelled", + "read_only": 1, + "reqd": 1, + "search_index": 1 + }, + { + "fieldname": "production_item", + "fieldtype": "Link", + "in_global_search": 1, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Item To Manufacture", + "oldfieldname": "production_item", + "oldfieldtype": "Link", + "options": "Item", + "reqd": 1 + }, + { + "depends_on": "eval:doc.production_item", + "fieldname": "item_name", + "fieldtype": "Data", + "label": "Item Name", + "read_only": 1 + }, + { + "fetch_from": "production_item.image", + "fieldname": "image", + "fieldtype": "Attach Image", + "hidden": 1, + "label": "Image", + "options": "image", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "bom_no", + "fieldtype": "Link", + "label": "BOM No", + "oldfieldname": "bom_no", + "oldfieldtype": "Link", + "options": "BOM", + "reqd": 1 + }, + { + "default": "0", + "fieldname": "allow_alternative_item", + "fieldtype": "Check", + "label": "Allow Alternative Item" + }, + { + "default": "1", + "description": "Plan material for sub-assemblies", + "fieldname": "use_multi_level_bom", + "fieldtype": "Check", + "label": "Use Multi-Level BOM", + "print_hide": 1 + }, + { + "default": "0", + "description": "Check if material transfer entry is not required", + "fieldname": "skip_transfer", + "fieldtype": "Check", + "label": "Skip Material Transfer to WIP Warehouse" + }, + { + "fieldname": "column_break1", + "fieldtype": "Column Break", + "oldfieldtype": "Column Break", + "width": "50%" + }, + { + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "oldfieldname": "company", + "oldfieldtype": "Link", + "options": "Company", + "remember_last_selected_value": 1, + "reqd": 1 + }, + { + "fieldname": "qty", + "fieldtype": "Float", + "label": "Qty To Manufacture", + "oldfieldname": "qty", + "oldfieldtype": "Currency", + "reqd": 1 + }, + { + "default": "0", + "depends_on": "eval:doc.docstatus==1 && doc.skip_transfer==0", + "fieldname": "material_transferred_for_manufacturing", + "fieldtype": "Float", + "label": "Material Transferred for Manufacturing", + "no_copy": 1, + "read_only": 1 + }, + { + "default": "0", + "depends_on": "eval:doc.docstatus==1", + "fieldname": "produced_qty", + "fieldtype": "Float", + "label": "Manufactured Qty", + "no_copy": 1, + "oldfieldname": "produced_qty", + "oldfieldtype": "Currency", + "read_only": 1 + }, + { + "allow_on_submit": 1, + "fieldname": "sales_order", + "fieldtype": "Link", + "in_global_search": 1, + "label": "Sales Order", + "options": "Sales Order" + }, + { + "fieldname": "project", + "fieldtype": "Link", + "label": "Project", + "oldfieldname": "project", + "oldfieldtype": "Link", + "options": "Project" + }, + { + "default": "0", + "depends_on": "skip_transfer", + "fieldname": "from_wip_warehouse", + "fieldtype": "Check", + "label": "Backflush Raw Materials From Work-in-Progress Warehouse" + }, + { + "fieldname": "warehouses", + "fieldtype": "Section Break", + "label": "Warehouses", + "options": "fa fa-building" + }, + { + "fieldname": "wip_warehouse", + "fieldtype": "Link", + "label": "Work-in-Progress Warehouse", + "options": "Warehouse" + }, + { + "fieldname": "fg_warehouse", + "fieldtype": "Link", + "label": "Target Warehouse", + "options": "Warehouse" + }, + { + "fieldname": "column_break_12", + "fieldtype": "Column Break" + }, + { + "fieldname": "scrap_warehouse", + "fieldtype": "Link", + "label": "Scrap Warehouse", + "options": "Warehouse" + }, + { + "fieldname": "required_items_section", + "fieldtype": "Section Break", + "label": "Required Items" + }, + { + "fieldname": "required_items", + "fieldtype": "Table", + "label": "Required Items", + "no_copy": 1, + "options": "Work Order Item", + "print_hide": 1 + }, + { + "fieldname": "time", + "fieldtype": "Section Break", + "label": "Time", + "options": "fa fa-time" + }, + { + "allow_on_submit": 1, + "default": "now", + "fieldname": "planned_start_date", + "fieldtype": "Datetime", + "label": "Planned Start Date", + "reqd": 1 + }, + { + "fieldname": "actual_start_date", + "fieldtype": "Datetime", + "label": "Actual Start Date", + "read_only": 1 + }, + { + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, + { + "fieldname": "planned_end_date", + "fieldtype": "Datetime", + "label": "Planned End Date", + "no_copy": 1, + "read_only": 1 + }, + { + "fieldname": "actual_end_date", + "fieldtype": "Datetime", + "label": "Actual End Date", + "read_only": 1 + }, + { + "allow_on_submit": 1, + "fieldname": "expected_delivery_date", + "fieldtype": "Date", + "label": "Expected Delivery Date" + }, + { + "fieldname": "operations_section", + "fieldtype": "Section Break", + "label": "Operations", + "options": "fa fa-wrench" + }, + { + "default": "Work Order", + "depends_on": "operations", + "fieldname": "transfer_material_against", + "fieldtype": "Select", + "label": "Transfer Material Against", + "options": "\nWork Order\nJob Card" + }, + { + "fieldname": "operations", + "fieldtype": "Table", + "label": "Operations", + "options": "Work Order Operation", + "read_only": 1 + }, + { + "depends_on": "operations", + "fieldname": "section_break_22", + "fieldtype": "Section Break", + "label": "Operation Cost" + }, + { + "fieldname": "planned_operating_cost", + "fieldtype": "Currency", + "label": "Planned Operating Cost", + "options": "Company:company:default_currency", + "read_only": 1 + }, + { + "fieldname": "actual_operating_cost", + "fieldtype": "Currency", + "label": "Actual Operating Cost", + "no_copy": 1, + "options": "Company:company:default_currency", + "read_only": 1 + }, + { + "fieldname": "additional_operating_cost", + "fieldtype": "Currency", + "label": "Additional Operating Cost", + "no_copy": 1, + "options": "Company:company:default_currency" + }, + { + "fieldname": "column_break_24", + "fieldtype": "Column Break" + }, + { + "fieldname": "total_operating_cost", + "fieldtype": "Currency", + "label": "Total Operating Cost", + "no_copy": 1, + "options": "Company:company:default_currency", + "read_only": 1 + }, + { + "collapsible": 1, + "fieldname": "more_info", + "fieldtype": "Section Break", + "label": "More Information", + "options": "fa fa-file-text" + }, + { + "fieldname": "description", + "fieldtype": "Small Text", + "label": "Item Description", + "read_only": 1 + }, + { + "fieldname": "stock_uom", + "fieldtype": "Link", + "label": "Stock UOM", + "oldfieldname": "stock_uom", + "oldfieldtype": "Data", + "options": "UOM", + "read_only": 1 + }, + { + "fieldname": "column_break2", + "fieldtype": "Column Break", + "width": "50%" + }, + { + "description": "Manufacture against Material Request", + "fieldname": "material_request", + "fieldtype": "Link", + "label": "Material Request", + "options": "Material Request" + }, + { + "fieldname": "material_request_item", + "fieldtype": "Data", + "hidden": 1, + "label": "Material Request Item", + "read_only": 1 + }, + { + "fieldname": "sales_order_item", + "fieldtype": "Data", + "hidden": 1, + "label": "Sales Order Item", + "read_only": 1 + }, + { + "fieldname": "production_plan", + "fieldtype": "Link", + "label": "Production Plan", + "no_copy": 1, + "options": "Production Plan", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "production_plan_item", + "fieldtype": "Data", + "label": "Production Plan Item", + "no_copy": 1, + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "product_bundle_item", + "fieldtype": "Link", + "label": "Product Bundle Item", + "no_copy": 1, + "options": "Item", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "amended_from", + "fieldtype": "Link", + "ignore_user_permissions": 1, + "label": "Amended From", + "no_copy": 1, + "oldfieldname": "amended_from", + "oldfieldtype": "Data", + "options": "Work Order", + "read_only": 1 + }, + { + "fieldname": "settings_section", + "fieldtype": "Section Break", + "label": "Settings" + }, + { + "fieldname": "column_break_18", + "fieldtype": "Column Break" + }, + { + "default": "1", + "fieldname": "update_consumed_material_cost_in_project", + "fieldtype": "Check", + "label": "Update Consumed Material Cost In Project" + } + ], + "icon": "fa fa-cogs", + "idx": 1, + "image_field": "image", + "is_submittable": 1, + "modified": "2019-07-31 00:13:38.218277", + "modified_by": "Administrator", + "module": "Manufacturing", + "name": "Work Order", + "owner": "Administrator", + "permissions": [ + { + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "import": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Manufacturing User", + "set_user_permissions": 1, + "share": 1, + "submit": 1, + "write": 1 + }, + { + "read": 1, + "report": 1, + "role": "Stock User" + } + ], + "sort_field": "modified", + "sort_order": "ASC", + "title_field": "production_item", + "track_changes": 1, + "track_seen": 1 +} \ No newline at end of file diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index b5303327f6..6e81dd0ae2 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -145,6 +145,10 @@ class StockEntry(StockController): self.precision("transfer_qty", item)) def update_cost_in_project(self): + if (self.work_order and not frappe.db.get_value("Work Order", + self.work_order, "update_consumed_material_cost_in_project")): + return + if self.project: amount = frappe.db.sql(""" select ifnull(sum(sed.amount), 0) from From 23f30cdb8bd69934e5c9041c1e4f3168780dd360 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 5 Aug 2019 12:40:50 +0530 Subject: [PATCH 094/124] fix: Aambigious column in query --- erpnext/accounts/doctype/pricing_rule/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index 5795b8f808..bbabac4302 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -382,7 +382,7 @@ def get_qty_amount_data_for_cumulative(pr_doc, doc, items=[]): `tab{child_doc}`.amount FROM `tab{child_doc}`, `tab{parent_doc}` WHERE - `tab{child_doc}`.parent = `tab{parent_doc}`.name and {date_field} + `tab{child_doc}`.parent = `tab{parent_doc}`.name and `tab{parent_doc}`.{date_field} between %s and %s and `tab{parent_doc}`.docstatus = 1 {condition} group by `tab{child_doc}`.name """.format(parent_doc = doctype, From e8f95a2adf33913fd2b4feee912faf97023b264e Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 5 Aug 2019 14:21:09 +0530 Subject: [PATCH 095/124] fix: TreeView fixes --- .../doctype/quality_procedure/quality_procedure.json | 10 +++++----- .../doctype/quality_procedure/quality_procedure.py | 8 +++----- .../quality_procedure/quality_procedure_tree.js | 10 +++------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json index 7b241ef787..472b75103c 100644 --- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json +++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json @@ -1,11 +1,11 @@ { - "autoname": "format:PRC-{procedure}", + "autoname": "format:PRC-{quality_procedure_name}", "creation": "2018-10-06 00:06:29.756804", "doctype": "DocType", "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "procedure", + "quality_procedure_name", "parent_quality_procedure", "is_group", "sb_00", @@ -62,14 +62,14 @@ "options": "Quality Procedure Process" }, { - "fieldname": "procedure", + "fieldname": "quality_procedure_name", "fieldtype": "Data", "in_list_view": 1, - "label": "Procedure", + "label": "Quality Procedure", "reqd": 1 } ], - "modified": "2019-05-26 22:11:53.771428", + "modified": "2019-08-05 13:09:29.945082", "modified_by": "Administrator", "module": "Quality Management", "name": "Quality Procedure", diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py index 52c3320840..4d3c522956 100644 --- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py +++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py @@ -36,12 +36,10 @@ class QualityProcedure(NestedSet): doc.load_from_db() for process in doc.processes: - if process.procedure: - flag_is_group = 1 + flag_is_group = 1 if process.procedure else 0 - if flag_is_group == 0: - doc.is_group = 0 - doc.save(ignore_permissions=True) + doc.is_group = 0 if flag_is_group == 0 else 1 + doc.save(ignore_permissions=True) def set_parent(self): for process in self.processes: diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure_tree.js b/erpnext/quality_management/doctype/quality_procedure/quality_procedure_tree.js index 15b7784dbd..8fd785f205 100644 --- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure_tree.js +++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure_tree.js @@ -6,8 +6,8 @@ frappe.treeview_settings["Quality Procedure"] = { add_tree_node: 'erpnext.quality_management.doctype.quality_procedure.quality_procedure.add_node', filters: [ { - fieldname: "Quality Procedure", - fieldtype:"Link", + fieldname: "quality_procedure", + fieldtype: "Link", options: "Quality Procedure", label: __("Quality Procedure"), get_query: function() { @@ -19,7 +19,7 @@ frappe.treeview_settings["Quality Procedure"] = { ], breadcrumb: "Setup", root_label: "All Quality Procedures", - get_tree_root: false, + get_tree_root: true, menu_items: [ { label: __("New Quality Procedure"), @@ -32,8 +32,4 @@ frappe.treeview_settings["Quality Procedure"] = { onload: function(treeview) { treeview.make_tree(); }, - onrender: function() { - $("button:contains('Add Child')").remove(); - $("button:contains('New')").remove(); - } }; \ No newline at end of file From c5ae3cc120838341db71405ec228700873e066bb Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Wed, 7 Aug 2019 16:41:13 +0550 Subject: [PATCH 096/124] bumped to version 12.0.5 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 260478f730..0a735a1da1 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '12.0.4' +__version__ = '12.0.5' def get_default_company(user=None): '''Get default company for user''' From 226083893392546b2cb4133cdce078fe62077817 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 7 Aug 2019 17:21:22 +0530 Subject: [PATCH 097/124] fix(Item Template): Fallback description string Fixes #18572 --- erpnext/templates/generators/item/item_details.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/templates/generators/item/item_details.html b/erpnext/templates/generators/item/item_details.html index 8e560333ae..4cbecb0215 100644 --- a/erpnext/templates/generators/item/item_details.html +++ b/erpnext/templates/generators/item/item_details.html @@ -9,9 +9,9 @@

-{% if frappe.utils.strip_html(doc.web_long_description) %} +{% if frappe.utils.strip_html(doc.web_long_description or '') %} {{ doc.web_long_description | safe }} -{% elif frappe.utils.strip_html(doc.description) %} +{% elif frappe.utils.strip_html(doc.description or '') %} {{ doc.description | safe }} {% else %} {{ _("No description given") }} From b9f2a6048be8f448c7d6ba792c80786c712aa295 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 7 Aug 2019 18:21:38 +0530 Subject: [PATCH 098/124] test: fix test cases --- .../doctype/quality_procedure/test_quality_procedure.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py b/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py index 79f8771395..3289bb5a37 100644 --- a/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py +++ b/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py @@ -18,7 +18,7 @@ class TestQualityProcedure(unittest.TestCase): def create_procedure(): procedure = frappe.get_doc({ "doctype": "Quality Procedure", - "procedure": "_Test Quality Procedure", + "quality_procedure_name": "_Test Quality Procedure", "processes": [ { "process_description": "_Test Quality Procedure Table", @@ -37,7 +37,7 @@ def create_procedure(): def create_nested_procedure(): nested_procedure = frappe.get_doc({ "doctype": "Quality Procedure", - "procedure": "_Test Nested Quality Procedure", + "quality_procedure_name": "_Test Nested Quality Procedure", "processes": [ { "procedure": "PRC-_Test Quality Procedure" From e5c733bdb399ba1a7d206207f7784297c9b7b3f1 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 8 Aug 2019 15:44:11 +0530 Subject: [PATCH 099/124] fix: Accounting period (#18630) * fix: accounting period * test: accounting period * fix: account period creation * fix: remove status field from accounting period --- .../accounting_period/accounting_period.json | 36 +----------- .../accounting_period/accounting_period.py | 11 ++-- .../test_accounting_period.py | 57 ++++++++++++------- erpnext/accounts/general_ledger.py | 23 ++++++++ 4 files changed, 70 insertions(+), 57 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.json b/erpnext/accounts/doctype/accounting_period/accounting_period.json index ed30b83c26..57f8e32dc6 100644 --- a/erpnext/accounts/doctype/accounting_period/accounting_period.json +++ b/erpnext/accounts/doctype/accounting_period/accounting_period.json @@ -167,39 +167,7 @@ "set_only_once": 0, "translatable": 0, "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Status", - "length": 0, - "no_copy": 0, - "options": "Open\nClosed", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -273,7 +241,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-04-13 19:14:47.593753", + "modified": "2019-08-01 19:14:47.593753", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting Period", diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py index de45f3a252..180460c091 100644 --- a/erpnext/accounts/doctype/accounting_period/accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py @@ -7,6 +7,8 @@ import frappe from frappe.model.document import Document from frappe import _ +class OverlapError(frappe.ValidationError): pass + class AccountingPeriod(Document): def validate(self): self.validate_overlap() @@ -34,12 +36,13 @@ class AccountingPeriod(Document): }, as_dict=True) if len(existing_accounting_period) > 0: - frappe.throw(_("Accounting Period overlaps with {0}".format(existing_accounting_period[0].get("name")))) + frappe.throw(_("Accounting Period overlaps with {0}") + .format(existing_accounting_period[0].get("name")), OverlapError) def get_doctypes_for_closing(self): docs_for_closing = [] - #if not self.closed_documents or len(self.closed_documents) == 0: - doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", "Bank Reconciliation", "Asset", "Purchase Order", "Sales Order", "Leave Application", "Leave Allocation", "Stock Entry"] + doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", "Bank Reconciliation", + "Asset", "Purchase Order", "Sales Order", "Leave Application", "Leave Allocation", "Stock Entry"] closed_doctypes = [{"document_type": doctype, "closed": 1} for doctype in doctypes] for closed_doctype in closed_doctypes: docs_for_closing.append(closed_doctype) @@ -52,4 +55,4 @@ class AccountingPeriod(Document): self.append('closed_documents', { "document_type": doctype_for_closing.document_type, "closed": doctype_for_closing.closed - }) + }) \ No newline at end of file diff --git a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py index 29deefdbed..022d7a7e80 100644 --- a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py @@ -5,23 +5,42 @@ from __future__ import unicode_literals import frappe import unittest +from frappe.utils import nowdate, add_months +from erpnext.accounts.general_ledger import ClosedAccountingPeriod +from erpnext.accounts.doctype.accounting_period.accounting_period import OverlapError +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice -# class TestAccountingPeriod(unittest.TestCase): -# def test_overlap(self): -# ap1 = create_accounting_period({"start_date":"2018-04-01", "end_date":"2018-06-30", "company":"Wind Power LLC"}) -# ap1.save() -# ap2 = create_accounting_period({"start_date":"2018-06-30", "end_date":"2018-07-10", "company":"Wind Power LLC"}) -# self.assertRaises(frappe.OverlapError, accounting_period_2.save()) -# -# def tearDown(self): -# pass -# -# -# def create_accounting_period(**args): -# accounting_period = frappe.new_doc("Accounting Period") -# accounting_period.start_date = args.start_date or frappe.utils.datetime.date(2018, 4, 1) -# accounting_period.end_date = args.end_date or frappe.utils.datetime.date(2018, 6, 30) -# accounting_period.company = args.company -# accounting_period.period_name = "_Test_Period_Name_1" -# -# return accounting_period +class TestAccountingPeriod(unittest.TestCase): + def test_overlap(self): + ap1 = create_accounting_period(start_date = "2018-04-01", + end_date = "2018-06-30", company = "Wind Power LLC") + ap1.save() + + ap2 = create_accounting_period(start_date = "2018-06-30", + end_date = "2018-07-10", company = "Wind Power LLC", period_name = "Test Accounting Period 1") + self.assertRaises(OverlapError, ap2.save) + + def test_accounting_period(self): + ap1 = create_accounting_period(period_name = "Test Accounting Period 2") + ap1.save() + + doc = create_sales_invoice(do_not_submit=1, cost_center = "_Test Company - _TC", warehouse = "Stores - _TC") + self.assertRaises(ClosedAccountingPeriod, doc.submit) + + def tearDown(self): + for d in frappe.get_all("Accounting Period"): + frappe.delete_doc("Accounting Period", d.name) + +def create_accounting_period(**args): + args = frappe._dict(args) + + accounting_period = frappe.new_doc("Accounting Period") + accounting_period.start_date = args.start_date or nowdate() + accounting_period.end_date = args.end_date or add_months(nowdate(), 1) + accounting_period.company = args.company or "_Test Company" + accounting_period.period_name =args.period_name or "_Test_Period_Name_1" + accounting_period.append("closed_documents", { + "document_type": 'Sales Invoice', "closed": 1 + }) + + return accounting_period \ No newline at end of file diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index be1448df3a..5c9e93d019 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -10,11 +10,13 @@ from erpnext.accounts.doctype.budget.budget import validate_expense_against_budg from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions +class ClosedAccountingPeriod(frappe.ValidationError): pass class StockAccountInvalidTransaction(frappe.ValidationError): pass def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes', from_repost=False): if gl_map: if not cancel: + validate_accounting_period(gl_map) gl_map = process_gl_map(gl_map, merge_entries) if gl_map and len(gl_map) > 1: save_entries(gl_map, adv_adj, update_outstanding, from_repost) @@ -23,6 +25,27 @@ def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, upd else: delete_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding) +def validate_accounting_period(gl_map): + accounting_periods = frappe.db.sql(""" SELECT + ap.name as name + FROM + `tabAccounting Period` ap, `tabClosed Document` cd + WHERE + ap.name = cd.parent + AND ap.company = %(company)s + AND cd.closed = 1 + AND cd.document_type = %(voucher_type)s + AND %(date)s between ap.start_date and ap.end_date + """, { + 'date': gl_map[0].posting_date, + 'company': gl_map[0].company, + 'voucher_type': gl_map[0].voucher_type + }, as_dict=1) + + if accounting_periods: + frappe.throw(_("You can't create accounting entries in the closed accounting period {0}") + .format(accounting_periods[0].name), ClosedAccountingPeriod) + def process_gl_map(gl_map, merge_entries=True): if merge_entries: gl_map = merge_similar_entries(gl_map) From f19b7b9122061ac7400e12d6371aa04486a24c92 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 8 Aug 2019 15:48:09 +0530 Subject: [PATCH 100/124] fix(quickbooks): Do not build global search for QuickBooks Migrator (#18627) --- .../quickbooks_migrator.json | 734 ++---------------- 1 file changed, 52 insertions(+), 682 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.json b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.json index b156006e28..5428177914 100644 --- a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.json +++ b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.json @@ -1,843 +1,213 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, "beta": 1, "creation": "2018-07-10 14:48:16.757030", - "custom": 0, - "docstatus": 0, "doctype": "DocType", - "document_type": "", "editable_grid": 1, "engine": "InnoDB", + "field_order": [ + "status", + "application_settings", + "client_id", + "redirect_url", + "token_endpoint", + "application_column_break", + "client_secret", + "scope", + "api_endpoint", + "authorization_settings", + "authorization_endpoint", + "refresh_token", + "code", + "authorization_column_break", + "authorization_url", + "access_token", + "quickbooks_company_id", + "company_settings", + "company", + "default_shipping_account", + "default_warehouse", + "company_column_break", + "default_cost_center", + "undeposited_funds_account" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "status", "fieldtype": "Select", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Status", - "length": 0, - "no_copy": 0, - "options": "Connecting to QuickBooks\nConnected to QuickBooks\nIn Progress\nComplete\nFailed", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Connecting to QuickBooks\nConnected to QuickBooks\nIn Progress\nComplete\nFailed" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, "collapsible_depends_on": "eval:doc.client_id && doc.client_secret && doc.redirect_url", - "columns": 0, "fieldname": "application_settings", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Application Settings", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Application Settings" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", "fieldname": "client_id", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Client ID", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", "fieldname": "redirect_url", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Redirect URL", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer", "fieldname": "token_endpoint", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Token Endpoint", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "application_column_break", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", "fieldname": "client_secret", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Client Secret", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "com.intuit.quickbooks.accounting", "fieldname": "scope", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Scope", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "https://quickbooks.api.intuit.com/v3", "fieldname": "api_endpoint", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "API Endpoint", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, - "columns": 0, "fieldname": "authorization_settings", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Authorization Settings", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Authorization Settings" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "https://appcenter.intuit.com/connect/oauth2", "fieldname": "authorization_endpoint", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Authorization Endpoint", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "refresh_token", "fieldtype": "Small Text", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Refresh Token", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Refresh Token" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "code", "fieldtype": "Data", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Code", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Code" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "authorization_column_break", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "authorization_url", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Authorization URL", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "access_token", "fieldtype": "Small Text", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Access Token", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Access Token" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "quickbooks_company_id", "fieldtype": "Data", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Quickbooks Company ID", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Quickbooks Company ID" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "company_settings", "fieldtype": "Section Break", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company Settings", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Company Settings" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "company", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Company" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "default_shipping_account", "fieldtype": "Link", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Shipping Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Account" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "default_warehouse", "fieldtype": "Link", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Warehouse", - "length": 0, - "no_copy": 0, - "options": "Warehouse", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Warehouse" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "company_column_break", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "default_cost_center", "fieldtype": "Link", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Cost Center", - "length": 0, - "no_copy": 0, - "options": "Cost Center", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Cost Center" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "undeposited_funds_account", "fieldtype": "Link", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Undeposited Funds Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Account" } ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, "issingle": 1, - "istable": 0, - "max_attachments": 0, - "modified": "2018-10-17 03:12:53.506229", + "modified": "2019-08-07 15:26:00.653433", "modified_by": "Administrator", "module": "ERPNext Integrations", "name": "QuickBooks Migrator", - "name_case": "", "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, "create": 1, "delete": 1, "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, - "report": 0, "role": "System Manager", - "set_user_permissions": 0, "share": 1, - "submit": 0, "write": 1 } ], "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 1, "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 + "sort_order": "DESC" } \ No newline at end of file From df7644a96d8b2d91d7b882c3f8e18949c354681d Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Thu, 8 Aug 2019 15:50:24 +0530 Subject: [PATCH 101/124] fix: Show created serial nos as links in message (#18635) Fixes #18623 --- erpnext/stock/doctype/serial_no/serial_no.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index c203f8baa3..409a864678 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -369,10 +369,11 @@ def auto_make_serial_nos(args): elif args.get('actual_qty', 0) > 0: created_numbers.append(make_serial_no(serial_no, args)) - if len(created_numbers) == 1: - frappe.msgprint(_("Serial No {0} created").format(created_numbers[0])) - elif len(created_numbers) > 0: - frappe.msgprint(_("The following serial numbers were created:
{0}").format(', '.join(created_numbers))) + form_links = list(map(lambda d: frappe.utils.get_link_to_form('Serial No', d), created_numbers)) + if len(form_links) == 1: + frappe.msgprint(_("Serial No {0} created").format(form_links[0])) + elif len(form_links) > 0: + frappe.msgprint(_("The following serial numbers were created:
{0}").format(', '.join(form_links))) def get_item_details(item_code): return frappe.db.sql("""select name, has_batch_no, docstatus, From 04b42600b094a8ac10e31308aa6f3f4c779f470c Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Thu, 8 Aug 2019 15:51:50 +0530 Subject: [PATCH 102/124] fix: Changes in print format due to attribute name changes in frappe (#18641) --- .../sales_invoice_return/sales_invoice_return.html | 8 ++++---- erpnext/templates/print_formats/includes/taxes.html | 4 ++-- erpnext/templates/print_formats/includes/total.html | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html index 889b7f71aa..2c015192c4 100644 --- a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html +++ b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html @@ -4,7 +4,7 @@ {%- macro render_currency(df, doc) -%}
+ {%- if doc.align_labels_right %} text-right{%- endif -%}">
@@ -23,7 +23,7 @@ {%- for charge in data -%} {%- if (charge.tax_amount or doc.flags.print_taxes_with_zero_amount) and (not charge.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}
-
+
{{ frappe.utils.fmt_money((charge.tax_amount)|int|abs, currency=doc.currency) }} @@ -103,8 +103,8 @@ {% for section in page %}
{% if section.columns.fields %} - {%- if doc._line_breaks and loop.index != 1 -%}
{%- endif -%} - {%- if doc._show_section_headings and section.label and section.has_data -%} + {%- if doc.print_line_breaks and loop.index != 1 -%}
{%- endif -%} + {%- if doc.print_section_headings and section.label and section.has_data -%}

{{ _(section.label) }}

{% endif %} {%- endif -%} diff --git a/erpnext/templates/print_formats/includes/taxes.html b/erpnext/templates/print_formats/includes/taxes.html index 377f9a34bd..6e984f3901 100644 --- a/erpnext/templates/print_formats/includes/taxes.html +++ b/erpnext/templates/print_formats/includes/taxes.html @@ -1,7 +1,7 @@ {%- macro render_discount_amount(doc) -%} {%- if doc.discount_amount -%}
-
+
- {{ doc.get_formatted("discount_amount", doc) }} @@ -19,7 +19,7 @@ {%- for charge in data -%} {%- if (charge.tax_amount or doc.flags.print_taxes_with_zero_amount) and (not charge.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}
-
+
{{ frappe.format_value(frappe.utils.flt(charge.tax_amount), diff --git a/erpnext/templates/print_formats/includes/total.html b/erpnext/templates/print_formats/includes/total.html index c13bf92760..81799809ba 100644 --- a/erpnext/templates/print_formats/includes/total.html +++ b/erpnext/templates/print_formats/includes/total.html @@ -1,12 +1,12 @@
{% if doc.flags.show_inclusive_tax_in_print %} -
+
{{ doc.get_formatted("net_total", doc) }}
{% else %} -
+
{{ doc.get_formatted("total", doc) }} From f729eed03563b44e64603450af38b6c8675d4d52 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Thu, 8 Aug 2019 15:52:25 +0530 Subject: [PATCH 103/124] fix: Show Cr or Dr symbol in chart of accounts based on balance (#18654) * fix: Show Cr or Dr symbol in chart of accounts based on balance * fix: Typo fix in comment --- erpnext/accounts/doctype/account/account_tree.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js index b70c6d2b27..6fdd797437 100644 --- a/erpnext/accounts/doctype/account/account_tree.js +++ b/erpnext/accounts/doctype/account/account_tree.js @@ -121,7 +121,10 @@ frappe.treeview_settings["Account"] = { }, onrender: function(node) { if(frappe.boot.user.can_read.indexOf("GL Entry") !== -1){ - var dr_or_cr = in_list(["Liability", "Income", "Equity"], node.data.root_type) ? "Cr" : "Dr"; + + // show Dr if positive since balance is calculated as debit - credit else show Cr + let dr_or_cr = node.data.balance_in_account_currency > 0 ? "Dr": "Cr"; + if (node.data && node.data.balance!==undefined) { $('' + (node.data.balance_in_account_currency ? From 536e6bf57cac98af4b99a0d6e2e5fd46e71420f2 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 8 Aug 2019 17:40:57 +0530 Subject: [PATCH 104/124] fix: group by condition in the payment reconciliation (#18657) --- .../doctype/payment_reconciliation/payment_reconciliation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index b74eed5841..5bb269ee7e 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -93,7 +93,7 @@ class PaymentReconciliation(Document): and `tab{doc}`.is_return = 1 and `tabGL Entry`.against_voucher_type = %(voucher_type)s and `tab{doc}`.docstatus = 1 and `tabGL Entry`.party = %(party)s and `tabGL Entry`.party_type = %(party_type)s and `tabGL Entry`.account = %(account)s - GROUP BY `tabSales Invoice`.name + GROUP BY `tab{doc}`.name Having amount > 0 """.format(doc=voucher_type, dr_or_cr=dr_or_cr, reconciled_dr_or_cr=reconciled_dr_or_cr), { From 9f9184c908212dc87b8ec435154e6a00220685d0 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 8 Aug 2019 17:41:38 +0530 Subject: [PATCH 105/124] fix: not able to transfer raw materials for subcontracted items (#18650) --- erpnext/buying/doctype/purchase_order/purchase_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 8117d9d514..6ed6766288 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -483,7 +483,7 @@ def make_rm_stock_entry(purchase_order, rm_items): 'from_warehouse': rm_item_data["warehouse"], 'stock_uom': rm_item_data["stock_uom"], 'main_item_code': rm_item_data["item_code"], - 'allow_alternative_item': item_wh[rm_item_code].get('allow_alternative_item') + 'allow_alternative_item': item_wh.get(rm_item_code, {}).get('allow_alternative_item') } } stock_entry.add_to_stock_entry_detail(items_dict) From cfd19afabf7e9ddc7253d72567b4486fc107fab3 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Thu, 8 Aug 2019 17:45:44 +0530 Subject: [PATCH 106/124] fix: Set Maintenance Status fields as Read Only (#18633) Maintenance Status is set based on warranty_expiry_date and amc_expiry_date. Even if they are editable they are set programmatically server side. Better to make them as read only. --- .../stock/doctype/serial_no/serial_no.json | 1408 ++--------------- 1 file changed, 94 insertions(+), 1314 deletions(-) diff --git a/erpnext/stock/doctype/serial_no/serial_no.json b/erpnext/stock/doctype/serial_no/serial_no.json index 8c3dafe8ba..712aadc525 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.json +++ b/erpnext/stock/doctype/serial_no/serial_no.json @@ -1,1691 +1,471 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 1, "autoname": "field:serial_no", - "beta": 0, "creation": "2013-05-16 10:59:15", - "custom": 0, "description": "Distinct unit of an Item", - "docstatus": 0, "doctype": "DocType", "document_type": "Setup", - "editable_grid": 0, + "field_order": [ + "details", + "column_break0", + "serial_no", + "item_code", + "warehouse", + "batch_no", + "column_break1", + "item_name", + "description", + "item_group", + "brand", + "sales_order", + "purchase_details", + "column_break2", + "purchase_document_type", + "purchase_document_no", + "purchase_date", + "purchase_time", + "purchase_rate", + "column_break3", + "supplier", + "supplier_name", + "asset_details", + "asset", + "asset_status", + "column_break_24", + "location", + "employee", + "delivery_details", + "delivery_document_type", + "delivery_document_no", + "delivery_date", + "delivery_time", + "is_cancelled", + "column_break5", + "customer", + "customer_name", + "invoice_details", + "sales_invoice", + "warranty_amc_details", + "column_break6", + "warranty_expiry_date", + "amc_expiry_date", + "column_break7", + "maintenance_status", + "warranty_period", + "more_info", + "serial_no_details", + "company" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "details", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "oldfieldtype": "Section Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break0", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "serial_no", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Serial No", - "length": 0, "no_copy": 1, "oldfieldname": "serial_no", "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, "unique": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "item_code", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 1, "label": "Item Code", - "length": 0, - "no_copy": 0, "oldfieldname": "item_code", "oldfieldtype": "Link", "options": "Item", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "description": "Warehouse can only be changed via Stock Entry / Delivery Note / Purchase Receipt", "fieldname": "warehouse", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 1, "label": "Warehouse", - "length": 0, "no_copy": 1, "oldfieldname": "warehouse", "oldfieldtype": "Link", "options": "Warehouse", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "search_index": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "batch_no", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 1, "label": "Batch No", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "item_name", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Item Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "description", "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Description", - "length": 0, - "no_copy": 0, "oldfieldname": "description", "oldfieldtype": "Text", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, "width": "300px" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", "fieldname": "item_group", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Item Group", - "length": 0, - "no_copy": 0, "oldfieldname": "item_group", "oldfieldtype": "Link", "options": "Item Group", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "brand", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Brand", - "length": 0, - "no_copy": 0, "oldfieldname": "brand", "oldfieldtype": "Link", "options": "Brand", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "sales_order", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Sales Order", - "length": 0, - "no_copy": 0, - "options": "Sales Order", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Sales Order" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "purchase_details", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Purchase / Manufacture Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Purchase / Manufacture Details" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break2", "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, "width": "50%" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "purchase_document_type", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Creation Document Type", - "length": 0, "no_copy": 1, "options": "DocType", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "purchase_document_no", "fieldtype": "Dynamic Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Creation Document No", - "length": 0, "no_copy": 1, "options": "purchase_document_type", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "purchase_date", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Creation Date", - "length": 0, "no_copy": 1, "oldfieldname": "purchase_date", "oldfieldtype": "Date", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "purchase_time", "fieldtype": "Time", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Creation Time", - "length": 0, "no_copy": 1, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "purchase_rate", "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Incoming Rate", - "length": 0, "no_copy": 1, "oldfieldname": "purchase_rate", "oldfieldtype": "Currency", "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break3", "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, "width": "50%" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "supplier", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Supplier", - "length": 0, "no_copy": 1, - "options": "Supplier", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Supplier" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, "fieldname": "supplier_name", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Supplier Name", - "length": 0, "no_copy": 1, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "asset_details", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Asset Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Asset Details" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "asset", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Asset", - "length": 0, "no_copy": 1, "options": "Asset", - "permlevel": 0, - "precision": "", "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "asset", "fieldname": "asset_status", "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Asset Status", - "length": 0, - "no_copy": 0, "options": "\nIssue\nReceipt\nTransfer", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break_24", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "location", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Location", - "length": 0, - "no_copy": 0, "options": "Location", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "employee", "fieldtype": "Link", - "hidden": 0, "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Employee", - "length": 0, - "no_copy": 0, "options": "Employee", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "delivery_details", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Delivery Details", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Column Break", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "oldfieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "delivery_document_type", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Delivery Document Type", - "length": 0, "no_copy": 1, "options": "DocType", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "delivery_document_no", "fieldtype": "Dynamic Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Delivery Document No", - "length": 0, "no_copy": 1, "options": "delivery_document_type", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "delivery_date", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Delivery Date", - "length": 0, "no_copy": 1, "oldfieldname": "delivery_date", "oldfieldtype": "Date", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "delivery_time", "fieldtype": "Time", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Delivery Time", - "length": 0, "no_copy": 1, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "is_cancelled", "fieldtype": "Select", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Is Cancelled", - "length": 0, - "no_copy": 0, "oldfieldname": "is_cancelled", "oldfieldtype": "Select", "options": "\nYes\nNo", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "report_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break5", "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, "width": "50%" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "customer", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Customer", - "length": 0, "no_copy": 1, "oldfieldname": "customer", "oldfieldtype": "Link", "options": "Customer", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, "fieldname": "customer_name", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Customer Name", - "length": 0, "no_copy": 1, "oldfieldname": "customer_name", "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "invoice_details", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Invoice Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Invoice Details" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "sales_invoice", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Sales Invoice", - "length": 0, - "no_copy": 0, "options": "Sales Invoice", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "warranty_amc_details", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Warranty / AMC Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Warranty / AMC Details" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break6", "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, "width": "50%" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "maintenance_status", "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Maintenance Status", - "length": 0, - "no_copy": 0, "oldfieldname": "maintenance_status", "oldfieldtype": "Select", "options": "\nUnder Warranty\nOut of Warranty\nUnder AMC\nOut of AMC", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, + "read_only": 1, "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0, "width": "150px" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "warranty_period", "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Warranty Period (Days)", - "length": 0, - "no_copy": 0, "oldfieldname": "warranty_period", "oldfieldtype": "Int", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, + "read_only": 1, "width": "150px" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break7", "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, "width": "50%" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "warranty_expiry_date", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Warranty Expiry Date", - "length": 0, - "no_copy": 0, "oldfieldname": "warranty_expiry_date", "oldfieldtype": "Date", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, "width": "150px" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "amc_expiry_date", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "AMC Expiry Date", - "length": 0, - "no_copy": 0, "oldfieldname": "amc_expiry_date", "oldfieldtype": "Date", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, "width": "150px" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "more_info", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "More Information", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "More Information" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "serial_no_details", "fieldtype": "Text Editor", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Serial No Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Serial No Details" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "company", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Company", - "length": 0, - "no_copy": 0, "options": "Company", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, "read_only": 1, "remember_last_selected_value": 1, - "report_hide": 0, "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "search_index": 1 } ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, "icon": "fa fa-barcode", "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-10-19 12:38:34.448513", + "modified": "2019-08-07 17:28:32.243280", "modified_by": "Administrator", "module": "Stock", "name": "Serial No", "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, "create": 1, "delete": 1, "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "Item Manager", - "set_user_permissions": 0, "share": 1, - "submit": 0, "write": 1 }, { - "amend": 0, - "cancel": 0, "create": 1, "delete": 1, "email": 1, "export": 1, - "if_owner": 0, "import": 1, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "Stock Manager", "set_user_permissions": 1, - "share": 0, - "submit": 0, "write": 1 }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, "report": 1, - "role": "Stock User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 + "role": "Stock User" } ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, "search_fields": "item_code", "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + "track_changes": 1 } \ No newline at end of file From 10e8073204ec2f4b2be32dcc89ef6000152af8cc Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 8 Aug 2019 18:19:24 +0530 Subject: [PATCH 107/124] fix: allow to subcotract service raw materials --- erpnext/controllers/buying_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 0b4d38ce5c..5c51a2c7bd 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -725,7 +725,7 @@ def get_items_from_bom(item_code, bom, exploded_item=1): where t2.parent = t1.name and t1.item = %s and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s - and t2.item_code = t3.name and t3.is_stock_item = 1""".format(doctype), + and t2.item_code = t3.name""".format(doctype), (item_code, bom), as_dict=1) if not bom_items: From 24c3b4e00ffab02eb47d7a22f4fda3da91bd94ff Mon Sep 17 00:00:00 2001 From: Anurag Mishra Date: Fri, 9 Aug 2019 13:27:59 +0530 Subject: [PATCH 108/124] fix: get item from product bundle --- erpnext/public/js/controllers/buying.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js index acc09ed213..118aee9a8c 100644 --- a/erpnext/public/js/controllers/buying.js +++ b/erpnext/public/js/controllers/buying.js @@ -452,7 +452,8 @@ erpnext.buying.get_items_from_product_bundle = function(frm) { company: frm.doc.company, is_subcontracted: frm.doc.is_subcontracted, transaction_date: frm.doc.transaction_date || frm.doc.posting_date, - ignore_pricing_rule: frm.doc.ignore_pricing_rule + ignore_pricing_rule: frm.doc.ignore_pricing_rule, + doctype: frm.doc.doctype } }, freeze: true, From 9839a9afb0f4c38e1a008b263e0d8212de6b6fab Mon Sep 17 00:00:00 2001 From: marination Date: Fri, 9 Aug 2019 15:54:18 +0530 Subject: [PATCH 109/124] fix: Fixed error message in Payment Entry for outstanding invoices not found via filters --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index da6b167880..401d1806f2 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -624,7 +624,7 @@ def get_outstanding_reference_documents(args): data = negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed if not data: - frappe.msgprint(_("No outstanding invoices found for the {0} {1}.") + frappe.msgprint(_("No outstanding invoices found for the {0} {1} which qualify the filters you have specified") .format(args.get("party_type").lower(), args.get("party"))) return data From dabcb6b5314886433663d720218ac221c7d85b18 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 11 Aug 2019 10:58:16 +0530 Subject: [PATCH 110/124] fix: GSTR 3B report fixes --- .../doctype/gstr_3b_report/gstr_3b_report.js | 8 +- .../gstr_3b_report/gstr_3b_report.json | 304 ++++-------------- .../doctype/gstr_3b_report/gstr_3b_report.py | 48 +-- 3 files changed, 90 insertions(+), 270 deletions(-) diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js index 0d6cef0792..a1cea8f609 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js @@ -2,7 +2,7 @@ // For license information, please see license.txt frappe.ui.form.on('GSTR 3B Report', { - refresh : function(frm){ + refresh : function(frm) { if(!frm.is_new()) { frm.set_intro(__("Please save the report again to rebuild or update")); frm.add_custom_button(__('Download JSON'), function() { @@ -39,9 +39,13 @@ frappe.ui.form.on('GSTR 3B Report', { }); }); } + + let current_year = new Date().getFullYear(); + let options = [current_year, current_year-1, current_year-2]; + frm.set_df_property('year', 'options', options); }, - setup: function(frm){ + setup: function(frm) { frm.set_query('company_address', function(doc) { if(!doc.company) { frappe.throw(__('Please set Company')); diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json index 7b0462fd4b..548d40b974 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json @@ -1,259 +1,73 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "format:GSTR3B-{month}-{year}-{company_address}", - "beta": 0, - "creation": "2019-02-04 11:35:55.964639", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "autoname": "format:GSTR3B-{month}-{year}-{company_address}", + "creation": "2019-02-04 11:35:55.964639", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "company", + "company_address", + "year", + "month", + "json_output", + "missing_field_invoices" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company_address", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company Address", - "length": 0, - "no_copy": 0, - "options": "Address", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "company_address", + "fieldtype": "Link", + "label": "Company Address", + "options": "Address" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "year", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Year", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "year", + "fieldtype": "Select", + "label": "Year" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "month", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Month", - "length": 0, - "no_copy": 0, - "options": "January\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "month", + "fieldtype": "Select", + "label": "Month", + "options": "January\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "json_output", - "fieldtype": "Code", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "JSON Output", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "json_output", + "fieldtype": "Code", + "label": "JSON Output" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "missing_field_invoices", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Invoices with no Place Of Supply", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "missing_field_invoices", + "fieldtype": "Small Text", + "label": "Invoices with no Place Of Supply", + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-03-04 10:04:44.767655", - "modified_by": "Administrator", - "module": "Regional", - "name": "GSTR 3B Report", - "name_case": "", - "owner": "Administrator", + ], + "modified": "2019-08-10 22:30:26.727038", + "modified_by": "Administrator", + "module": "Regional", + "name": "GSTR 3B Report", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py index aad267e90a..79dace7925 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py @@ -329,28 +329,29 @@ class GSTR3BReport(Document): d.gst_category, [] ) - if state_number != d.place_of_supply.split("-")[0]: - inter_state_supply_details[d.gst_category].append({ - "pos": d.place_of_supply, - "txval": flt(d.total, 2), - "iamt": flt(inter_state_supply_tax_mapping.get(d.place_of_supply), 2) - }) - else: - osup_det = self.report_dict["sup_details"]["osup_det"] - osup_det["txval"] = flt(osup_det["txval"] + d.total, 2) - osup_det["camt"] = flt(osup_det["camt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2) - osup_det["samt"] = flt(osup_det["samt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2) + if d.place_of_supply: + if state_number != d.place_of_supply.split("-")[0]: + inter_state_supply_details[d.gst_category].append({ + "pos": d.place_of_supply.split("-")[0], + "txval": flt(d.total, 2), + "iamt": flt(inter_state_supply_tax_mapping.get(d.place_of_supply), 2) + }) + else: + osup_det = self.report_dict["sup_details"]["osup_det"] + osup_det["txval"] = flt(osup_det["txval"] + d.total, 2) + osup_det["camt"] = flt(osup_det["camt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2) + osup_det["samt"] = flt(osup_det["samt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2) return inter_state_supply_details def get_inward_nil_exempt(self, state): - inward_nil_exempt = frappe.db.sql(""" select a.gst_state, sum(i.base_amount) as base_amount, - i.is_nil_exempt, i.is_non_gst from `tabPurchase Invoice` p , `tabPurchase Invoice Item` i, `tabAddress` a - where p.docstatus = 1 and p.name = i.parent and p.supplier_address = a.name + inward_nil_exempt = frappe.db.sql(""" select p.place_of_supply, sum(i.base_amount) as base_amount, + i.is_nil_exempt, i.is_non_gst from `tabPurchase Invoice` p , `tabPurchase Invoice Item` i + where p.docstatus = 1 and p.name = i.parent and i.is_nil_exempt = 1 or i.is_non_gst = 1 and month(p.posting_date) = %s and year(p.posting_date) = %s and p.company = %s and p.company_gstin = %s - group by a.gst_state """, (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) + group by p.place_of_supply """, (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) inward_nil_exempt_details = { "gst": { @@ -364,14 +365,15 @@ class GSTR3BReport(Document): } for d in inward_nil_exempt: - if d.is_nil_exempt == 1 and state == d.gst_state: - inward_nil_exempt_details["gst"]["intra"] += d.base_amount - elif d.is_nil_exempt == 1 and state != d.gst_state: - inward_nil_exempt_details["gst"]["inter"] += d.base_amount - elif d.is_non_gst == 1 and state == d.gst_state: - inward_nil_exempt_details["non_gst"]["inter"] += d.base_amount - elif d.is_non_gst == 1 and state != d.gst_state: - inward_nil_exempt_details["non_gst"]["intra"] += d.base_amount + if d.place_of_supply: + if d.is_nil_exempt == 1 and state == d.place_of_supply.split("-")[1]: + inward_nil_exempt_details["gst"]["intra"] += d.base_amount + elif d.is_nil_exempt == 1 and state != d.place_of_supply.split("-")[1]: + inward_nil_exempt_details["gst"]["inter"] += d.base_amount + elif d.is_non_gst == 1 and state == d.place_of_supply.split("-")[1]: + inward_nil_exempt_details["non_gst"]["intra"] += d.base_amount + elif d.is_non_gst == 1 and state != d.place_of_supply.split("-")[1]: + inward_nil_exempt_details["non_gst"]["inter"] += d.base_amount return inward_nil_exempt_details From b87c5d83de06a4f3b4c55bba11e047abc68d910b Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 11 Aug 2019 12:40:45 +0530 Subject: [PATCH 111/124] fix: Test Cases --- erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py index de150f466e..fa33541e60 100644 --- a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py @@ -176,6 +176,9 @@ def create_purchase_invoices(): do_not_save=1 ) + pi1.place_of_supply = "29-Karnataka" + pi1.save() + pi1.submit() def make_suppliers(): From db017438851cf0b73abf23477f93bc75b8dc00b2 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 11 Aug 2019 15:47:35 +0530 Subject: [PATCH 112/124] fix: Test Case --- erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py index fa33541e60..fef73d9a0a 100644 --- a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py @@ -176,7 +176,7 @@ def create_purchase_invoices(): do_not_save=1 ) - pi1.place_of_supply = "29-Karnataka" + pi1.shipping_address = "_Test Supplier GST-1-Billing" pi1.save() pi1.submit() @@ -221,6 +221,7 @@ def make_suppliers(): "link_name": "_Test Registered Supplier" }) + address.is_shipping_address = 1 address.save() if not frappe.db.exists('Address', '_Test Supplier GST-2-Billing'): From a0b9b3cef5fe786977f00107872f6618ea799939 Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Mon, 12 Aug 2019 11:49:14 +0530 Subject: [PATCH 113/124] fix(patch): force reload child docs (#18671) --- .../v12_0/update_pricing_rule_fields.py | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/erpnext/patches/v12_0/update_pricing_rule_fields.py b/erpnext/patches/v12_0/update_pricing_rule_fields.py index 8f8349e9b5..985613a973 100644 --- a/erpnext/patches/v12_0/update_pricing_rule_fields.py +++ b/erpnext/patches/v12_0/update_pricing_rule_fields.py @@ -5,67 +5,67 @@ from __future__ import unicode_literals import frappe parentfield = { - 'item_code': 'items', - 'item_group': 'item_groups', - 'brand': 'brands' + 'item_code': 'items', + 'item_group': 'item_groups', + 'brand': 'brands' } def execute(): - if not frappe.get_all('Pricing Rule', limit=1): - return + if not frappe.get_all('Pricing Rule', limit=1): + return - frappe.reload_doc('accounts', 'doctype', 'pricing_rule_detail') - doctypes = {'Supplier Quotation': 'buying', 'Purchase Order': 'buying', 'Purchase Invoice': 'accounts', - 'Purchase Receipt': 'stock', 'Quotation': 'selling', 'Sales Order': 'selling', - 'Sales Invoice': 'accounts', 'Delivery Note': 'stock'} + frappe.reload_doc('accounts', 'doctype', 'pricing_rule_detail') + doctypes = {'Supplier Quotation': 'buying', 'Purchase Order': 'buying', 'Purchase Invoice': 'accounts', + 'Purchase Receipt': 'stock', 'Quotation': 'selling', 'Sales Order': 'selling', + 'Sales Invoice': 'accounts', 'Delivery Note': 'stock'} - for doctype, module in doctypes.items(): - frappe.reload_doc(module, 'doctype', frappe.scrub(doctype)) + for doctype, module in doctypes.items(): + frappe.reload_doc(module, 'doctype', frappe.scrub(doctype)) - child_doc = frappe.scrub(doctype) + '_item' - frappe.reload_doc(module, 'doctype', child_doc) + child_doc = frappe.scrub(doctype) + '_item' + frappe.reload_doc(module, 'doctype', child_doc, force=True) - child_doctype = doctype + ' Item' + child_doctype = doctype + ' Item' - frappe.db.sql(""" UPDATE `tab{child_doctype}` SET pricing_rules = pricing_rule - WHERE docstatus < 2 and pricing_rule is not null and pricing_rule != '' - """.format(child_doctype= child_doctype)) + frappe.db.sql(""" UPDATE `tab{child_doctype}` SET pricing_rules = pricing_rule + WHERE docstatus < 2 and pricing_rule is not null and pricing_rule != '' + """.format(child_doctype= child_doctype)) - data = frappe.db.sql(""" SELECT pricing_rule, name, parent, - parenttype, creation, modified, docstatus, modified_by, owner, name - FROM `tab{child_doc}` where docstatus < 2 and pricing_rule is not null - and pricing_rule != ''""".format(child_doc=child_doctype), as_dict=1) + data = frappe.db.sql(""" SELECT pricing_rule, name, parent, + parenttype, creation, modified, docstatus, modified_by, owner, name + FROM `tab{child_doc}` where docstatus < 2 and pricing_rule is not null + and pricing_rule != ''""".format(child_doc=child_doctype), as_dict=1) - values = [] - for d in data: - values.append((d.pricing_rule, d.name, d.parent, 'pricing_rules', d.parenttype, - d.creation, d.modified, d.docstatus, d.modified_by, d.owner, frappe.generate_hash("", 10))) + values = [] + for d in data: + values.append((d.pricing_rule, d.name, d.parent, 'pricing_rules', d.parenttype, + d.creation, d.modified, d.docstatus, d.modified_by, d.owner, frappe.generate_hash("", 10))) - if values: - frappe.db.sql(""" INSERT INTO - `tabPricing Rule Detail` (`pricing_rule`, `child_docname`, `parent`, `parentfield`, `parenttype`, - `creation`, `modified`, `docstatus`, `modified_by`, `owner`, `name`) - VALUES {values} """.format(values=', '.join(['%s'] * len(values))), tuple(values)) + if values: + frappe.db.sql(""" INSERT INTO + `tabPricing Rule Detail` (`pricing_rule`, `child_docname`, `parent`, `parentfield`, `parenttype`, + `creation`, `modified`, `docstatus`, `modified_by`, `owner`, `name`) + VALUES {values} """.format(values=', '.join(['%s'] * len(values))), tuple(values)) - frappe.reload_doc('accounts', 'doctype', 'pricing_rule') + frappe.reload_doc('accounts', 'doctype', 'pricing_rule') - for doctype, apply_on in {'Pricing Rule Item Code': 'Item Code', - 'Pricing Rule Item Group': 'Item Group', 'Pricing Rule Brand': 'Brand'}.items(): - frappe.reload_doc('accounts', 'doctype', frappe.scrub(doctype)) + for doctype, apply_on in {'Pricing Rule Item Code': 'Item Code', + 'Pricing Rule Item Group': 'Item Group', 'Pricing Rule Brand': 'Brand'}.items(): + frappe.reload_doc('accounts', 'doctype', frappe.scrub(doctype)) - field = frappe.scrub(apply_on) - data = frappe.get_all('Pricing Rule', fields=[field, "name", "creation", "modified", - "owner", "modified_by"], filters= {'apply_on': apply_on}) + field = frappe.scrub(apply_on) + data = frappe.get_all('Pricing Rule', fields=[field, "name", "creation", "modified", + "owner", "modified_by"], filters= {'apply_on': apply_on}) - values = [] - for d in data: - values.append((d.get(field), d.name, parentfield.get(field), 'Pricing Rule', - d.creation, d.modified, d.owner, d.modified_by, frappe.generate_hash("", 10))) + values = [] + for d in data: + values.append((d.get(field), d.name, parentfield.get(field), 'Pricing Rule', + d.creation, d.modified, d.owner, d.modified_by, frappe.generate_hash("", 10))) - if values: - frappe.db.sql(""" INSERT INTO - `tab{doctype}` ({field}, parent, parentfield, parenttype, creation, modified, - owner, modified_by, name) - VALUES {values} """.format(doctype=doctype, - field=field, values=', '.join(['%s'] * len(values))), tuple(values)) \ No newline at end of file + if values: + frappe.db.sql(""" INSERT INTO + `tab{doctype}` ({field}, parent, parentfield, parenttype, creation, modified, + owner, modified_by, name) + VALUES {values} """.format(doctype=doctype, + field=field, values=', '.join(['%s'] * len(values))), tuple(values)) From 83705af0b336ec7b87a7f32854e3c4a6aacd5690 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Mon, 12 Aug 2019 11:51:27 +0530 Subject: [PATCH 114/124] fix: Filters for portal quotation list (#18689) * fix: Filters for portal quotation list * fix: Remove unwanted import --- .../controllers/website_list_for_contact.py | 59 ++++++++----------- erpnext/templates/pages/rfq.py | 7 +-- 2 files changed, 29 insertions(+), 37 deletions(-) diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py index 187eaed107..0738fd506f 100644 --- a/erpnext/controllers/website_list_for_contact.py +++ b/erpnext/controllers/website_list_for_contact.py @@ -21,42 +21,45 @@ def get_list_context(context=None): def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_page_length=20, order_by="modified"): user = frappe.session.user - key = None + ignore_permissions = False if not filters: filters = [] if doctype == 'Supplier Quotation': - filters.append((doctype, "docstatus", "<", 2)) + filters.append((doctype, 'docstatus', '<', 2)) else: - filters.append((doctype, "docstatus", "=", 1)) + filters.append((doctype, 'docstatus', '=', 1)) - if (user != "Guest" and is_website_user()) or doctype == 'Request for Quotation': + if (user != 'Guest' and is_website_user()) or doctype == 'Request for Quotation': parties_doctype = 'Request for Quotation Supplier' if doctype == 'Request for Quotation' else doctype # find party for this contact customers, suppliers = get_customers_suppliers(parties_doctype, user) - if not customers and not suppliers: return [] - - key, parties = get_party_details(customers, suppliers) - - if doctype == 'Request for Quotation': - return rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length) - - filters.append((doctype, key, "in", parties)) - - if key: - return post_process(doctype, get_list_for_transactions(doctype, txt, - filters=filters, fields="name",limit_start=limit_start, - limit_page_length=limit_page_length,ignore_permissions=True, - order_by="modified desc")) + if customers: + if doctype == 'Quotation': + filters.append(('quotation_to', '=', 'Customer')) + filters.append(('party_name', 'in', customers)) + else: + filters.append(('customer', 'in', customers)) + elif suppliers: + filters.append(('supplier', 'in', suppliers)) else: return [] - return post_process(doctype, get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length, - fields="name", order_by="modified desc")) + if doctype == 'Request for Quotation': + parties = customers or suppliers + return rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length) + + # Since customers and supplier do not have direct access to internal doctypes + ignore_permissions = True + + transactions = get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length, + fields='name', ignore_permissions=ignore_permissions, order_by='modified desc') + + return post_process(doctype, transactions) def get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length=20, - ignore_permissions=False,fields=None, order_by=None): + ignore_permissions=False, fields=None, order_by=None): """ Get List of transactions like Invoices, Orders """ from frappe.www.list import get_list meta = frappe.get_meta(doctype) @@ -83,16 +86,6 @@ def get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_len return data -def get_party_details(customers, suppliers): - if customers: - key, parties = "customer", customers - elif suppliers: - key, parties = "supplier", suppliers - else: - key, parties = "customer", [] - - return key, parties - def rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length): data = frappe.db.sql("""select distinct parent as name, supplier from `tab{doctype}` where supplier = '{supplier}' and docstatus=1 order by modified desc limit {start}, {len}""". @@ -159,7 +152,7 @@ def has_website_permission(doc, ptype, user, verbose=False): doctype = doc.doctype customers, suppliers = get_customers_suppliers(doctype, user) if customers: - return frappe.db.exists(doctype, filters=get_customer_filter(doc, customers)) + return frappe.db.exists(doctype, get_customer_filter(doc, customers)) elif suppliers: fieldname = 'suppliers' if doctype == 'Request for Quotation' else 'supplier' return frappe.db.exists(doctype, filters={ @@ -175,7 +168,7 @@ def get_customer_filter(doc, customers): filters.name = doc.name filters[get_customer_field_name(doctype)] = ['in', customers] if doctype == 'Quotation': - filters.party_type = 'Customer' + filters.quotation_to = 'Customer' return filters def get_customer_field_name(doctype): diff --git a/erpnext/templates/pages/rfq.py b/erpnext/templates/pages/rfq.py index 62ec60966b..67679a1a7d 100644 --- a/erpnext/templates/pages/rfq.py +++ b/erpnext/templates/pages/rfq.py @@ -5,8 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import formatdate -from erpnext.controllers.website_list_for_contact import (get_customers_suppliers, - get_party_details) +from erpnext.controllers.website_list_for_contact import get_customers_suppliers def get_context(context): context.no_cache = 1 @@ -23,8 +22,8 @@ def get_supplier(): doctype = frappe.form_dict.doctype parties_doctype = 'Request for Quotation Supplier' if doctype == 'Request for Quotation' else doctype customers, suppliers = get_customers_suppliers(parties_doctype, frappe.session.user) - key, parties = get_party_details(customers, suppliers) - return parties[0] if key == 'supplier' else '' + + return suppliers[0] if suppliers else '' def check_supplier_has_docname_access(supplier): status = True From 677c522f01b9aa583de64cd5bc78162550fdec87 Mon Sep 17 00:00:00 2001 From: Andrew McLeod Date: Mon, 12 Aug 2019 07:36:23 +0100 Subject: [PATCH 115/124] fix: Python3 urllib use in item_group.py (now uses six.moves) (#18642) --- erpnext/setup/doctype/item_group/item_group.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index cab21162c7..33ab992568 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import frappe -import urllib import copy from frappe.utils import nowdate, cint, cstr from frappe.utils.nestedset import NestedSet @@ -12,6 +11,7 @@ from frappe.website.render import clear_cache from frappe.website.doctype.website_slideshow.website_slideshow import get_slideshow from erpnext.shopping_cart.product_info import set_product_info_for_website from erpnext.utilities.product import get_qty_in_stock +from six.moves.urllib.parse import quote class ItemGroup(NestedSet, WebsiteGenerator): nsm_parent_field = 'parent_item_group' @@ -165,7 +165,7 @@ def get_item_for_list_in_html(context): # add missing absolute link in files # user may forget it during upload if (context.get("website_image") or "").startswith("files/"): - context["website_image"] = "/" + urllib.quote(context["website_image"]) + context["website_image"] = "/" + quote(context["website_image"]) context["show_availability_status"] = cint(frappe.db.get_single_value('Products Settings', 'show_availability_status')) @@ -218,4 +218,4 @@ def get_item_group_defaults(item, company): row.pop("name") return row - return frappe._dict() \ No newline at end of file + return frappe._dict() From 19199baf29024233ded5138336c1b0c1622af1d1 Mon Sep 17 00:00:00 2001 From: Himanshu Date: Mon, 12 Aug 2019 12:17:28 +0530 Subject: [PATCH 116/124] fix: miscellaneous fixes (#18615) --- erpnext/stock/doctype/item/item.json | 1 - erpnext/stock/doctype/purchase_receipt/purchase_receipt.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index a142bb9035..383fb61f51 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -468,7 +468,6 @@ }, { "default": "0", - "depends_on": "has_batch_no", "fieldname": "retain_sample", "fieldtype": "Check", "label": "Retain Sample" diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index 7da648aad9..8266055d69 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -190,7 +190,7 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend frappe.set_route("Form", doc.doctype, doc.name); } else { - frappe.msgprint(__("Retention Stock Entry already created or Sample Quantity not provided")); + frappe.msgprint(__("Purchase Receipt doesn't have any Item for which Retain Sample is enabled.")); } } }); From cfce53103b9c206afdb1fd5d5cfa231f57961bd1 Mon Sep 17 00:00:00 2001 From: DeeMysterio Date: Mon, 12 Aug 2019 13:03:55 +0530 Subject: [PATCH 117/124] fix(delivery note): change the text invoice to sales invoice on make button (#18666) --- erpnext/stock/doctype/delivery_note/delivery_note.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js index 569a03a8f1..a88bb2ad1e 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.js +++ b/erpnext/stock/doctype/delivery_note/delivery_note.js @@ -197,7 +197,7 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend( }); if(!from_sales_invoice) { - this.frm.add_custom_button(__('Invoice'), function() { me.make_sales_invoice() }, + this.frm.add_custom_button(__('Sales Invoice'), function() { me.make_sales_invoice() }, __('Create')); } } From f841afd48dd7d1f4bfeb7db53d209c7f51071f5b Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Tue, 13 Aug 2019 15:04:18 +0550 Subject: [PATCH 118/124] bumped to version 12.0.6 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 0a735a1da1..e1c3d78d3f 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '12.0.5' +__version__ = '12.0.6' def get_default_company(user=None): '''Get default company for user''' From e14a00b887beb062c45e72b310ccb3347f3f036f Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Tue, 13 Aug 2019 17:26:56 +0530 Subject: [PATCH 119/124] fix: v12 patches sequence (#18609) --- erpnext/patches.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 33d4f55ae0..b6ea542554 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -596,6 +596,7 @@ erpnext.patches.v12_0.rename_pricing_rule_child_doctypes erpnext.patches.v12_0.move_target_distribution_from_parent_to_child erpnext.patches.v12_0.stock_entry_enhancements erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019 #25-06-2019 +erpnext.patches.v12_0.make_item_manufacturer erpnext.patches.v12_0.move_item_tax_to_item_tax_template erpnext.patches.v11_1.set_variant_based_on erpnext.patches.v11_1.woocommerce_set_creation_user @@ -606,7 +607,6 @@ erpnext.patches.v11_1.delete_scheduling_tool erpnext.patches.v12_0.rename_tolerance_fields erpnext.patches.v12_0.make_custom_fields_for_bank_remittance #14-06-2019 execute:frappe.delete_doc_if_exists("Page", "support-analytics") -erpnext.patches.v12_0.make_item_manufacturer erpnext.patches.v12_0.remove_patient_medical_record_page erpnext.patches.v11_1.move_customer_lead_to_dynamic_column erpnext.patches.v11_1.set_default_action_for_quality_inspection From 81d5265385393a2b78c936613fddffd528f3bc62 Mon Sep 17 00:00:00 2001 From: Anurag Mishra Date: Tue, 13 Aug 2019 19:40:36 +0530 Subject: [PATCH 120/124] fix: removed hard coded string --- erpnext/setup/doctype/company/company.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index da29d20503..584391e1e0 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -252,7 +252,7 @@ class Company(NestedSet): def set_mode_of_payment_account(self): cash = frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name') if cash and self.default_cash_account \ - and not frappe.db.get_value('Mode of Payment Account', {'company': self.name, 'parent': 'Cash'}): + and not frappe.db.get_value('Mode of Payment Account', {'company': self.name, 'parent': cash}): mode_of_payment = frappe.get_doc('Mode of Payment', cash) mode_of_payment.append('accounts', { 'company': self.name, From 78690d7b8b91dd825fe80593e54dea1e7172bc4b Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Wed, 14 Aug 2019 15:03:58 +0530 Subject: [PATCH 121/124] fix:payment ammount validation for pos invoices (#18663) --- .../accounts/doctype/sales_invoice/sales_invoice.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 874230052a..4f80b78c88 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -78,6 +78,7 @@ class SalesInvoice(SellingController): self.so_dn_required() self.validate_proj_cust() + self.validate_pos_return() self.validate_with_previous_doc() self.validate_uom_is_integer("stock_uom", "stock_qty") self.validate_uom_is_integer("uom", "qty") @@ -199,6 +200,16 @@ class SalesInvoice(SellingController): if "Healthcare" in active_domains: manage_invoice_submit_cancel(self, "on_submit") + def validate_pos_return(self): + + if self.is_pos and self.is_return: + total_amount_in_payments = 0 + for payment in self.payments: + total_amount_in_payments += payment.amount + + if total_amount_in_payments < self.rounded_total: + frappe.throw(_("Total payments amount can't be greater than {}".format(-self.rounded_total))) + def validate_pos_paid_amount(self): if len(self.payments) == 0 and self.is_pos: frappe.throw(_("At least one mode of payment is required for POS invoice.")) From c97a7fb845302c7d3fe7e661ab228946b3e4545d Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 14 Aug 2019 17:38:44 +0530 Subject: [PATCH 122/124] fix: restrict the payment order to non received type payment entries --- erpnext/accounts/doctype/payment_order/payment_order.js | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js index f2f00cebcb..ce9cfe527c 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.js +++ b/erpnext/accounts/doctype/payment_order/payment_order.js @@ -66,6 +66,7 @@ frappe.ui.form.on('Payment Order', { get_query_filters: { bank: frm.doc.bank, docstatus: 1, + payment_type: ("!=", "Receive"), bank_account: frm.doc.company_bank_account, paid_from: frm.doc.account, payment_order_status: ["=", "Initiated"], From d5b4b1fdaff341df5697f1e37c0b19ffd9238791 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 20 Aug 2019 12:35:15 +0530 Subject: [PATCH 123/124] fix: group by voucher consolidated showing incorrect data for deferred entries (#18777) --- .../report/general_ledger/general_ledger.py | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 86fd1088f5..ec3fb1fc9c 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -119,19 +119,11 @@ def get_gl_entries(filters): select_fields = """, debit, credit, debit_in_account_currency, credit_in_account_currency """ - group_by_statement = '' order_by_statement = "order by posting_date, account" if filters.get("group_by") == _("Group by Voucher"): order_by_statement = "order by posting_date, voucher_type, voucher_no" - if filters.get("group_by") == _("Group by Voucher (Consolidated)"): - group_by_statement = "group by voucher_type, voucher_no, account, cost_center" - - select_fields = """, sum(debit) as debit, sum(credit) as credit, - sum(debit_in_account_currency) as debit_in_account_currency, - sum(credit_in_account_currency) as credit_in_account_currency""" - if filters.get("include_default_book_entries"): filters['company_fb'] = frappe.db.get_value("Company", filters.get("company"), 'default_finance_book') @@ -144,11 +136,10 @@ def get_gl_entries(filters): against_voucher_type, against_voucher, account_currency, remarks, against, is_opening {select_fields} from `tabGL Entry` - where company=%(company)s {conditions} {group_by_statement} + where company=%(company)s {conditions} {order_by_statement} """.format( select_fields=select_fields, conditions=get_conditions(filters), - group_by_statement=group_by_statement, order_by_statement=order_by_statement ), filters, as_dict=1) @@ -185,7 +176,8 @@ def get_conditions(filters): if not (filters.get("account") or filters.get("party") or filters.get("group_by") in ["Group by Account", "Group by Party"]): conditions.append("posting_date >=%(from_date)s") - conditions.append("posting_date <=%(to_date)s") + + conditions.append("(posting_date <=%(to_date)s or is_opening = 'Yes')") if filters.get("project"): conditions.append("project in %(project)s") @@ -286,6 +278,7 @@ def initialize_gle_map(gl_entries, filters): def get_accountwise_gle(filters, gl_entries, gle_map): totals = get_totals_dict() entries = [] + consolidated_gle = OrderedDict() group_by = group_by_field(filters.get('group_by')) def update_value_in_dict(data, key, gle): @@ -310,12 +303,20 @@ def get_accountwise_gle(filters, gl_entries, gle_map): update_value_in_dict(totals, 'total', gle) if filters.get("group_by") != _('Group by Voucher (Consolidated)'): gle_map[gle.get(group_by)].entries.append(gle) - else: - entries.append(gle) + elif filters.get("group_by") == _('Group by Voucher (Consolidated)'): + key = (gle.get("voucher_type"), gle.get("voucher_no"), + gle.get("account"), gle.get("cost_center")) + if key not in consolidated_gle: + consolidated_gle.setdefault(key, gle) + else: + update_value_in_dict(consolidated_gle, key, gle) update_value_in_dict(gle_map[gle.get(group_by)].totals, 'closing', gle) update_value_in_dict(totals, 'closing', gle) + for key, value in consolidated_gle.items(): + entries.append(value) + return totals, entries def get_result_as_list(data, filters): From a8403cde168982d582563e0629f4ab38b1f7bae6 Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Tue, 20 Aug 2019 16:20:26 +0550 Subject: [PATCH 124/124] bumped to version 12.0.7 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index e1c3d78d3f..8c47111e01 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '12.0.6' +__version__ = '12.0.7' def get_default_company(user=None): '''Get default company for user'''