From e9f2b176bc71bb808b8f19f1b5a687324f0d3d92 Mon Sep 17 00:00:00 2001 From: Helkyd Date: Wed, 11 Oct 2017 15:02:27 +0100 Subject: [PATCH 01/33] Salary Detail Abbr When processing via Process Salary Abbr is not filled unless if Hourly pay ... this is required for later check what Component is or was added for Employee --- erpnext/hr/doctype/salary_slip/salary_slip.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 356104e69c..a39c171aff 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -69,7 +69,8 @@ class SalarySlip(TransactionBase): 'amount': amount, 'default_amount': amount, 'depends_on_lwp' : struct_row.depends_on_lwp, - 'salary_component' : struct_row.salary_component + 'salary_component' : struct_row.salary_component, + 'abbr' : struct_row.abbr }) else: component_row.amount = amount From 2b6bf82d6103f32f78c1d210bb708d00fc5a76e0 Mon Sep 17 00:00:00 2001 From: Helkyd Date: Wed, 22 Nov 2017 14:49:51 +0100 Subject: [PATCH 02/33] Default Payment Mode POS drafted, user retrieves the record and sets the default payment mode so that Zero payment is not done. --- erpnext/accounts/page/pos/pos.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index be0b6f7b72..b86529e753 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -1638,6 +1638,14 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ this.si_docs = this.get_doc_from_localstorage(); if (this.name) { this.update_invoice() + //to retrieve and set the default payment + invoice_data[this.name] = this.frm.doc; + invoice_data[this.name].payments[0].amount = this.frm.doc.net_total + invoice_data[this.name].payments[0].base_amount = this.frm.doc.net_total + + this.frm.doc.paid_amount = this.frm.doc.net_total + this.frm.doc.outstanding_amount = 0 + } else { this.name = $.now(); this.frm.doc.offline_pos_name = this.name; From 3264c135453f16896baa9c4a15cd5051ad894553 Mon Sep 17 00:00:00 2001 From: Helkyd Date: Wed, 22 Nov 2017 16:06:22 +0100 Subject: [PATCH 03/33] No ZERO payment If no payment mode selected does not process ... to avoid having SI with payment pending as POS for sure was paid.. --- erpnext/public/js/payment/payments.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js index 77209e093a..554566ad95 100644 --- a/erpnext/public/js/payment/payments.js +++ b/erpnext/public/js/payment/payments.js @@ -27,9 +27,14 @@ erpnext.payments = erpnext.stock.StockController.extend({ var me = this; this.dialog.set_primary_action(__("Submit"), function() { - me.dialog.hide() - me.submit_invoice() - }) + //Allow no ZERO payment + $.each(me.frm.doc.payments, function (index, data) { + if (data.amount != 0) { + me.dialog.hide(); + me.submit_invoice(); + return; + } + }); }) }, make_keyboard: function(){ From 6e3f789f82d3ddd07297c9d72ad689108b50baaf Mon Sep 17 00:00:00 2001 From: Helkyd Date: Wed, 22 Nov 2017 16:12:27 +0100 Subject: [PATCH 04/33] code fixe fixed }) --- erpnext/public/js/payment/payments.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js index 554566ad95..32523735a6 100644 --- a/erpnext/public/js/payment/payments.js +++ b/erpnext/public/js/payment/payments.js @@ -34,7 +34,8 @@ erpnext.payments = erpnext.stock.StockController.extend({ me.submit_invoice(); return; } - }); }) + }); + }) }, make_keyboard: function(){ From c14f1f145b7e30b71104c96498c6fb708511b95f Mon Sep 17 00:00:00 2001 From: tundebabzy Date: Sat, 27 Jan 2018 06:28:29 +0100 Subject: [PATCH 05/33] adjust stock_qty for expired quantities adjust based on warehouse add parameters to `get_qty_in_stock` so it can be useful in other parts of the code base --- .../setup/doctype/item_group/item_group.py | 22 +++++++- erpnext/utilities/product.py | 50 +++++++++++++++++-- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index 39172d7d11..bb1910720d 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -9,6 +9,7 @@ from frappe.utils.nestedset import NestedSet from frappe.website.website_generator import WebsiteGenerator from frappe.website.render import clear_cache from frappe.website.doctype.website_slideshow.website_slideshow import get_slideshow +from erpnext.utilities.product import get_qty_in_stock class ItemGroup(NestedSet, WebsiteGenerator): @@ -83,7 +84,8 @@ def get_product_list_for_group(product_group=None, start=0, limit=10, search=Non # base query query = """select I.name, I.item_name, I.item_code, I.route, I.image, I.website_image, I.thumbnail, I.item_group, I.description, I.web_long_description as website_description, I.is_stock_item, - case when (S.actual_qty - S.reserved_qty) > 0 then 1 else 0 end as in_stock + case when (S.actual_qty - S.reserved_qty) > 0 then 1 else 0 end as in_stock, I.website_warehouse, + I.has_batch_no from `tabItem` I left join tabBin S on I.item_code = S.item_code and I.website_warehouse = S.warehouse where I.show_in_website = 1 @@ -104,8 +106,26 @@ def get_product_list_for_group(product_group=None, start=0, limit=10, search=Non data = frappe.db.sql(query, {"product_group": product_group,"search": search, "today": nowdate()}, as_dict=1) + data = adjust_for_expired_items(data) + return [get_item_for_list_in_html(r) for r in data] + +def adjust_for_expired_items(data): + adjusted_data = [] + + for item in data: + if item.get('has_batch_no') and item.get('website_warehouse'): + stock_qty_dict = get_qty_in_stock( + item.get('name'), 'website_warehouse', item.get('website_warehouse')) + qty = stock_qty_dict.stock_qty[0][0] + item['in_stock'] = 1 if qty else 0 + adjusted_data.append(item) + + return adjusted_data + + + def get_child_groups(item_group_name): item_group = frappe.get_doc("Item Group", item_group_name) return frappe.db.sql("""select name diff --git a/erpnext/utilities/product.py b/erpnext/utilities/product.py index 9d5c056ba7..f088e3267d 100644 --- a/erpnext/utilities/product.py +++ b/erpnext/utilities/product.py @@ -4,14 +4,17 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cint, fmt_money, flt +from frappe.utils import cint, fmt_money, flt, nowdate, getdate from erpnext.accounts.doctype.pricing_rule.pricing_rule import get_pricing_rule_for_item +from erpnext.stock.doctype.batch.batch import get_batch_qty -def get_qty_in_stock(item_code, item_warehouse_field): +def get_qty_in_stock(item_code, item_warehouse_field, warehouse=None): in_stock, stock_qty = 0, '' template_item_code, is_stock_item = frappe.db.get_value("Item", item_code, ["variant_of", "is_stock_item"]) - warehouse = frappe.db.get_value("Item", item_code, item_warehouse_field) + if not warehouse: + warehouse = frappe.db.get_value("Item", item_code, item_warehouse_field) + if not warehouse and template_item_code and template_item_code != item_code: warehouse = frappe.db.get_value("Item", template_item_code, item_warehouse_field) @@ -21,8 +24,49 @@ def get_qty_in_stock(item_code, item_warehouse_field): if stock_qty: in_stock = stock_qty[0][0] > 0 and 1 or 0 + if stock_qty[0][0]: + stock_qty = adjust_for_expired_items(item_code, stock_qty, warehouse) + + if stock_qty[0][0]: + in_stock = stock_qty[0][0] > 0 and 1 or 0 + return frappe._dict({"in_stock": in_stock, "stock_qty": stock_qty, "is_stock_item": is_stock_item}) + +def adjust_for_expired_items(item_code, stock_qty, warehouse): + batches = frappe.get_list('Batch', filters=[{'item': item_code}], fields=['expiry_date', 'name']) + expired_batches = get_expired_batches(batches) + stock_qty = [list(item) for item in stock_qty] + + if expired_batches: + for batch in expired_batches: + if warehouse: + stock_qty[0][0] = max(0, stock_qty[0][0] - get_batch_qty(batch, warehouse)) + else: + stock_qty[0][0] = max(0, stock_qty[0][0] - qty_from_all_warehouses(get_batch_qty(batch))) + + if not stock_qty[0][0]: + break + return stock_qty + + +def get_expired_batches(batches): + """ + :param batches: A list of dict in the form [{'expiry_date': datetime.date(20XX, 1, 1), 'name': 'batch_id'}, ...] + """ + return [b.name for b in batches if b.expiry_date and b.expiry_date <= getdate(nowdate())] + + +def qty_from_all_warehouses(batch_info): + """ + :param batch_info: A list of dict in the form [{u'warehouse': u'Stores - I', u'qty': 0.8}, ...] + """ + qty = 0 + for batch in batch_info: + qty = qty + batch.qty + + return qty + def get_price(item_code, price_list, customer_group, company, qty=1): template_item_code = frappe.db.get_value("Item", item_code, "variant_of") From c7c1defe648310bb1971735f71a8fc9e5a24aa75 Mon Sep 17 00:00:00 2001 From: tundebabzy Date: Sat, 27 Jan 2018 06:30:56 +0100 Subject: [PATCH 06/33] after adjusting stock_qty for expired, set in_stock flag --- erpnext/utilities/product.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/utilities/product.py b/erpnext/utilities/product.py index f088e3267d..5a9322bb38 100644 --- a/erpnext/utilities/product.py +++ b/erpnext/utilities/product.py @@ -21,8 +21,6 @@ def get_qty_in_stock(item_code, item_warehouse_field, warehouse=None): if warehouse: stock_qty = frappe.db.sql("""select GREATEST(actual_qty - reserved_qty, 0) from tabBin where item_code=%s and warehouse=%s""", (item_code, warehouse)) - if stock_qty: - in_stock = stock_qty[0][0] > 0 and 1 or 0 if stock_qty[0][0]: stock_qty = adjust_for_expired_items(item_code, stock_qty, warehouse) @@ -30,6 +28,9 @@ def get_qty_in_stock(item_code, item_warehouse_field, warehouse=None): if stock_qty[0][0]: in_stock = stock_qty[0][0] > 0 and 1 or 0 + if stock_qty: + in_stock = stock_qty[0][0] > 0 and 1 or 0 + return frappe._dict({"in_stock": in_stock, "stock_qty": stock_qty, "is_stock_item": is_stock_item}) From 5cf01d9702b5f56a543f8e2ccf2fdfeb81bc514b Mon Sep 17 00:00:00 2001 From: Cesar Date: Mon, 29 Jan 2018 11:54:12 +0100 Subject: [PATCH 07/33] Sort by account name Trial balance not sorted .. by adding those changes fixes the problem. --- erpnext/accounts/report/trial_balance/trial_balance.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index 9eea472086..ba6d00b68d 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -52,7 +52,7 @@ def validate_filters(filters): def get_data(filters): accounts = frappe.db.sql("""select name, parent_account, account_name, root_type, report_type, lft, rgt - from `tabAccount` where company=%s order by lft""", filters.company, as_dict=True) + from `tabAccount` where company=%s order by account_name,lft""", filters.company, as_dict=True) company_currency = erpnext.get_company_currency(filters.company) if not accounts: @@ -168,7 +168,8 @@ def accumulate_values_into_parents(accounts, accounts_by_name): def prepare_data(accounts, filters, total_row, parent_children_map, company_currency): data = [] - + tmpacnt = sorted(accounts) + accounts = tmpacnt for d in accounts: has_value = False row = { From 58c040cffb503b6b9ae192a2e4af0530ab0aecfe Mon Sep 17 00:00:00 2001 From: Cesar Date: Mon, 29 Jan 2018 11:57:15 +0100 Subject: [PATCH 08/33] Revert "Sort by account name" This reverts commit 5cf01d9702b5f56a543f8e2ccf2fdfeb81bc514b. --- erpnext/accounts/report/trial_balance/trial_balance.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index ba6d00b68d..9eea472086 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -52,7 +52,7 @@ def validate_filters(filters): def get_data(filters): accounts = frappe.db.sql("""select name, parent_account, account_name, root_type, report_type, lft, rgt - from `tabAccount` where company=%s order by account_name,lft""", filters.company, as_dict=True) + from `tabAccount` where company=%s order by lft""", filters.company, as_dict=True) company_currency = erpnext.get_company_currency(filters.company) if not accounts: @@ -168,8 +168,7 @@ def accumulate_values_into_parents(accounts, accounts_by_name): def prepare_data(accounts, filters, total_row, parent_children_map, company_currency): data = [] - tmpacnt = sorted(accounts) - accounts = tmpacnt + for d in accounts: has_value = False row = { From d6a61ad0c389715dbf54e35770257431c8d1a13b Mon Sep 17 00:00:00 2001 From: Helkyd Date: Mon, 29 Jan 2018 13:47:12 +0000 Subject: [PATCH 09/33] Trial Balance sort by Account Name Trial Balance order by Account Name Used Sorted under Prepare_data Function. --- erpnext/accounts/report/trial_balance/trial_balance.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index 9eea472086..1ad8f0e725 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -52,7 +52,7 @@ def validate_filters(filters): def get_data(filters): accounts = frappe.db.sql("""select name, parent_account, account_name, root_type, report_type, lft, rgt - from `tabAccount` where company=%s order by lft""", filters.company, as_dict=True) + from `tabAccount` where company=%s order by account_name, lft""", filters.company, as_dict=True) company_currency = erpnext.get_company_currency(filters.company) if not accounts: @@ -168,6 +168,8 @@ def accumulate_values_into_parents(accounts, accounts_by_name): def prepare_data(accounts, filters, total_row, parent_children_map, company_currency): data = [] + tmpaccnt = sorted(accounts) + accounts = tmpaccnt for d in accounts: has_value = False From d8b1927e8d510391c4c40b509b8961bdceeab3ca Mon Sep 17 00:00:00 2001 From: Cesar Date: Mon, 29 Jan 2018 15:39:52 +0100 Subject: [PATCH 10/33] Allow no ZERO Payment Allow no ZERO Payment --- erpnext/public/js/payment/payments.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js index 32523735a6..0d656bc1fb 100644 --- a/erpnext/public/js/payment/payments.js +++ b/erpnext/public/js/payment/payments.js @@ -27,14 +27,14 @@ erpnext.payments = erpnext.stock.StockController.extend({ var me = this; this.dialog.set_primary_action(__("Submit"), function() { - //Allow no ZERO payment + // Allow no ZERO payment $.each(me.frm.doc.payments, function (index, data) { if (data.amount != 0) { me.dialog.hide(); me.submit_invoice(); return; } - }); + }); }) }, From 98e33c31cdf33264169842d11f34faaf79c61f29 Mon Sep 17 00:00:00 2001 From: vishdha Date: Mon, 29 Jan 2018 13:57:34 +0530 Subject: [PATCH 11/33] [wip] Gstr2 --- erpnext/regional/india/setup.py | 35 +- erpnext/regional/report/gstr_2/__init__.py | 0 erpnext/regional/report/gstr_2/gstr_2.js | 39 +++ erpnext/regional/report/gstr_2/gstr_2.json | 29 ++ erpnext/regional/report/gstr_2/gstr_2.py | 367 +++++++++++++++++++++ 5 files changed, 458 insertions(+), 12 deletions(-) create mode 100644 erpnext/regional/report/gstr_2/__init__.py create mode 100644 erpnext/regional/report/gstr_2/gstr_2.js create mode 100644 erpnext/regional/report/gstr_2/gstr_2.json create mode 100644 erpnext/regional/report/gstr_2/gstr_2.py diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index e9d91abd48..385d33946f 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -107,16 +107,7 @@ def make_custom_fields(): dict(fieldname='reason_for_issuing_document', label='Reason For Issuing document', fieldtype='Select', insert_after='ecommerce_gstin', print_hide=1, depends_on='eval:doc.is_return==1', - options='\n01-Sales Return\n02-Post Sale Discount\n03-Deficiency in services\n04-Correction in Invoice\n05-Change in POS\n06-Finalization of Provisional assessment\n07-Others'), - dict(fieldname='port_code', label='Port Code', - fieldtype='Data', insert_after='reason_for_issuing_document', print_hide=1, - depends_on="eval:doc.invoice_type=='Export' "), - dict(fieldname='shipping_bill_number', label=' Shipping Bill Number', - fieldtype='Data', insert_after='port_code', print_hide=1, - depends_on="eval:doc.invoice_type=='Export' "), - dict(fieldname='shipping_bill_date', label='Shipping Bill Date', - fieldtype='Date', insert_after='shipping_bill_number', print_hide=1, - depends_on="eval:doc.invoice_type=='Export' "), + options='\n01-Sales Return\n02-Post Sale Discount\n03-Deficiency in services\n04-Correction in Invoice\n05-Change in POS\n06-Finalization of Provisional assessment\n07-Others') ] purchase_invoice_gst_fields = [ @@ -125,7 +116,18 @@ def make_custom_fields(): options='supplier_address.gstin', print_hide=1), dict(fieldname='company_gstin', label='Company GSTIN', fieldtype='Data', insert_after='shipping_address', - options='shipping_address.gstin', print_hide=1) + options='shipping_address.gstin', print_hide=1), + dict(fieldname='eligibility_for_itc', label='Eligibility For ITC', + fieldtype='Select', insert_after='reason_for_issuing_document', print_hide=1, + options='input\ninput service\ncapital goods\nineligible', default="ineligible"), + dict(fieldname='itc_integrated_tax', label='Availed ITC Integrated Tax', + fieldtype='Data', insert_after='eligibility_for_itc', print_hide=1), + dict(fieldname='itc_central_tax', label='Availed ITC Central Tax', + fieldtype='Data', insert_after='itc_integrated_tax', print_hide=1), + dict(fieldname='itc_state_tax', label='Availed ITC State/UT Tax', + fieldtype='Data', insert_after='itc_central_tax', print_hide=1), + dict(fieldname='itc_cess_amount', label='Availed ITC Cess', + fieldtype='Data', insert_after='itc_state_tax', print_hide=1), ] sales_invoice_gst_fields = [ @@ -140,7 +142,16 @@ def make_custom_fields(): print_hide=1, read_only=0), dict(fieldname='company_gstin', label='Company GSTIN', fieldtype='Data', insert_after='company_address', - options='company_address.gstin', print_hide=1) + options='company_address.gstin', print_hide=1), + dict(fieldname='port_code', label='Port Code', + fieldtype='Data', insert_after='reason_for_issuing_document', print_hide=1, + depends_on="eval:doc.invoice_type=='Export' "), + dict(fieldname='shipping_bill_number', label=' Shipping Bill Number', + fieldtype='Data', insert_after='port_code', print_hide=1, + depends_on="eval:doc.invoice_type=='Export' "), + dict(fieldname='shipping_bill_date', label='Shipping Bill Date', + fieldtype='Date', insert_after='shipping_bill_number', print_hide=1, + depends_on="eval:doc.invoice_type=='Export' ") ] custom_fields = { diff --git a/erpnext/regional/report/gstr_2/__init__.py b/erpnext/regional/report/gstr_2/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/regional/report/gstr_2/gstr_2.js b/erpnext/regional/report/gstr_2/gstr_2.js new file mode 100644 index 0000000000..5c1ea67e8e --- /dev/null +++ b/erpnext/regional/report/gstr_2/gstr_2.js @@ -0,0 +1,39 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["GSTR-2"] = { + "filters": [ + { + "fieldname":"company", + "label": __("Company"), + "fieldtype": "Link", + "options": "Company", + "reqd": 1, + "default": frappe.defaults.get_user_default("Company") + }, + { + "fieldname":"from_date", + "label": __("From Date"), + "fieldtype": "Date", + "reqd": 1, + "default": frappe.datetime.add_months(frappe.datetime.get_today(), -3), + "width": "80" + }, + { + "fieldname":"to_date", + "label": __("To Date"), + "fieldtype": "Date", + "reqd": 1, + "default": frappe.datetime.get_today() + }, + { + "fieldname":"type_of_business", + "label": __("Type of Business"), + "fieldtype": "Select", + "reqd": 1, + "options": ["B2B","CDNR"], + "default": "B2B" + } + ] +} diff --git a/erpnext/regional/report/gstr_2/gstr_2.json b/erpnext/regional/report/gstr_2/gstr_2.json new file mode 100644 index 0000000000..929ed914d8 --- /dev/null +++ b/erpnext/regional/report/gstr_2/gstr_2.json @@ -0,0 +1,29 @@ +{ + "add_total_row": 0, + "apply_user_permissions": 1, + "creation": "2018-01-29 12:59:55.650445", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2018-01-29 12:59:55.650445", + "modified_by": "Administrator", + "module": "Regional", + "name": "GSTR-2", + "owner": "Administrator", + "ref_doctype": "GL Entry", + "report_name": "GSTR-2", + "report_type": "Script Report", + "roles": [ + { + "role": "Accounts User" + }, + { + "role": "Accounts Manager" + }, + { + "role": "Auditor" + } + ] +} \ No newline at end of file diff --git a/erpnext/regional/report/gstr_2/gstr_2.py b/erpnext/regional/report/gstr_2/gstr_2.py new file mode 100644 index 0000000000..8743e677d8 --- /dev/null +++ b/erpnext/regional/report/gstr_2/gstr_2.py @@ -0,0 +1,367 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe, json +from frappe import _ +from datetime import date + +def execute(filters=None): + return Gstr2Report(filters).run() + +class Gstr2Report(object): + def __init__(self, filters=None): + self.filters = frappe._dict(filters or {}) + + def run(self): + self.get_columns() + self.get_data() + return self.columns, self.data + + def get_data(self): + self.data = [] + self.get_gst_accounts() + self.get_invoice_data() + + if not self.invoices: return + + self.get_invoice_items() + self.get_items_based_on_tax_rate() + invoice_fields = [d["fieldname"] for d in self.invoice_columns] + + + for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): + invoice_details = self.invoices.get(inv) + for x in xrange(1,10): + print(invoice_details) + for rate, items in items_based_on_rate.items(): + row = [] + for fieldname in invoice_fields: + if fieldname == "invoice_value": + row.append(invoice_details.base_rounded_total or invoice_details.base_grand_total) + else: + row.append(invoice_details.get(fieldname)) + + row += [rate, + sum([net_amount for item_code, net_amount in self.invoice_items.get(inv).items() + if item_code in items]), + self.invoice_cess.get(inv), + ] + + + if self.filters.get("type_of_business") == "CDNR": + row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N") + row.append("C" if invoice_details.return_against else "R") + + self.data.append(row) + + def get_invoice_data(self): + self.invoices = frappe._dict() + conditions = self.get_conditions() + + invoice_data = frappe.db.sql(""" + select + name as invoice_number, + supplier_name, + posting_date, + base_grand_total, + base_rounded_total, + supplier_gstin, + place_of_supply, + ecommerce_gstin, + reverse_charge, + invoice_type, + return_against, + is_return, + invoice_type, + export_type, + port_code, + shipping_bill_number, + shipping_bill_date, + reason_for_issuing_document, + eligibility_for_itc, + itc_integrated_tax, + itc_central_tax, + itc_state_tax, + itc_cess_amount + from `tabPurchase Invoice` + where docstatus = 1 %s + order by posting_date desc + """ % (conditions), self.filters, as_dict=1) + + for d in invoice_data: + self.invoices.setdefault(d.invoice_number, d) + + def get_conditions(self): + conditions = "" + + for opts in (("company", " and company=%(company)s"), + ("from_date", " and posting_date>=%(from_date)s"), + ("to_date", " and posting_date<=%(to_date)s")): + if self.filters.get(opts[0]): + conditions += opts[1] + + if self.filters.get("type_of_business") == "B2B": + conditions += "and invoice_type != 'Export' and is_return != 1 " + + elif self.filters.get("type_of_business") == "CDNR": + conditions += """ and is_return = 1 """ + + return conditions + + def get_invoice_items(self): + self.invoice_items = frappe._dict() + items = frappe.db.sql(""" + select item_code, parent, base_net_amount + from `tabPurchase Invoice Item` + where parent in (%s) + """ % (', '.join(['%s']*len(self.invoices))), tuple(self.invoices), as_dict=1) + + for d in items: + self.invoice_items.setdefault(d.parent, {}).setdefault(d.item_code, d.base_net_amount) + + def get_items_based_on_tax_rate(self): + tax_details = frappe.db.sql(""" + select + parent, account_head, item_wise_tax_detail, base_tax_amount_after_discount_amount + from `tabPurchase Taxes and Charges` + where + parenttype = 'Purchase Invoice' and docstatus = 1 + and parent in (%s) + + order by account_head + """ % (', '.join(['%s']*len(self.invoices.keys()))), tuple(self.invoices.keys())) + + self.items_based_on_tax_rate = {} + self.invoice_cess = frappe._dict() + unidentified_gst_accounts = [] + + for parent, account, item_wise_tax_detail, tax_amount in tax_details: + if account in self.gst_accounts.cess_account: + self.invoice_cess.setdefault(parent, tax_amount) + else: + if item_wise_tax_detail: + try: + item_wise_tax_detail = json.loads(item_wise_tax_detail) + cgst_or_sgst = False + if account in self.gst_accounts.cgst_account \ + or account in self.gst_accounts.sgst_account: + cgst_or_sgst = True + + if not (cgst_or_sgst or account in self.gst_accounts.igst_account): + if "gst" in account.lower() and account not in unidentified_gst_accounts: + unidentified_gst_accounts.append(account) + continue + + for item_code, tax_amounts in item_wise_tax_detail.items(): + tax_rate = tax_amounts[0] + if cgst_or_sgst: + tax_rate *= 2 + + rate_based_dict = self.items_based_on_tax_rate.setdefault(parent, {})\ + .setdefault(tax_rate, []) + if item_code not in rate_based_dict: + rate_based_dict.append(item_code) + except ValueError: + continue + if unidentified_gst_accounts: + frappe.msgprint(_("Following accounts might be selected in GST Settings:") + + "
" + "
".join(unidentified_gst_accounts), alert=True) + + def get_gst_accounts(self): + self.gst_accounts = frappe._dict() + gst_settings_accounts = frappe.get_list("GST Account", + filters={"parent": "GST Settings", "company": self.filters.company}, + fields=["cgst_account", "sgst_account", "igst_account", "cess_account"]) + + if not gst_settings_accounts: + frappe.throw(_("Please set GST Accounts in GST Settings")) + + for d in gst_settings_accounts: + for acc, val in d.items(): + self.gst_accounts.setdefault(acc, []).append(val) + + def get_columns(self): + self.tax_columns = [ + { + "fieldname": "rate", + "label": "Rate", + "fieldtype": "Int", + "width": 60 + }, + { + "fieldname": "taxable_value", + "label": "Taxable Value", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "integrated_tax_paid", + "label": "Integrated Tax Paid", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "central_tax_paid", + "label": "Central Tax Paid", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "state_tax_paid", + "label": "State/UT Tax Paid", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "cess_amount", + "label": "Cess Paid", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "eligibility_for_itc", + "label": "Eligibility For ITC", + "fieldtype": "Data", + "width": 100 + }, + { + "fieldname": "itc_integrated_tax", + "label": "Availed ITC Integrated Tax", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "itc_central_tax", + "label": "Availed ITC Central Tax", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "itc_state_tax", + "label": "Availed ITC State/UT Tax", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "itc_cess_amount", + "label": "Availed ITC Cess ", + "fieldtype": "Currency", + "width": 100 + } + ] + self.other_columns = [] + + if self.filters.get("type_of_business") == "B2B": + self.invoice_columns = [ + { + "fieldname": "supplier_gstin", + "label": "GSTIN of Supplier", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "invoice_number", + "label": "Invoice Number", + "fieldtype": "Link", + "options": "Purchase Invoice", + "width": 120 + }, + { + "fieldname": "posting_date", + "label": "Invoice date", + "fieldtype": "Date", + "width": 120 + }, + { + "fieldname": "invoice_value", + "label": "Invoice Value", + "fieldtype": "Currency", + "width": 120 + }, + { + "fieldname": "place_of_supply", + "label": "Place of Supply", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "reverse_charge", + "label": "Reverse Charge", + "fieldtype": "Data", + "width": 80 + }, + { + "fieldname": "invoice_type", + "label": "Invoice Type", + "fieldtype": "Data", + "width": 80 + } + ] + elif self.filters.get("type_of_business") == "CDNR": + self.invoice_columns = [ + { + "fieldname": "supplier_gstin", + "label": "GSTIN of Supplier", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "invoice_number", + "label": "Note/Refund Voucher Number", + "fieldtype": "Link", + "options": "Purchase Invoice" + }, + { + "fieldname": "posting_date", + "label": "Note/Refund Voucher date", + "fieldtype": "Date", + "width": 120 + }, + { + "fieldname": "return_against", + "label": "Invoice/Advance Payment Voucher Number", + "fieldtype": "Link", + "options": "Purchase Invoice", + "width": 120 + }, + { + "fieldname": "posting_date", + "label": "Invoice/Advance Payment Voucher date", + "fieldtype": "Date", + "width": 120 + }, + { + "fieldname": "reason_for_issuing_document", + "label": "Reason For Issuing document", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "supply_type", + "label": "Supply Type", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "invoice_value", + "label": "Invoice Value", + "fieldtype": "Currency", + "width": 120 + } + ] + self.other_columns = [ + { + "fieldname": "pre_gst", + "label": "PRE GST", + "fieldtype": "Data", + "width": 50 + }, + { + "fieldname": "document_type", + "label": "Document Type", + "fieldtype": "Data", + "width": 50 + } + ] + self.columns = self.invoice_columns + self.tax_columns + self.other_columns From e03e4a581f579d0766da847bf01e5381b1da202d Mon Sep 17 00:00:00 2001 From: vishdha Date: Mon, 29 Jan 2018 22:54:24 +0530 Subject: [PATCH 12/33] [fix] Fetch correct Tax Details --- erpnext/patches.txt | 1 + .../added_extra_gst_custom_field_in_gstr2.py | 9 ++++++ erpnext/regional/report/gstr_2/gstr_2.py | 28 +++++++++++++++---- 3 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 erpnext/patches/v10_0/added_extra_gst_custom_field_in_gstr2.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index d300285c67..74f90a8b28 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -491,3 +491,4 @@ erpnext.patches.v10_0.update_assessment_result erpnext.patches.v10_0.added_extra_gst_custom_field erpnext.patches.v10_0.workflow_leave_application #2018-01-24 erpnext.patches.v10_0.set_default_payment_terms_based_on_company +erpnext.patches.v10_0.added_extra_gst_custom_field_in_gstr2 diff --git a/erpnext/patches/v10_0/added_extra_gst_custom_field_in_gstr2.py b/erpnext/patches/v10_0/added_extra_gst_custom_field_in_gstr2.py new file mode 100644 index 0000000000..a1512ed9b7 --- /dev/null +++ b/erpnext/patches/v10_0/added_extra_gst_custom_field_in_gstr2.py @@ -0,0 +1,9 @@ +import frappe +from erpnext.regional.india.setup import make_custom_fields + +def execute(): + company = frappe.get_all('Company', filters = {'country': 'India'}) + if not company: + return + + make_custom_fields() \ No newline at end of file diff --git a/erpnext/regional/report/gstr_2/gstr_2.py b/erpnext/regional/report/gstr_2/gstr_2.py index 8743e677d8..cb5f472987 100644 --- a/erpnext/regional/report/gstr_2/gstr_2.py +++ b/erpnext/regional/report/gstr_2/gstr_2.py @@ -32,9 +32,9 @@ class Gstr2Report(object): for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): invoice_details = self.invoices.get(inv) - for x in xrange(1,10): - print(invoice_details) + for rate, items in items_based_on_rate.items(): + # for is_igst, items in account.items(): row = [] for fieldname in invoice_fields: if fieldname == "invoice_value": @@ -42,13 +42,23 @@ class Gstr2Report(object): else: row.append(invoice_details.get(fieldname)) + print("items", items.items()) + + # for k, v in items.items(): + # print(k,v[1], items.items().) row += [rate, sum([net_amount for item_code, net_amount in self.invoice_items.get(inv).items() - if item_code in items]), + if item_code in [v[0] for k, v in items.items()]]), + [v[1] if k == True else 0.00 for k, v in items.items()], + [v[1] if k == False else 0.00 for k, v in items.items()], + [v[1] if k == False else 0.00 for k, v in items.items()], + # [x for x in items if is_igst == False], self.invoice_cess.get(inv), ] + + if self.filters.get("type_of_business") == "CDNR": row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N") row.append("C" if invoice_details.return_against else "R") @@ -152,16 +162,24 @@ class Gstr2Report(object): if "gst" in account.lower() and account not in unidentified_gst_accounts: unidentified_gst_accounts.append(account) continue - + is_igst = False for item_code, tax_amounts in item_wise_tax_detail.items(): tax_rate = tax_amounts[0] + tax_amt = tax_amounts[1] if cgst_or_sgst: tax_rate *= 2 + tax_amt *= 2 + + else: + is_igst =True + rate_based_dict = self.items_based_on_tax_rate.setdefault(parent, {})\ - .setdefault(tax_rate, []) + .setdefault(tax_rate, {}).setdefault(is_igst, []) + print("rate_base_dict", rate_based_dict) if item_code not in rate_based_dict: rate_based_dict.append(item_code) + rate_based_dict.append(tax_amt if is_igst else tax_amt / 2 ) except ValueError: continue if unidentified_gst_accounts: From 963dd1e4bc75a2ff1db73f75ef0321485142e1f0 Mon Sep 17 00:00:00 2001 From: vishdha Date: Tue, 30 Jan 2018 11:51:57 +0530 Subject: [PATCH 13/33] [minor] ITC data append to row --- erpnext/regional/report/gstr_2/gstr_2.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/erpnext/regional/report/gstr_2/gstr_2.py b/erpnext/regional/report/gstr_2/gstr_2.py index cb5f472987..0715c8a478 100644 --- a/erpnext/regional/report/gstr_2/gstr_2.py +++ b/erpnext/regional/report/gstr_2/gstr_2.py @@ -44,16 +44,19 @@ class Gstr2Report(object): print("items", items.items()) - # for k, v in items.items(): - # print(k,v[1], items.items().) + row += [rate, sum([net_amount for item_code, net_amount in self.invoice_items.get(inv).items() if item_code in [v[0] for k, v in items.items()]]), [v[1] if k == True else 0.00 for k, v in items.items()], [v[1] if k == False else 0.00 for k, v in items.items()], [v[1] if k == False else 0.00 for k, v in items.items()], - # [x for x in items if is_igst == False], self.invoice_cess.get(inv), + invoice_details.get('eligibility_for_itc'), + invoice_details.get('itc_integrated_tax'), + invoice_details.get('itc_central_tax'), + invoice_details.get('itc_state_tax'), + invoice_details.get('itc_cess_amount'), ] From 109b408d11ed03d000f6dd82c5d900eeb5cf7266 Mon Sep 17 00:00:00 2001 From: vishdha Date: Tue, 30 Jan 2018 12:11:13 +0530 Subject: [PATCH 14/33] [fix] minor changes in gst field alignment --- erpnext/regional/india/setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index 385d33946f..9243859b01 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -87,7 +87,7 @@ def make_custom_fields(): allow_on_submit=1, print_hide=1) invoice_gst_fields = [ dict(fieldname='gst_section', label='GST Details', fieldtype='Section Break', - insert_after='select_print_heading', print_hide=1, collapsible=1), + insert_after='language', print_hide=1, collapsible=1), dict(fieldname='invoice_copy', label='Invoice Copy', fieldtype='Select', insert_after='gst_section', print_hide=1, allow_on_submit=1, options='Original for Recipient\nDuplicate for Transporter\nDuplicate for Supplier\nTriplicate for Supplier'), @@ -96,7 +96,7 @@ def make_custom_fields(): options='Y\nN', default='N'), dict(fieldname='gst_col_break', fieldtype='Column Break', insert_after='reverse_charge'), dict(fieldname='invoice_type', label='Invoice Type', - fieldtype='Select', insert_after='reverse_charge', print_hide=1, + fieldtype='Select', insert_after='gst_col_break', print_hide=1, options='Regular\nSEZ\nExport\nDeemed Export', default='Regular'), dict(fieldname='export_type', label='Export Type', fieldtype='Select', insert_after='invoice_type', print_hide=1, From 1910530e41e1718eca50b16a304f2d68244f95f9 Mon Sep 17 00:00:00 2001 From: vishdha Date: Tue, 30 Jan 2018 12:19:56 +0530 Subject: [PATCH 15/33] [fix] CDNR negative value --- erpnext/regional/report/gstr_2/gstr_2.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/erpnext/regional/report/gstr_2/gstr_2.py b/erpnext/regional/report/gstr_2/gstr_2.py index 0715c8a478..2aa0386b4e 100644 --- a/erpnext/regional/report/gstr_2/gstr_2.py +++ b/erpnext/regional/report/gstr_2/gstr_2.py @@ -37,7 +37,9 @@ class Gstr2Report(object): # for is_igst, items in account.items(): row = [] for fieldname in invoice_fields: - if fieldname == "invoice_value": + if self.filters.get("type_of_business") == "CDNR" and fieldname == "invoice_value": + row.append(abs(invoice_details.base_rounded_total) or abs(invoice_details.base_grand_total)) + elif fieldname == "invoice_value": row.append(invoice_details.base_rounded_total or invoice_details.base_grand_total) else: row.append(invoice_details.get(fieldname)) @@ -46,11 +48,11 @@ class Gstr2Report(object): row += [rate, - sum([net_amount for item_code, net_amount in self.invoice_items.get(inv).items() + sum([abs(net_amount) for item_code, net_amount in self.invoice_items.get(inv).items() if item_code in [v[0] for k, v in items.items()]]), - [v[1] if k == True else 0.00 for k, v in items.items()], - [v[1] if k == False else 0.00 for k, v in items.items()], - [v[1] if k == False else 0.00 for k, v in items.items()], + [abs(v[1]) if k == True else 0.00 for k, v in items.items()], + [abs(v[1]) if k == False else 0.00 for k, v in items.items()], + [abs(v[1]) if k == False else 0.00 for k, v in items.items()], self.invoice_cess.get(inv), invoice_details.get('eligibility_for_itc'), invoice_details.get('itc_integrated_tax'), From 4dc329f5ea716cc70b52a96db0a3a032696f7431 Mon Sep 17 00:00:00 2001 From: Vishal Date: Wed, 24 Jan 2018 16:46:18 +0530 Subject: [PATCH 16/33] [fix] Sales order link to purchase order not working fixed --- erpnext/stock/doctype/material_request/material_request.py | 5 +++-- erpnext/stock/get_item_details.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index da310aa3d7..c4059c1848 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -65,7 +65,7 @@ class MaterialRequest(BuyingController): self.status = "Draft" from erpnext.controllers.status_updater import validate_status - validate_status(self.status, + validate_status(self.status, ["Draft", "Submitted", "Stopped", "Cancelled", "Pending", "Partially Ordered", "Ordered", "Issued", "Transferred"]) @@ -240,7 +240,8 @@ def make_purchase_order(source_name, target_doc=None): ["name", "material_request_item"], ["parent", "material_request"], ["uom", "stock_uom"], - ["uom", "uom"] + ["uom", "uom"], + ["sales_order", "sales_order"] ], "postprocess": update_item, "condition": lambda doc: doc.ordered_qty < doc.stock_qty diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index a7638b4169..6b6723331a 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -472,8 +472,8 @@ def get_projected_qty(item_code, warehouse): @frappe.whitelist() def get_bin_details(item_code, warehouse): return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, - ["projected_qty", "actual_qty"], as_dict=True) \ - or {"projected_qty": 0, "actual_qty": 0} + ["projected_qty", "actual_qty", "ordered_qty"], as_dict=True) \ + or {"projected_qty": 0, "actual_qty": 0, "ordered_qty": 0} @frappe.whitelist() def get_serial_no_details(item_code, warehouse, stock_qty, serial_no): From fc05cc4e70911444563f11910a0ef31c4dcd31f1 Mon Sep 17 00:00:00 2001 From: Vishal Date: Thu, 25 Jan 2018 15:27:35 +0530 Subject: [PATCH 17/33] [fix] link with supplier quotation to purchase order --- .../supplier_quotation/supplier_quotation.py | 3 +- .../supplier_quotation_item.json | 33 ++++++++++++++++++- .../material_request/material_request.py | 3 +- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py index c395d0cfd7..b221a08959 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py @@ -124,7 +124,8 @@ def make_purchase_order(source_name, target_doc=None): ["name", "supplier_quotation_item"], ["parent", "supplier_quotation"], ["material_request", "material_request"], - ["material_request_item", "material_request_item"] + ["material_request_item", "material_request_item"], + ["sales_order", "sales_order"] ], "postprocess": update_item }, diff --git a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json index b3a55b645d..da78c12ba0 100644 --- a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json +++ b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json @@ -1326,6 +1326,37 @@ "unique": 0, "width": "120px" }, + { + "allow_bulk_edit": 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": 1, + "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, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1614,7 +1645,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-12-14 09:37:47.427897", + "modified": "2018-01-25 15:04:40.171617", "modified_by": "Administrator", "module": "Buying", "name": "Supplier Quotation Item", diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index c4059c1848..defce62e2e 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -345,7 +345,8 @@ def make_supplier_quotation(source_name, target_doc=None): "doctype": "Supplier Quotation Item", "field_map": { "name": "material_request_item", - "parent": "material_request" + "parent": "material_request", + "sales_order": "sales_order" } } }, target_doc, postprocess) From df1653827fe5187ed99e2f230929517d2b2a7d6d Mon Sep 17 00:00:00 2001 From: vishdha Date: Wed, 31 Jan 2018 12:38:46 +0530 Subject: [PATCH 18/33] [fix] Patch for material request to purchase order added --- erpnext/patches.txt | 3 ++- ...pdate_sales_order_link_to_purchase_order.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index dbd098d119..9474a946e8 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -486,4 +486,5 @@ erpnext.patches.v10_0.add_guardian_role_for_parent_portal erpnext.patches.v10_0.set_numeric_ranges_in_template_if_blank erpnext.patches.v10_0.update_assessment_plan erpnext.patches.v10_0.update_assessment_result -erpnext.patches.v10_0.set_default_payment_terms_based_on_company \ No newline at end of file +erpnext.patches.v10_0.set_default_payment_terms_based_on_company +erpnext.patches.v10_0.update_sales_order_link_to_purchase_order \ No newline at end of file diff --git a/erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py b/erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py new file mode 100644 index 0000000000..b4f58384bf --- /dev/null +++ b/erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py @@ -0,0 +1,18 @@ +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc("buying", "doctype", "supplier_quotation_item") + + for doctype in ['Purchase Order','Supplier Quotation']: + frappe.db.sql(""" + Update + `tab{doctype} Item`, `tabMaterial Request Item` + set + `tab{doctype} Item`.sales_order = `tabMaterial Request Item`.sales_order + where + `tab{doctype} Item`.material_request= `tabMaterial Request Item`.parent + and `tab{doctype} Item`.material_request_item = `tabMaterial Request Item`.name + and `tabMaterial Request Item`.sales_order is not null""".format(doctype=doctype)) \ No newline at end of file From 29c8142678d9f81a7098266bdff0e762360f9bab Mon Sep 17 00:00:00 2001 From: tundebabzy Date: Wed, 31 Jan 2018 10:36:31 +0100 Subject: [PATCH 19/33] refactor `adjust_for_expired_items` and others as per code review use get_all instead of get_list rename `adjust_for_expired_items` to `adjust_qty_for_expired_items` --- .../setup/doctype/item_group/item_group.py | 4 ++-- erpnext/utilities/product.py | 22 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index bb1910720d..14a478d7e4 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -106,12 +106,12 @@ def get_product_list_for_group(product_group=None, start=0, limit=10, search=Non data = frappe.db.sql(query, {"product_group": product_group,"search": search, "today": nowdate()}, as_dict=1) - data = adjust_for_expired_items(data) + data = adjust_qty_for_expired_items(data) return [get_item_for_list_in_html(r) for r in data] -def adjust_for_expired_items(data): +def adjust_qty_for_expired_items(data): adjusted_data = [] for item in data: diff --git a/erpnext/utilities/product.py b/erpnext/utilities/product.py index 5a9322bb38..5901b6031d 100644 --- a/erpnext/utilities/product.py +++ b/erpnext/utilities/product.py @@ -23,7 +23,7 @@ def get_qty_in_stock(item_code, item_warehouse_field, warehouse=None): item_code=%s and warehouse=%s""", (item_code, warehouse)) if stock_qty[0][0]: - stock_qty = adjust_for_expired_items(item_code, stock_qty, warehouse) + stock_qty = adjust_qty_for_expired_items(item_code, stock_qty, warehouse) if stock_qty[0][0]: in_stock = stock_qty[0][0] > 0 and 1 or 0 @@ -34,20 +34,20 @@ def get_qty_in_stock(item_code, item_warehouse_field, warehouse=None): return frappe._dict({"in_stock": in_stock, "stock_qty": stock_qty, "is_stock_item": is_stock_item}) -def adjust_for_expired_items(item_code, stock_qty, warehouse): - batches = frappe.get_list('Batch', filters=[{'item': item_code}], fields=['expiry_date', 'name']) +def adjust_qty_for_expired_items(item_code, stock_qty, warehouse): + batches = frappe.get_all('Batch', filters=[{'item': item_code}], fields=['expiry_date', 'name']) expired_batches = get_expired_batches(batches) stock_qty = [list(item) for item in stock_qty] - if expired_batches: - for batch in expired_batches: - if warehouse: - stock_qty[0][0] = max(0, stock_qty[0][0] - get_batch_qty(batch, warehouse)) - else: - stock_qty[0][0] = max(0, stock_qty[0][0] - qty_from_all_warehouses(get_batch_qty(batch))) + for batch in expired_batches: + if warehouse: + stock_qty[0][0] = max(0, stock_qty[0][0] - get_batch_qty(batch, warehouse)) + else: + stock_qty[0][0] = max(0, stock_qty[0][0] - qty_from_all_warehouses(get_batch_qty(batch))) + + if not stock_qty[0][0]: + break - if not stock_qty[0][0]: - break return stock_qty From 4990cf7783fbf7b800e36967ac82d43296027ffe Mon Sep 17 00:00:00 2001 From: tundebabzy Date: Wed, 31 Jan 2018 11:35:56 +0100 Subject: [PATCH 20/33] remove stray code --- erpnext/stock/doctype/batch/batch.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index 760643c4ec..3e5d351650 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -47,7 +47,6 @@ def get_batch_qty(batch_no=None, warehouse=None, item_code=None): :param batch_no: Optional - give qty for this batch no :param warehouse: Optional - give qty for this warehouse :param item_code: Optional - give qty for this item''' - frappe.has_permission('Batch', throw=True) out = 0 if batch_no and warehouse: out = float(frappe.db.sql("""select sum(actual_qty) From 82fa04ce323d1094cf32b8ec7f3074f3edd3cfd5 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Wed, 31 Jan 2018 22:20:14 +0530 Subject: [PATCH 21/33] Update projects.py --- erpnext/config/projects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/config/projects.py b/erpnext/config/projects.py index b97e097f08..ac11c7e45c 100644 --- a/erpnext/config/projects.py +++ b/erpnext/config/projects.py @@ -15,7 +15,7 @@ def get_data(): { "type": "doctype", "name": "Task", - "route": "Tree/Task", + "route": "List/Task", "description": _("Project activity / task."), }, { From b9ce104b092af55ab3a3b95aa82a3b62054922e4 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 1 Feb 2018 14:58:50 +0530 Subject: [PATCH 22/33] Opening balance in stock ledger report (#12729) --- erpnext/stock/report/stock_ledger/stock_ledger.py | 5 ++--- erpnext/stock/stock_ledger.py | 10 +++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py index 8377f59979..e436132ec8 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.py +++ b/erpnext/stock/report/stock_ledger/stock_ledger.py @@ -106,11 +106,10 @@ def get_opening_balance(filters, columns): from erpnext.stock.stock_ledger import get_previous_sle last_entry = get_previous_sle({ "item_code": filters.item_code, - "warehouse": get_warehouse_condition(filters.warehouse), + "warehouse_condition": get_warehouse_condition(filters.warehouse), "posting_date": filters.from_date, "posting_time": "00:00:00" }) - row = [""]*len(columns) row[1] = _("'Opening'") for i, v in ((9, 'qty_after_transaction'), (11, 'valuation_rate'), (12, 'stock_value')): @@ -122,7 +121,7 @@ def get_warehouse_condition(warehouse): warehouse_details = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"], as_dict=1) if warehouse_details: return " exists (select name from `tabWarehouse` wh \ - where wh.lft >= %s and wh.rgt <= %s and sle.warehouse = wh.name)"%(warehouse_details.lft, + where wh.lft >= %s and wh.rgt <= %s and warehouse = wh.name)"%(warehouse_details.lft, warehouse_details.rgt) return '' diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 647c9faf02..874a382192 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -407,7 +407,12 @@ def get_previous_sle(args, for_update=False): def get_stock_ledger_entries(previous_sle, operator=None, order="desc", limit=None, for_update=False, debug=False): """get stock ledger entries filtered by specific posting datetime conditions""" - conditions = "timestamp(posting_date, posting_time) {0} timestamp(%(posting_date)s, %(posting_time)s)".format(operator) + conditions = " and timestamp(posting_date, posting_time) {0} timestamp(%(posting_date)s, %(posting_time)s)".format(operator) + if previous_sle.get("warehouse"): + conditions += " and warehouse = %(warehouse)s" + elif previous_sle.get("warehouse_condition"): + conditions += " and " + previous_sle.get("warehouse_condition") + if not previous_sle.get("posting_date"): previous_sle["posting_date"] = "1900-01-01" if not previous_sle.get("posting_time"): @@ -418,9 +423,8 @@ def get_stock_ledger_entries(previous_sle, operator=None, order="desc", limit=No return frappe.db.sql("""select *, timestamp(posting_date, posting_time) as "timestamp" from `tabStock Ledger Entry` where item_code = %%(item_code)s - and warehouse = %%(warehouse)s and ifnull(is_cancelled, 'No')='No' - and %(conditions)s + %(conditions)s order by timestamp(posting_date, posting_time) %(order)s, name %(order)s %(limit)s %(for_update)s""" % { "conditions": conditions, From d85247cd7af6d63a553ad143acb801ac225fb204 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 1 Feb 2018 17:18:38 +0530 Subject: [PATCH 23/33] [Fix] Pay button not working in pos --- erpnext/selling/page/point_of_sale/point_of_sale.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js index f5bc6c2499..357475d479 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.js +++ b/erpnext/selling/page/point_of_sale/point_of_sale.js @@ -1268,7 +1268,7 @@ class NumberPad { this.disable_highlight = disable_highlight; this.reset_btns = reset_btns; this.del_btn = del_btn; - this.disable_btns = disable_btns; + this.disable_btns = disable_btns || []; this.make_dom(); this.bind_events(); this.value = ''; From d4359faa3153cf9b0bd8f3e02c73407699976b4b Mon Sep 17 00:00:00 2001 From: Jay Parikh Date: Thu, 1 Feb 2018 04:26:24 -0800 Subject: [PATCH 24/33] Enable/Disable Discount in POS using POS Profile #11748 --- .../doctype/pos_profile/pos_profile.json | 32 ++++++++++++++- .../doctype/sales_invoice/sales_invoice.py | 3 +- .../page/point_of_sale/point_of_sale.js | 40 ++++++++++++++----- 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json index 2cb8e1024a..ed3de07140 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.json +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json @@ -254,6 +254,36 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "allow_user_to_edit_discount", + "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 user to edit Discount", + "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, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1476,7 +1506,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-01-03 17:30:45.198147", + "modified": "2018-01-31 19:33:11.765731", "modified_by": "Administrator", "module": "Accounts", "name": "POS Profile", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index f37fe6114c..2af30e1956 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -249,7 +249,8 @@ class SalesInvoice(SellingController): if pos: return { "print_format": pos.get("print_format_for_online"), - "allow_edit_rate": pos.get("allow_user_to_edit_rate") + "allow_edit_rate": pos.get("allow_user_to_edit_rate"), + "allow_edit_discount": pos.get("allow_user_to_edit_discount") } def update_time_sheet(self, sales_invoice): diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js index f5bc6c2499..bfbb6ad405 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.js +++ b/erpnext/selling/page/point_of_sale/point_of_sale.js @@ -464,6 +464,7 @@ erpnext.pos.PointOfSale = class PointOfSale { if (r.message) { this.frm.meta.default_print_format = r.message.print_format || 'POS Invoice'; this.frm.allow_edit_rate = r.message.allow_edit_rate; + this.frm.allow_edit_discount = r.message.allow_edit_discount; } } @@ -553,9 +554,9 @@ class POSCart {
${this.get_taxes_and_totals()}
-
- ${this.get_discount_amount()} -
+
`+ + (!this.frm.allow_edit_discount ? `` : `${this.get_discount_amount()}`)+ + `
${this.get_grand_total()}
@@ -714,6 +715,21 @@ class POSCart { this.customer_field.set_value(this.frm.doc.customer); } + disable_numpad_control() { + if(!this.frm.allow_edit_rate && !this.frm.allow_edit_discount) { + return ['Rate', 'Disc']; + } + if(!this.frm.allow_edit_rate || !this.frm.allow_edit_discount) { + if(!this.frm.allow_edit_rate) { + return ['Rate']; + } else { + return ['Disc']; + } + } else { + return []; + } + } + make_numpad() { this.numpad = new NumberPad({ button_array: [ @@ -728,7 +744,7 @@ class POSCart { disable_highlight: ['Qty', 'Disc', 'Rate', 'Pay'], reset_btns: ['Qty', 'Disc', 'Rate', 'Pay'], del_btn: 'Del', - disable_btns: !this.frm.allow_edit_rate ? ['Rate']: [], + disable_btns: this.disable_numpad_control(), wrapper: this.wrapper.find('.number-pad-container'), onclick: (btn_value) => { // on click @@ -1300,13 +1316,15 @@ class NumberPad { this.set_class(); - this.disable_btns.forEach((btn) => { - const $btn = this.get_btn(btn); - $btn.prop("disabled", true) - $btn.hover(() => { - $btn.css('cursor','not-allowed'); - }) - }) + if(this.disable_btns) { + this.disable_btns.forEach((btn) => { + const $btn = this.get_btn(btn); + $btn.prop("disabled", true) + $btn.hover(() => { + $btn.css('cursor','not-allowed'); + }) + }) + } } set_class() { From 2aba97bff1aec527068053bd03798e2356df4070 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 1 Feb 2018 18:52:33 +0530 Subject: [PATCH 25/33] Fetch items from BOM in Material Request --- erpnext/manufacturing/doctype/bom/bom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index fb52d5260c..2e69475c9a 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -544,7 +544,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite group by item_code, stock_uom order by idx""" - if fetch_exploded: + if cint(fetch_exploded): query = query.format(table="BOM Explosion Item", where_conditions="", select_columns = ", bom_item.source_warehouse, (Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s ) as idx") From cae13bf048042190dffe76f079827a523ab8e168 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 1 Feb 2018 18:58:14 +0530 Subject: [PATCH 26/33] Fixes in purchase register report (#12737) --- .../item_wise_sales_register/item_wise_sales_register.py | 4 ++-- .../accounts/report/purchase_register/purchase_register.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index ab5251f292..8917c9ff63 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -168,11 +168,11 @@ def get_tax_accounts(item_list, columns, company_currency, for d in item_list: invoice_item_row.setdefault(d.parent, []).append(d) - item_row_map.setdefault(d.parent, {}).setdefault(d.item_code, []).append(d) + item_row_map.setdefault(d.parent, {}).setdefault(d.item_code or d.item_name, []).append(d) conditions = "" if doctype == "Purchase Invoice": - conditions = " and category in ('Total', 'Valuation and Total')" + conditions = " and category in ('Total', 'Valuation and Total') and base_tax_amount_after_discount_amount != 0" tax_details = frappe.db.sql(""" select diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index 37848d5064..610475acfc 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -172,6 +172,7 @@ def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts): else sum(base_tax_amount_after_discount_amount) * -1 end as tax_amount from `tabPurchase Taxes and Charges` where parent in (%s) and category in ('Total', 'Valuation and Total') + and base_tax_amount_after_discount_amount != 0 group by parent, account_head, add_deduct_tax """ % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) From 91c5e4c429b09a03044873f6cd7f55f59804b9e0 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 1 Feb 2018 18:58:22 +0530 Subject: [PATCH 27/33] Validate rate in PO with supplier quotation only if checking is enabled via Buying Settings (#12734) --- erpnext/buying/doctype/purchase_order/purchase_order.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index db13bd5520..e879f40c37 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -68,12 +68,16 @@ class PurchaseOrder(BuyingController): }, "Supplier Quotation Item": { "ref_dn_field": "supplier_quotation_item", - "compare_fields": [["rate", "="], ["project", "="], ["item_code", "="], + "compare_fields": [["project", "="], ["item_code", "="], ["uom", "="], ["conversion_factor", "="]], "is_child_table": True } }) + + if cint(frappe.db.get_single_value('Buying Settings', 'maintain_same_rate')): + self.validate_rate_with_reference_doc([["Supplier Quotation", "supplier_quotation", "supplier_quotation_item"]]) + def validate_supplier(self): prevent_po = frappe.db.get_value("Supplier", self.supplier, 'prevent_pos') if prevent_po: From b258686b004c9e2a122af2777ace1ef5a8cfd53e Mon Sep 17 00:00:00 2001 From: Helkyd Date: Thu, 1 Feb 2018 15:53:30 +0000 Subject: [PATCH 28/33] Update trial_balance.py Fix to order only if account starts with Number ... while for others not required.... --- erpnext/accounts/report/trial_balance/trial_balance.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index 09b43c1bc9..f484111be3 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -176,7 +176,8 @@ def accumulate_values_into_parents(accounts, accounts_by_name): def prepare_data(accounts, filters, total_row, parent_children_map, company_currency): data = [] tmpaccnt = sorted(accounts) - accounts = tmpaccnt + if accounts[0].account_name[0].isnumeric(): + accounts = tmpaccnt for d in accounts: has_value = False From 5df64d84a1b18cc8730430a60423d3e8dc312cb6 Mon Sep 17 00:00:00 2001 From: tundebabzy Date: Thu, 1 Feb 2018 17:05:54 +0100 Subject: [PATCH 29/33] code review fix --- erpnext/utilities/product.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/utilities/product.py b/erpnext/utilities/product.py index 5901b6031d..415056d80b 100644 --- a/erpnext/utilities/product.py +++ b/erpnext/utilities/product.py @@ -22,10 +22,10 @@ def get_qty_in_stock(item_code, item_warehouse_field, warehouse=None): stock_qty = frappe.db.sql("""select GREATEST(actual_qty - reserved_qty, 0) from tabBin where item_code=%s and warehouse=%s""", (item_code, warehouse)) - if stock_qty[0][0]: + if stock_qty: stock_qty = adjust_qty_for_expired_items(item_code, stock_qty, warehouse) - if stock_qty[0][0]: + if stock_qty: in_stock = stock_qty[0][0] > 0 and 1 or 0 if stock_qty: From 171e5af995a8b2de1db5603d8f56b1b8cb13bf1f Mon Sep 17 00:00:00 2001 From: Jay Parikh Date: Thu, 1 Feb 2018 21:39:20 -0800 Subject: [PATCH 30/33] Fixed indentation issue in pull # 11748 --- .../page/point_of_sale/point_of_sale.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js index bfbb6ad405..70e45f9512 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.js +++ b/erpnext/selling/page/point_of_sale/point_of_sale.js @@ -464,7 +464,7 @@ erpnext.pos.PointOfSale = class PointOfSale { if (r.message) { this.frm.meta.default_print_format = r.message.print_format || 'POS Invoice'; this.frm.allow_edit_rate = r.message.allow_edit_rate; - this.frm.allow_edit_discount = r.message.allow_edit_discount; + this.frm.allow_edit_discount = r.message.allow_edit_discount; } } @@ -715,7 +715,7 @@ class POSCart { this.customer_field.set_value(this.frm.doc.customer); } - disable_numpad_control() { + disable_numpad_control() { if(!this.frm.allow_edit_rate && !this.frm.allow_edit_discount) { return ['Rate', 'Disc']; } @@ -1316,15 +1316,15 @@ class NumberPad { this.set_class(); - if(this.disable_btns) { - this.disable_btns.forEach((btn) => { - const $btn = this.get_btn(btn); - $btn.prop("disabled", true) - $btn.hover(() => { - $btn.css('cursor','not-allowed'); - }) - }) - } + if(this.disable_btns) { + this.disable_btns.forEach((btn) => { + const $btn = this.get_btn(btn); + $btn.prop("disabled", true) + $btn.hover(() => { + $btn.css('cursor','not-allowed'); + }) + }) + } } set_class() { From 2c95ab3897571bdfa63e62d0c7ac73dd91db50c6 Mon Sep 17 00:00:00 2001 From: Jay Parikh Date: Thu, 1 Feb 2018 22:52:58 -0800 Subject: [PATCH 31/33] Code fix for Enable/Disable Discount in POS using POS Profile #11748 --- .../page/point_of_sale/point_of_sale.js | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js index 70e45f9512..bc7ebf3abe 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.js +++ b/erpnext/selling/page/point_of_sale/point_of_sale.js @@ -464,7 +464,7 @@ erpnext.pos.PointOfSale = class PointOfSale { if (r.message) { this.frm.meta.default_print_format = r.message.print_format || 'POS Invoice'; this.frm.allow_edit_rate = r.message.allow_edit_rate; - this.frm.allow_edit_discount = r.message.allow_edit_discount; + this.frm.allow_edit_discount = r.message.allow_edit_discount; } } @@ -585,6 +585,7 @@ class POSCart { this.numpad && this.numpad.reset_value(); this.customer_field.set_value(""); + this.$discount_amount.find('input:text').val(''); this.wrapper.find('.grand-total-value').text( format_currency(this.frm.doc.grand_total, this.frm.currency)); this.wrapper.find('.rounded-total-value').text( @@ -715,19 +716,15 @@ class POSCart { this.customer_field.set_value(this.frm.doc.customer); } - disable_numpad_control() { - if(!this.frm.allow_edit_rate && !this.frm.allow_edit_discount) { - return ['Rate', 'Disc']; + disable_numpad_control() { + let disabled_btns = []; + if(!this.frm.allow_edit_rate) { + disabled_btns.push('Rate'); } - if(!this.frm.allow_edit_rate || !this.frm.allow_edit_discount) { - if(!this.frm.allow_edit_rate) { - return ['Rate']; - } else { - return ['Disc']; - } - } else { - return []; + if(!this.frm.allow_edit_discount) { + disabled_btns.push('Disc'); } + return disabled_btns; } make_numpad() { From 5e93b02c85042bc591b5aeb2e9f40c153f75ec59 Mon Sep 17 00:00:00 2001 From: Helkyd Date: Fri, 2 Feb 2018 12:27:30 +0000 Subject: [PATCH 32/33] Update trial_balance.py Assuming that Account_number has NUMBERs will sort. --- erpnext/accounts/report/trial_balance/trial_balance.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index f484111be3..7142c69955 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -51,7 +51,7 @@ def validate_filters(filters): filters.to_date = filters.year_end_date def get_data(filters): - accounts = frappe.db.sql("""select name, parent_account, account_name, root_type, report_type, lft, rgt + accounts = frappe.db.sql("""select name, parent_account, account_name, account_number, root_type, report_type, lft, rgt from `tabAccount` where company=%s order by account_name, lft""", filters.company, as_dict=True) company_currency = erpnext.get_company_currency(filters.company) @@ -176,7 +176,7 @@ def accumulate_values_into_parents(accounts, accounts_by_name): def prepare_data(accounts, filters, total_row, parent_children_map, company_currency): data = [] tmpaccnt = sorted(accounts) - if accounts[0].account_name[0].isnumeric(): + if not (accounts[0].account_number is None): accounts = tmpaccnt for d in accounts: From 9d2f04139c1a321a501b3b8ca7c928d2213116a6 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Sat, 3 Feb 2018 09:43:12 +0600 Subject: [PATCH 33/33] bumped to version 10.0.19 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 96ad60f866..76123b1a0b 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__ = '10.0.18' +__version__ = '10.0.19' def get_default_company(user=None): '''Get default company for user'''