From eac87b4764451816158779da2bad3d549218b1ce Mon Sep 17 00:00:00 2001 From: Rohan Bansal Date: Mon, 11 Mar 2019 14:48:26 +0530 Subject: [PATCH 001/115] fix(transaction): Avoid shipping rule charge override by tax template --- erpnext/public/js/controllers/transaction.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 168a727f270..584a3d41088 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1286,7 +1286,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }, callback: function(r) { if(!r.exc) { - me.frm.set_value("taxes", r.message); + for (let tax of r.message) { + me.frm.add_child("taxes", tax); + } me.calculate_taxes_and_totals(); } } From 9c923ae418ec3d7d1a7ac91ba3f48d18d63d0965 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 25 Apr 2019 01:09:56 +0200 Subject: [PATCH 002/115] feat(regional): Report for german tax consultants (DATEV) --- erpnext/regional/report/datev/__init__.py | 0 erpnext/regional/report/datev/datev.js | 26 ++++ erpnext/regional/report/datev/datev.json | 29 +++++ erpnext/regional/report/datev/datev.py | 137 ++++++++++++++++++++++ 4 files changed, 192 insertions(+) create mode 100644 erpnext/regional/report/datev/__init__.py create mode 100644 erpnext/regional/report/datev/datev.js create mode 100644 erpnext/regional/report/datev/datev.json create mode 100644 erpnext/regional/report/datev/datev.py diff --git a/erpnext/regional/report/datev/__init__.py b/erpnext/regional/report/datev/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/regional/report/datev/datev.js b/erpnext/regional/report/datev/datev.js new file mode 100644 index 00000000000..737a84aef24 --- /dev/null +++ b/erpnext/regional/report/datev/datev.js @@ -0,0 +1,26 @@ +frappe.query_reports["DATEV"] = { + "filters": [ + { + "fieldname": "company", + "label": __("Company"), + "fieldtype": "Link", + "options": "Company", + "default": frappe.defaults.get_user_default("Company"), + "reqd": 1 + }, + { + "fieldname": "fiscal_year", + "label": __("Fiscal Year"), + "fieldtype": "Link", + "options": "Fiscal Year", + "default": frappe.defaults.get_user_default("fiscal_year"), + "reqd": 1 + } + ], + onload: function(query_report) { + query_report.export_report = function() { + const filters = JSON.stringify(query_report.get_values()); + window.open(`/api/method/erpnext.regional.report.datev.datev.download_datev_csv?filters=${filters}`); + }; + } +}; diff --git a/erpnext/regional/report/datev/datev.json b/erpnext/regional/report/datev/datev.json new file mode 100644 index 00000000000..d4f44b6fbb6 --- /dev/null +++ b/erpnext/regional/report/datev/datev.json @@ -0,0 +1,29 @@ +{ + "add_total_row": 0, + "apply_user_permissions": 0, + "creation": "2019-04-24 08:45:16.650129", + "disabled": 0, + "icon": "octicon octicon-repo-pull", + "color": "#96cf41", + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "module": "Regional", + "name": "DATEV", + "owner": "Administrator", + "ref_doctype": "GL Entry", + "report_name": "DATEV", + "report_type": "Script Report", + "roles": [ + { + "role": "Accounts User" + }, + { + "role": "Accounts Manager" + }, + { + "role": "Auditor" + } + ] +} diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py new file mode 100644 index 00000000000..268de2874d7 --- /dev/null +++ b/erpnext/regional/report/datev/datev.py @@ -0,0 +1,137 @@ +# coding: utf-8 +from __future__ import unicode_literals +import json +from six import string_types +import frappe +from frappe.utils import format_datetime +from frappe import _ + + +def execute(filters=None): + validate_filters(filters) + result = get_gl_entries(filters, as_dict=0) + columns = get_columns() + + return columns, result + + +def validate_filters(filters): + if not filters.get('company'): + frappe.throw(_('{0} is mandatory').format(_('Company'))) + + if not filters.get('fiscal_year'): + frappe.throw(_('{0} is mandatory').format(_('Fiscal Year'))) + + +def get_columns(): + columns = [ + { + "label": "Umsatz (ohne Soll/Haben-Kz)", + "fieldname": "umsatz", + "fieldtype": "Currency", + }, + { + "label": "Soll/Haben-Kennzeichen", + "fieldname": "soll_haben_kennzeichen", + "fieldtype": "Data", + }, + { + "label": "Kontonummer", + "fieldname": "kontonummer", + "fieldtype": "Data", + }, + { + "label": "Gegenkonto (ohne BU-Schlüssel)", + "fieldname": "gegenkonto_nummer", + "fieldtype": "Data", + }, + { + "label": "Belegdatum", + "fieldname": "belegdatum", + "fieldtype": "Date", + } + ] + + return columns + + +def get_gl_entries(filters, as_dict): + gl_entries = frappe.db.sql(""" + select + + case gl.debit when 0 then gl.credit else gl.debit end as Umsatz, + case gl.debit when 0 then 'H' else 'S' end as Kennzeichen, + coalesce(acc.account_number, acc_pa.account_number) as Kontonummer, + coalesce(acc_against.account_number, acc_against_pa.account_number) as Gegenkonto, + gl.posting_date as Belegdatum + + from `tabGL Entry` gl + + /* Statistisches Konto (Debitoren/Kreditoren) */ + left join `tabParty Account` pa + on gl.against = pa.parent + + /* Kontonummer */ + left join `tabAccount` acc + on gl.account = acc.name + + /* Gegenkonto-Nummer */ + left join `tabAccount` acc_against + on gl.against = acc_against.name + + /* Statistische Kontonummer */ + left join `tabAccount` acc_pa + on pa.account = acc_pa.name + + /* Statistische Gegenkonto-Nummer */ + left join `tabAccount` acc_against_pa + on pa.account = acc_against_pa.name + + where gl.company=%(company)s and gl.fiscal_year=%(fiscal_year)s + order by 'Belegdatum:Date', voucher_no""", filters, as_dict=as_dict) + + return gl_entries + + +def get_datev_csv(data): + title_row = [ + "Umsatz (ohne Soll/Haben-Kz)", + "Soll/Haben-Kennzeichen", + "Kontonummer", + "Gegenkonto (ohne BU-Schlüssel)", + "Belegdatum" + ] + + result = ['"' + '";"'.join(title_row) + '"'] + result += [ + ';'.join( + [ + '{:.2f}'.format(d.get('Umsatz')).replace('.', ','), + '"{}"'.format(d.get('Kennzeichen')), + d.get('Kontonummer'), + # Can be empty, if there are no debtor / creditor accounts + d.get('Gegenkonto') or '', + format_datetime(d.get('Belegdatum'), 'ddMMyyyy') + ] + ) for d in data + ] + + return b'\r\n'.join(result).encode(encoding='latin_1') + + +@frappe.whitelist() +def download_datev_csv(filters=None): + if isinstance(filters, string_types): + filters = json.loads(filters) + + validate_filters(filters) + data = get_gl_entries(filters, as_dict=1) + + filename = 'DATEV_Buchungsstapel_{}-{}'.format( + filters.get('company'), + filters.get('fiscal_year') + ) + + frappe.response['result'] = get_datev_csv(data) + frappe.response['doctype'] = filename + frappe.response['type'] = 'csv' From e82ab87f1cc393cdca63f0a369395ab2599f7ecf Mon Sep 17 00:00:00 2001 From: ashish-greycube Date: Fri, 26 Apr 2019 12:12:53 +0530 Subject: [PATCH 003/115] fix: copy_payment_schedule_from_quot_to_SO --- erpnext/selling/doctype/quotation/quotation.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index 729256068be..8fe20d7b072 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -161,6 +161,10 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False): "Sales Team": { "doctype": "Sales Team", "add_if_empty": True + }, + "Payment Schedule": { + "doctype": "Payment Schedule", + "add_if_empty": True } }, target_doc, set_missing_values, ignore_permissions=ignore_permissions) From e5f7af9e9f1703b53159f046526470a2439f49f0 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 9 May 2019 03:54:49 +0200 Subject: [PATCH 004/115] Use pandas, more columns, filter by date --- erpnext/regional/report/datev/datev.js | 14 ++- erpnext/regional/report/datev/datev.py | 149 ++++++++++++++++++++----- 2 files changed, 128 insertions(+), 35 deletions(-) diff --git a/erpnext/regional/report/datev/datev.js b/erpnext/regional/report/datev/datev.js index 737a84aef24..a556199a046 100644 --- a/erpnext/regional/report/datev/datev.js +++ b/erpnext/regional/report/datev/datev.js @@ -9,11 +9,15 @@ frappe.query_reports["DATEV"] = { "reqd": 1 }, { - "fieldname": "fiscal_year", - "label": __("Fiscal Year"), - "fieldtype": "Link", - "options": "Fiscal Year", - "default": frappe.defaults.get_user_default("fiscal_year"), + "fieldname": "from_date", + "label": __("From Date"), + "fieldtype": "Date", + "reqd": 1 + }, + { + "fieldname": "to_date", + "label": __("To Date"), + "fieldtype": "Date", "reqd": 1 } ], diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index 268de2874d7..5209f34528e 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -5,6 +5,7 @@ from six import string_types import frappe from frappe.utils import format_datetime from frappe import _ +import pandas as pd def execute(filters=None): @@ -19,35 +20,38 @@ def validate_filters(filters): if not filters.get('company'): frappe.throw(_('{0} is mandatory').format(_('Company'))) - if not filters.get('fiscal_year'): - frappe.throw(_('{0} is mandatory').format(_('Fiscal Year'))) + if not filters.get('from_date'): + frappe.throw(_('{0} is mandatory').format(_('From Date'))) + + if not filters.get('to_date'): + frappe.throw(_('{0} is mandatory').format(_('To Date'))) def get_columns(): columns = [ { "label": "Umsatz (ohne Soll/Haben-Kz)", - "fieldname": "umsatz", + "fieldname": "Umsatz (ohne Soll/Haben-Kz)", "fieldtype": "Currency", }, { "label": "Soll/Haben-Kennzeichen", - "fieldname": "soll_haben_kennzeichen", + "fieldname": "Soll/Haben-Kennzeichen", "fieldtype": "Data", }, { "label": "Kontonummer", - "fieldname": "kontonummer", + "fieldname": "Kontonummer", "fieldtype": "Data", }, { "label": "Gegenkonto (ohne BU-Schlüssel)", - "fieldname": "gegenkonto_nummer", + "fieldname": "Gegenkonto (ohne BU-Schlüssel)", "fieldtype": "Data", }, { "label": "Belegdatum", - "fieldname": "belegdatum", + "fieldname": "Belegdatum", "fieldtype": "Date", } ] @@ -59,11 +63,11 @@ def get_gl_entries(filters, as_dict): gl_entries = frappe.db.sql(""" select - case gl.debit when 0 then gl.credit else gl.debit end as Umsatz, - case gl.debit when 0 then 'H' else 'S' end as Kennzeichen, - coalesce(acc.account_number, acc_pa.account_number) as Kontonummer, - coalesce(acc_against.account_number, acc_against_pa.account_number) as Gegenkonto, - gl.posting_date as Belegdatum + case gl.debit when 0 then gl.credit else gl.debit end as 'Umsatz (ohne Soll/Haben-Kz)', + case gl.debit when 0 then 'H' else 'S' end as 'Soll/Haben-Kennzeichen', + coalesce(acc.account_number, acc_pa.account_number) as 'Kontonummer', + coalesce(acc_against.account_number, acc_against_pa.account_number) as 'Gegenkonto (ohne BU-Schlüssel)', + gl.posting_date as 'Belegdatum' from `tabGL Entry` gl @@ -87,36 +91,121 @@ def get_gl_entries(filters, as_dict): left join `tabAccount` acc_against_pa on pa.account = acc_against_pa.name - where gl.company=%(company)s and gl.fiscal_year=%(fiscal_year)s - order by 'Belegdatum:Date', voucher_no""", filters, as_dict=as_dict) + where gl.company = %(company)s + and DATE(gl.posting_date) >= %(from_date)s + and DATE(gl.posting_date) <= %(to_date)s + order by 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict) return gl_entries def get_datev_csv(data): - title_row = [ + columns = [ + # Umsatz "Umsatz (ohne Soll/Haben-Kz)", "Soll/Haben-Kennzeichen", + "WKZ Umsatz", + "Kurs", + "Basis-Umsatz", + "WKZ Basis-Umsatz", + # Konto/Gegenkonto "Kontonummer", "Gegenkonto (ohne BU-Schlüssel)", - "Belegdatum" + "BU-Schlüssel", + # Datum + "Belegdatum", + # Belegfelder + "Belegfeld 1", + "Belegfeld 2", + # Weitere Felder + "Skonto", + "Buchungstext", + # OPOS-Informationen + "Postensperre", + "Diverse Adressnummer", + "Geschäftspartnerbank", + "Sachverhalt", + "Zinssperre", + # Digitaler Beleg + "Beleglink", + # Kostenrechnung + "Kost 1 - Kostenstelle", + "Kost 2 - Kostenstelle", + "Kost-Menge", + # Steuerrechnung + "EU-Land u. UStID", + "EU-Steuersatz", + "Abw. Versteuerungsart", + # L+L Sachverhalt + "Sachverhalt L+L", + "FunktionsergänzungL+L", + # Mengenfelder LuF + "Stück", + "Gewicht", + # Forderungsart + "Zahlweise", + "Forderungsart", + "Veranlagungsjahr", + "Zugeordnete Fälligkeit", + # Weitere Felder + "Skontotyp", + # Anzahlungen + "Auftragsnummer", + "Buchungstyp", + "USt-Schlüssel (Anzahlungen)", + "EU-Land (Anzahlungen)", + "Sachverhalt L+L (Anzahlungen)", + "EU-Steuersatz (Anzahlungen)", + "Erlöskonto (Anzahlungen)", + # Stapelinformationen + "Herkunft-Kz", + # Technische Identifikation + "Buchungs GUID", + # Kostenrechnung + "Kost-Datum", + # OPOS-Informationen + "SEPA-Mandatsreferenz", + "Skontosperre", + # Gesellschafter und Sonderbilanzsachverhalt + "Gesellschaftername", + "Beteiligtennummer", + "Identifikationsnummer", + "Zeichnernummer", + # OPOS-Informationen + "Postensperre bis", + # Gesellschafter und Sonderbilanzsachverhalt + "Bezeichnung SoBil-Sachverhalt", + "Kennzeichen SoBil-Buchung", + # Stapelinformationen + "Festschreibung", + # Datum + "Leistungsdatum", + "Datum Zuord. Steuerperiode", + # OPOS-Informationen + "Fälligkeit", + # Konto/Gegenkonto + "Generalumkehr (GU)", + # Steuersatz für Steuerschlüssel + "Steuersatz", + "Land" ] - result = ['"' + '";"'.join(title_row) + '"'] - result += [ - ';'.join( - [ - '{:.2f}'.format(d.get('Umsatz')).replace('.', ','), - '"{}"'.format(d.get('Kennzeichen')), - d.get('Kontonummer'), - # Can be empty, if there are no debtor / creditor accounts - d.get('Gegenkonto') or '', - format_datetime(d.get('Belegdatum'), 'ddMMyyyy') - ] - ) for d in data - ] + empty_df = pd.DataFrame(columns=columns) - return b'\r\n'.join(result).encode(encoding='latin_1') + data_df = pd.DataFrame.from_records(data) + data_df["Belegdatum"] = pd.to_datetime(data_df["Belegdatum"]) + + result = empty_df.append(data_df) + + return result.to_csv( + sep=b';', + decimal=',', + encoding='latin_1', + date_format='%d%m', + line_terminator=b'\r\n', + index=False, + columns=columns + ) @frappe.whitelist() From 4b2901704cf4fa613c7b050fb0c18f32b001b0c8 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 9 May 2019 04:03:23 +0200 Subject: [PATCH 005/115] Add download button --- erpnext/regional/report/datev/datev.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/report/datev/datev.js b/erpnext/regional/report/datev/datev.js index a556199a046..781862c2a6a 100644 --- a/erpnext/regional/report/datev/datev.js +++ b/erpnext/regional/report/datev/datev.js @@ -22,9 +22,9 @@ frappe.query_reports["DATEV"] = { } ], onload: function(query_report) { - query_report.export_report = function() { + query_report.page.add_inner_button("Download DATEV Export", () => { const filters = JSON.stringify(query_report.get_values()); window.open(`/api/method/erpnext.regional.report.datev.datev.download_datev_csv?filters=${filters}`); - }; + }); } }; From 9eef60754da9c27527a21bbd627b0e1bbe56fc2d Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Sun, 12 May 2019 02:24:39 +0200 Subject: [PATCH 006/115] remove unused import --- erpnext/regional/report/datev/datev.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index 5209f34528e..e6d1cbfbf38 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import json from six import string_types import frappe -from frappe.utils import format_datetime from frappe import _ import pandas as pd From 2701f944911d98b2a6e829392814f98928d10980 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Tue, 21 May 2019 21:58:35 +0200 Subject: [PATCH 007/115] add remarks and voucher info --- erpnext/regional/report/datev/datev.py | 37 +++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index e6d1cbfbf38..4a6e0ef27e1 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -52,6 +52,31 @@ def get_columns(): "label": "Belegdatum", "fieldname": "Belegdatum", "fieldtype": "Date", + }, + { + "label": "Buchungstext", + "fieldname": "Buchungstext", + "fieldtype": "Text", + }, + { + "label": "Beleginfo - Art 1", + "fieldname": "Beleginfo - Art 1", + "fieldtype": "Data", + }, + { + "label": "Beleginfo - Inhalt 1", + "fieldname": "Beleginfo - Inhalt 1", + "fieldtype": "Data", + }, + { + "label": "Beleginfo - Art 2", + "fieldname": "Beleginfo - Art 2", + "fieldtype": "Data", + }, + { + "label": "Beleginfo - Inhalt 2", + "fieldname": "Beleginfo - Inhalt 2", + "fieldtype": "Data", } ] @@ -66,7 +91,12 @@ def get_gl_entries(filters, as_dict): case gl.debit when 0 then 'H' else 'S' end as 'Soll/Haben-Kennzeichen', coalesce(acc.account_number, acc_pa.account_number) as 'Kontonummer', coalesce(acc_against.account_number, acc_against_pa.account_number) as 'Gegenkonto (ohne BU-Schlüssel)', - gl.posting_date as 'Belegdatum' + gl.posting_date as 'Belegdatum', + gl.remarks as 'Buchungstext', + gl.voucher_type as 'Beleginfo - Art 1', + gl.voucher_no as 'Beleginfo - Inhalt 1', + gl.against_voucher_type as 'Beleginfo - Art 2', + gl.against_voucher as 'Beleginfo - Inhalt 2' from `tabGL Entry` gl @@ -127,6 +157,11 @@ def get_datev_csv(data): "Zinssperre", # Digitaler Beleg "Beleglink", + # Beleginfo + "Beleginfo - Art 1", + "Beleginfo - Inhalt 1", + "Beleginfo - Art 2", + "Beleginfo - Inhalt 2", # Kostenrechnung "Kost 1 - Kostenstelle", "Kost 2 - Kostenstelle", From 50de88417c1ce6dd08fee257a5144c043aa160b4 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Tue, 21 May 2019 21:59:04 +0200 Subject: [PATCH 008/115] fix filename --- erpnext/regional/report/datev/datev.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index 4a6e0ef27e1..2012fa21bff 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -250,9 +250,10 @@ def download_datev_csv(filters=None): validate_filters(filters) data = get_gl_entries(filters, as_dict=1) - filename = 'DATEV_Buchungsstapel_{}-{}'.format( + filename = 'DATEV_Buchungsstapel_{}-{}_bis_{}'.format( filters.get('company'), - filters.get('fiscal_year') + filters.get('from_date'), + filters.get('to_date') ) frappe.response['result'] = get_datev_csv(data) From ce9239af83b519b7aad810b407acac587f022b02 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Tue, 21 May 2019 22:49:59 +0200 Subject: [PATCH 009/115] fix error when downloading empty report --- erpnext/regional/report/datev/datev.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index 2012fa21bff..8b05ad0878c 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -225,11 +225,10 @@ def get_datev_csv(data): ] empty_df = pd.DataFrame(columns=columns) - data_df = pd.DataFrame.from_records(data) - data_df["Belegdatum"] = pd.to_datetime(data_df["Belegdatum"]) result = empty_df.append(data_df) + result["Belegdatum"] = pd.to_datetime(result["Belegdatum"]) return result.to_csv( sep=b';', From 31f505528705f7b1a40749cacb273a7341340ec6 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Wed, 22 May 2019 00:03:16 +0200 Subject: [PATCH 010/115] fix sql for multi-company case --- erpnext/regional/report/datev/datev.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index 8b05ad0878c..84bd52926b8 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -103,6 +103,7 @@ def get_gl_entries(filters, as_dict): /* Statistisches Konto (Debitoren/Kreditoren) */ left join `tabParty Account` pa on gl.against = pa.parent + and gl.company = pa.company /* Kontonummer */ left join `tabAccount` acc From 9638f0ef2b1234bf84207b2c892cb49ffde2a7a0 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Mon, 27 May 2019 14:42:52 +0200 Subject: [PATCH 011/115] Add columns to CSV, add comments and docstrings --- erpnext/regional/report/datev/datev.py | 122 ++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 5 deletions(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index 84bd52926b8..6ca1fe54c85 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -1,4 +1,12 @@ # coding: utf-8 +""" +Provide a report and downloadable CSV according to the German DATEV format. + +- Query report showing only the columns that contain data, formatted nicely for + dispay to the user. +- CSV download functionality `download_datev_csv` that provides a CSV file with + all required columns. Used to import the data into the DATEV Software. +""" from __future__ import unicode_literals import json from six import string_types @@ -8,6 +16,7 @@ import pandas as pd def execute(filters=None): + """Entry point for frappe.""" validate_filters(filters) result = get_gl_entries(filters, as_dict=0) columns = get_columns() @@ -16,6 +25,7 @@ def execute(filters=None): def validate_filters(filters): + """Make sure all mandatory filters are present.""" if not filters.get('company'): frappe.throw(_('{0} is mandatory').format(_('Company'))) @@ -27,6 +37,7 @@ def validate_filters(filters): def get_columns(): + """Return the list of columns that will be shown in query report.""" columns = [ { "label": "Umsatz (ohne Soll/Haben-Kz)", @@ -84,13 +95,31 @@ def get_columns(): def get_gl_entries(filters, as_dict): + """ + Get a list of accounting entries. + + Select GL Entries joined with Account and Party Account in order to get the + account numbers. Returns a list of accounting entries. + + Arguments: + filters -- dict of filters to be passed to the sql query + as_dict -- return as list of dicts [0,1] + """ gl_entries = frappe.db.sql(""" select + /* either debit or credit amount; always positive */ case gl.debit when 0 then gl.credit else gl.debit end as 'Umsatz (ohne Soll/Haben-Kz)', + + /* 'H' when credit, 'S' when debit */ case gl.debit when 0 then 'H' else 'S' end as 'Soll/Haben-Kennzeichen', + + /* account number or, if empty, party account number */ coalesce(acc.account_number, acc_pa.account_number) as 'Kontonummer', + + /* against number or, if empty, party against number */ coalesce(acc_against.account_number, acc_against_pa.account_number) as 'Gegenkonto (ohne BU-Schlüssel)', + gl.posting_date as 'Belegdatum', gl.remarks as 'Buchungstext', gl.voucher_type as 'Beleginfo - Art 1', @@ -130,7 +159,16 @@ def get_gl_entries(filters, as_dict): def get_datev_csv(data): + """ + Fill in missing columns and return a CSV in DATEV Format. + + Arguments: + data -- array of dictionaries + """ columns = [ + # All possible columns must tbe listed here, because DATEV requires them to + # be present in the CSV. + # --- # Umsatz "Umsatz (ohne Soll/Haben-Kz)", "Soll/Haben-Kennzeichen", @@ -159,10 +197,22 @@ def get_datev_csv(data): # Digitaler Beleg "Beleglink", # Beleginfo - "Beleginfo - Art 1", - "Beleginfo - Inhalt 1", - "Beleginfo - Art 2", - "Beleginfo - Inhalt 2", + "Beleginfo – Art 1", + "Beleginfo – Inhalt 1", + "Beleginfo – Art 2", + "Beleginfo – Inhalt 2", + "Beleginfo – Art 3", + "Beleginfo – Inhalt 3", + "Beleginfo – Art 4", + "Beleginfo – Inhalt 4", + "Beleginfo – Art 5", + "Beleginfo – Inhalt 5", + "Beleginfo – Art 6", + "Beleginfo – Inhalt 6", + "Beleginfo – Art 7", + "Beleginfo – Inhalt 7", + "Beleginfo – Art 8", + "Beleginfo – Inhalt 8", # Kostenrechnung "Kost 1 - Kostenstelle", "Kost 2 - Kostenstelle", @@ -173,7 +223,52 @@ def get_datev_csv(data): "Abw. Versteuerungsart", # L+L Sachverhalt "Sachverhalt L+L", - "FunktionsergänzungL+L", + "Funktionsergänzung L+L", + # Funktion Steuerschlüssel 49 + "BU 49 Hauptfunktionstyp", + "BU 49 Hauptfunktionsnummer", + "BU 49 Funktionsergänzung", + # Zusatzinformationen + "Zusatzinformation – Art 1", + "Zusatzinformation – Inhalt 1", + "Zusatzinformation – Art 2", + "Zusatzinformation – Inhalt 2", + "Zusatzinformation – Art 3", + "Zusatzinformation – Inhalt 3", + "Zusatzinformation – Art 4", + "Zusatzinformation – Inhalt 4", + "Zusatzinformation – Art 5", + "Zusatzinformation – Inhalt 5", + "Zusatzinformation – Art 6", + "Zusatzinformation – Inhalt 6", + "Zusatzinformation – Art 7", + "Zusatzinformation – Inhalt 7", + "Zusatzinformation – Art 8", + "Zusatzinformation – Inhalt 8", + "Zusatzinformation – Art 9", + "Zusatzinformation – Inhalt 9", + "Zusatzinformation – Art 10", + "Zusatzinformation – Inhalt 10", + "Zusatzinformation – Art 11", + "Zusatzinformation – Inhalt 11", + "Zusatzinformation – Art 12", + "Zusatzinformation – Inhalt 12", + "Zusatzinformation – Art 13", + "Zusatzinformation – Inhalt 13", + "Zusatzinformation – Art 14", + "Zusatzinformation – Inhalt 14", + "Zusatzinformation – Art 15", + "Zusatzinformation – Inhalt 15", + "Zusatzinformation – Art 16", + "Zusatzinformation – Inhalt 16", + "Zusatzinformation – Art 17", + "Zusatzinformation – Inhalt 17", + "Zusatzinformation – Art 18", + "Zusatzinformation – Inhalt 18", + "Zusatzinformation – Art 19", + "Zusatzinformation – Inhalt 19", + "Zusatzinformation – Art 20", + "Zusatzinformation – Inhalt 20", # Mengenfelder LuF "Stück", "Gewicht", @@ -233,17 +328,34 @@ def get_datev_csv(data): return result.to_csv( sep=b';', + # European decimal seperator decimal=',', + # Windows "ANSI" encoding encoding='latin_1', + # format date as DDMM date_format='%d%m', + # Windows line terminator line_terminator=b'\r\n', + # Do not number rows index=False, + # Use all columns defined above columns=columns ) @frappe.whitelist() def download_datev_csv(filters=None): + """ + Provide accounting entries for download in DATEV format. + + Validate the filters, get the data, produce the CSV file and provide it for + download. Can be called like this: + + GET /api/method/erpnext.regional.report.datev.datev.download_datev_csv + + Arguments / Params: + filters -- dict of filters to be passed to the sql query + """ if isinstance(filters, string_types): filters = json.loads(filters) From b7b5bcbd855a8b23eda9929f8c3ab66215fe15ab Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Mon, 27 May 2019 15:05:08 +0200 Subject: [PATCH 012/115] fix: em dash cannot be encoded in latin-1 --- erpnext/regional/report/datev/datev.py | 112 ++++++++++++------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index 6ca1fe54c85..50aed084aba 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -197,22 +197,22 @@ def get_datev_csv(data): # Digitaler Beleg "Beleglink", # Beleginfo - "Beleginfo – Art 1", - "Beleginfo – Inhalt 1", - "Beleginfo – Art 2", - "Beleginfo – Inhalt 2", - "Beleginfo – Art 3", - "Beleginfo – Inhalt 3", - "Beleginfo – Art 4", - "Beleginfo – Inhalt 4", - "Beleginfo – Art 5", - "Beleginfo – Inhalt 5", - "Beleginfo – Art 6", - "Beleginfo – Inhalt 6", - "Beleginfo – Art 7", - "Beleginfo – Inhalt 7", - "Beleginfo – Art 8", - "Beleginfo – Inhalt 8", + "Beleginfo - Art 1", + "Beleginfo - Inhalt 1", + "Beleginfo - Art 2", + "Beleginfo - Inhalt 2", + "Beleginfo - Art 3", + "Beleginfo - Inhalt 3", + "Beleginfo - Art 4", + "Beleginfo - Inhalt 4", + "Beleginfo - Art 5", + "Beleginfo - Inhalt 5", + "Beleginfo - Art 6", + "Beleginfo - Inhalt 6", + "Beleginfo - Art 7", + "Beleginfo - Inhalt 7", + "Beleginfo - Art 8", + "Beleginfo - Inhalt 8", # Kostenrechnung "Kost 1 - Kostenstelle", "Kost 2 - Kostenstelle", @@ -229,46 +229,46 @@ def get_datev_csv(data): "BU 49 Hauptfunktionsnummer", "BU 49 Funktionsergänzung", # Zusatzinformationen - "Zusatzinformation – Art 1", - "Zusatzinformation – Inhalt 1", - "Zusatzinformation – Art 2", - "Zusatzinformation – Inhalt 2", - "Zusatzinformation – Art 3", - "Zusatzinformation – Inhalt 3", - "Zusatzinformation – Art 4", - "Zusatzinformation – Inhalt 4", - "Zusatzinformation – Art 5", - "Zusatzinformation – Inhalt 5", - "Zusatzinformation – Art 6", - "Zusatzinformation – Inhalt 6", - "Zusatzinformation – Art 7", - "Zusatzinformation – Inhalt 7", - "Zusatzinformation – Art 8", - "Zusatzinformation – Inhalt 8", - "Zusatzinformation – Art 9", - "Zusatzinformation – Inhalt 9", - "Zusatzinformation – Art 10", - "Zusatzinformation – Inhalt 10", - "Zusatzinformation – Art 11", - "Zusatzinformation – Inhalt 11", - "Zusatzinformation – Art 12", - "Zusatzinformation – Inhalt 12", - "Zusatzinformation – Art 13", - "Zusatzinformation – Inhalt 13", - "Zusatzinformation – Art 14", - "Zusatzinformation – Inhalt 14", - "Zusatzinformation – Art 15", - "Zusatzinformation – Inhalt 15", - "Zusatzinformation – Art 16", - "Zusatzinformation – Inhalt 16", - "Zusatzinformation – Art 17", - "Zusatzinformation – Inhalt 17", - "Zusatzinformation – Art 18", - "Zusatzinformation – Inhalt 18", - "Zusatzinformation – Art 19", - "Zusatzinformation – Inhalt 19", - "Zusatzinformation – Art 20", - "Zusatzinformation – Inhalt 20", + "Zusatzinformation - Art 1", + "Zusatzinformation - Inhalt 1", + "Zusatzinformation - Art 2", + "Zusatzinformation - Inhalt 2", + "Zusatzinformation - Art 3", + "Zusatzinformation - Inhalt 3", + "Zusatzinformation - Art 4", + "Zusatzinformation - Inhalt 4", + "Zusatzinformation - Art 5", + "Zusatzinformation - Inhalt 5", + "Zusatzinformation - Art 6", + "Zusatzinformation - Inhalt 6", + "Zusatzinformation - Art 7", + "Zusatzinformation - Inhalt 7", + "Zusatzinformation - Art 8", + "Zusatzinformation - Inhalt 8", + "Zusatzinformation - Art 9", + "Zusatzinformation - Inhalt 9", + "Zusatzinformation - Art 10", + "Zusatzinformation - Inhalt 10", + "Zusatzinformation - Art 11", + "Zusatzinformation - Inhalt 11", + "Zusatzinformation - Art 12", + "Zusatzinformation - Inhalt 12", + "Zusatzinformation - Art 13", + "Zusatzinformation - Inhalt 13", + "Zusatzinformation - Art 14", + "Zusatzinformation - Inhalt 14", + "Zusatzinformation - Art 15", + "Zusatzinformation - Inhalt 15", + "Zusatzinformation - Art 16", + "Zusatzinformation - Inhalt 16", + "Zusatzinformation - Art 17", + "Zusatzinformation - Inhalt 17", + "Zusatzinformation - Art 18", + "Zusatzinformation - Inhalt 18", + "Zusatzinformation - Art 19", + "Zusatzinformation - Inhalt 19", + "Zusatzinformation - Art 20", + "Zusatzinformation - Inhalt 20", # Mengenfelder LuF "Stück", "Gewicht", From 1c1a5958bc4ed65ceeb746e43177de285cb2bed4 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Mon, 27 May 2019 15:05:32 +0200 Subject: [PATCH 013/115] more pleasant icon color --- erpnext/regional/report/datev/datev.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/report/datev/datev.json b/erpnext/regional/report/datev/datev.json index d4f44b6fbb6..80a866cbf5c 100644 --- a/erpnext/regional/report/datev/datev.json +++ b/erpnext/regional/report/datev/datev.json @@ -4,7 +4,7 @@ "creation": "2019-04-24 08:45:16.650129", "disabled": 0, "icon": "octicon octicon-repo-pull", - "color": "#96cf41", + "color": "#4CB944", "docstatus": 0, "doctype": "Report", "idx": 0, From 0261472ecd305ac405dd7604913cf2b359e7bbbd Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Mon, 27 May 2019 16:01:05 +0200 Subject: [PATCH 014/115] add default filters --- erpnext/regional/report/datev/datev.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/regional/report/datev/datev.js b/erpnext/regional/report/datev/datev.js index 781862c2a6a..1e000b673e6 100644 --- a/erpnext/regional/report/datev/datev.js +++ b/erpnext/regional/report/datev/datev.js @@ -5,18 +5,20 @@ frappe.query_reports["DATEV"] = { "label": __("Company"), "fieldtype": "Link", "options": "Company", - "default": frappe.defaults.get_user_default("Company"), + "default": frappe.defaults.get_user_default("Company") || frappe.defaults.get_global_default("Company"), "reqd": 1 }, { "fieldname": "from_date", "label": __("From Date"), + "default": frappe.datetime.month_start(), "fieldtype": "Date", "reqd": 1 }, { "fieldname": "to_date", "label": __("To Date"), + "default": frappe.datetime.now_date(), "fieldtype": "Date", "reqd": 1 } From 1d11ddc23524201b81d8b815a83612b6a621ff13 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 10 Jun 2019 17:33:36 +0530 Subject: [PATCH 015/115] fix: Available qty not shown in item batch selector for batch --- .../js/utils/serial_no_batch_selector.js | 65 ++++++++++--------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index df50884ce71..d9c84f5c463 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -233,30 +233,32 @@ erpnext.SerialNoBatchSelector = Class.extend({ get_batch_fields: function() { var me = this; return [ - {fieldtype:'Section Break', label: __('Batches')}, - {fieldname: 'batches', fieldtype: 'Table', + { fieldtype: 'Section Break', label: __('Batches') }, + { + fieldname: 'batches', fieldtype: 'Table', fields: [ { - fieldtype:'Link', - fieldname:'batch_no', - options: 'Batch', - label: __('Select Batch'), - in_list_view:1, - get_query: function() { + 'fieldtype': 'Link', + 'read_only': 0, + 'fieldname': 'batch_no', + 'options': 'Batch', + 'label': __('Select Batch'), + 'in_list_view': 1, + get_query: function () { return { - filters: {item: me.item_code }, - query: 'erpnext.controllers.queries.get_batch_numbers' - }; + filters: { item: me.item_code }, + query: 'erpnext.controllers.queries.get_batch_numbers' + }; }, - onchange: function(e) { + change: function (e) { let val = this.get_value(); - if(val.length === 0) { + if (val.length === 0) { this.grid_row.on_grid_fields_dict .available_qty.set_value(0); return; } let selected_batches = this.grid.grid_rows.map((row) => { - if(row === this.grid_row) { + if (row === this.grid_row) { return ""; } @@ -264,12 +266,12 @@ erpnext.SerialNoBatchSelector = Class.extend({ return row.on_grid_fields_dict.batch_no.get_value(); } }); - if(selected_batches.includes(val)) { + if (selected_batches.includes(val)) { this.set_value(""); frappe.throw(__(`Batch ${val} already selected.`)); return; } - if(me.warehouse_details.name) { + if (me.warehouse_details.name) { frappe.call({ method: 'erpnext.stock.doctype.batch.batch.get_batch_qty', args: { @@ -292,31 +294,32 @@ erpnext.SerialNoBatchSelector = Class.extend({ } }, { - fieldtype:'Float', - read_only:1, - fieldname:'available_qty', - label: __('Available'), - in_list_view:1, - default: 0, - onchange: function() { + 'fieldtype': 'Float', + 'read_only': 1, + 'fieldname': 'available_qty', + 'label': __('Available'), + 'in_list_view': 1, + 'default': 0, + change: function () { this.grid_row.on_grid_fields_dict.selected_qty.set_value('0'); } }, { - fieldtype:'Float', - fieldname:'selected_qty', - label: __('Qty'), - in_list_view:1, + 'fieldtype': 'Float', + 'read_only': 0, + 'fieldname': 'selected_qty', + 'label': __('Qty'), + 'in_list_view': 1, 'default': 0, - onchange: function(e) { + change: function (e) { var batch_no = this.grid_row.on_grid_fields_dict.batch_no.get_value(); var available_qty = this.grid_row.on_grid_fields_dict.available_qty.get_value(); var selected_qty = this.grid_row.on_grid_fields_dict.selected_qty.get_value(); - if(batch_no.length === 0 && parseInt(selected_qty)!==0) { + if (batch_no.length === 0 && parseInt(selected_qty) !== 0) { frappe.throw(__("Please select a batch")); } - if(me.warehouse_details.type === 'Source Warehouse' && + if (me.warehouse_details.type === 'Source Warehouse' && parseFloat(available_qty) < parseFloat(selected_qty)) { this.set_value('0'); @@ -332,7 +335,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ ], in_place_edit: true, data: this.data, - get_data: function() { + get_data: function () { return this.data; }, } From 2de80fdc3ecc1ed5a4ba782056783bad9be28ffa Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 10 Jun 2019 17:51:47 +0530 Subject: [PATCH 016/115] fix: Codacy --- erpnext/public/js/utils/serial_no_batch_selector.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index d9c84f5c463..0202bbb872a 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -250,7 +250,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ query: 'erpnext.controllers.queries.get_batch_numbers' }; }, - change: function (e) { + change: function () { let val = this.get_value(); if (val.length === 0) { this.grid_row.on_grid_fields_dict @@ -311,7 +311,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ 'label': __('Qty'), 'in_list_view': 1, 'default': 0, - change: function (e) { + change: function () { var batch_no = this.grid_row.on_grid_fields_dict.batch_no.get_value(); var available_qty = this.grid_row.on_grid_fields_dict.available_qty.get_value(); var selected_qty = this.grid_row.on_grid_fields_dict.selected_qty.get_value(); From 1174e5a1278b26537470371cf7fa285f4419ad21 Mon Sep 17 00:00:00 2001 From: Rohan Bansal Date: Tue, 11 Jun 2019 14:44:45 +0530 Subject: [PATCH 017/115] fix(stock): Remove hardcoded validation for Item --- erpnext/stock/doctype/item/item.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 16fd811fee3..c5697eda7a8 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -67,8 +67,6 @@ class Item(WebsiteGenerator): from frappe.model.naming import set_name_by_naming_series set_name_by_naming_series(self) self.item_code = self.name - elif not self.item_code: - msgprint(_("Item Code is mandatory because Item is not automatically numbered"), raise_exception=1) self.item_code = strip(self.item_code) self.name = self.item_code From 860b6bac75bad1fffd09ef296426fe1f123abbe1 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 13 Jun 2019 14:28:46 +0530 Subject: [PATCH 018/115] fix: get bom item when company is not passed --- erpnext/stock/doctype/material_request/material_request.js | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index fe1319103a8..a0fc3f34e20 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -186,6 +186,7 @@ frappe.ui.form.on('Material Request', { var values = d.get_values(); if(!values) return; values["company"] = frm.doc.company; + if(!frm.doc.company) frappe.throw(__("Company field is required")); frappe.call({ method: "erpnext.manufacturing.doctype.bom.bom.get_bom_items", args: values, From ffd6b27f4b6b367dd2c5f4cbb77441ba8dda0d31 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 13 Jun 2019 14:33:47 +0530 Subject: [PATCH 019/115] fix: Fixed setters for getting items from quotation/opportunity --- .../selling/doctype/quotation/quotation.js | 27 ++++++++++++------- .../doctype/sales_order/sales_order.js | 14 +++++++--- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js index 1a31db92cb3..02d293d3236 100644 --- a/erpnext/selling/doctype/quotation/quotation.js +++ b/erpnext/selling/doctype/quotation/quotation.js @@ -90,22 +90,29 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({ if (this.frm.doc.docstatus===0) { this.frm.add_custom_button(__('Opportunity'), function() { - var setters = {}; - if(me.frm.doc.quotation_to == "Customer" && me.frm.doc.party_name) { - setters.customer = me.frm.doc.party_name || undefined; - } else if (me.frm.doc.quotation_to == "Lead" && me.frm.doc.party_name) { - setters.lead = me.frm.doc.party_name || undefined; - } erpnext.utils.map_current_doc({ method: "erpnext.crm.doctype.opportunity.opportunity.make_quotation", source_doctype: "Opportunity", target: me.frm, - setters: setters, + setters: [ + { + label: "Party", + fieldname: "party_name", + fieldtype: "Link", + options: me.frm.doc.quotation_to, + default: me.frm.doc.party_name || undefined + }, + { + label: "Opportunity Type", + fieldname: "opportunity_type", + fieldtype: "Link", + options: "Opportunity Type", + default: me.frm.doc.order_type || undefined + } + ], get_query_filters: { status: ["not in", ["Lost", "Closed"]], - company: me.frm.doc.company, - // cannot set opportunity_type as setter, as the fieldname is order_type - opportunity_type: me.frm.doc.order_type, + company: me.frm.doc.company } }) }, __("Get items from"), "btn-default"); diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 6cdb4f88840..53b3e73f5e2 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -219,13 +219,19 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( method: "erpnext.selling.doctype.quotation.quotation.make_sales_order", source_doctype: "Quotation", target: me.frm, - setters: { - customer: me.frm.doc.customer || undefined - }, + setters: [ + { + label: "Customer", + fieldname: "party_name", + fieldtype: "Link", + options: "Customer", + default: me.frm.doc.customer || undefined + } + ], get_query_filters: { company: me.frm.doc.company, docstatus: 1, - status: ["!=", "Lost"], + status: ["!=", "Lost"] } }) }, __("Get items from")); From 49c6c909f8e23f2fbe98bd6df71a617149f5c507 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 13 Jun 2019 15:42:13 +0530 Subject: [PATCH 020/115] fix: taxes are not overriding after changing the taxes template --- erpnext/accounts/doctype/sales_invoice/sales_invoice.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index a836a1813e6..5393f5d37fb 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -371,6 +371,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte me.frm.pos_print_format = r.message.print_format; } me.frm.script_manager.trigger("update_stock"); + if(me.frm.doc.taxes_and_charges) { + me.frm.script_manager.trigger("taxes_and_charges"); + } + frappe.model.set_default_values(me.frm.doc); me.set_dynamic_labels(); me.calculate_taxes_and_totals(); From 2fc6d1d210b0e07b98a2dff446d84f168b793602 Mon Sep 17 00:00:00 2001 From: Anurag Mishra Date: Thu, 13 Jun 2019 16:09:30 +0530 Subject: [PATCH 021/115] fix: column sequence and width --- erpnext/projects/report/billing_summary.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/erpnext/projects/report/billing_summary.py b/erpnext/projects/report/billing_summary.py index 929a13f6683..76379f1de2e 100644 --- a/erpnext/projects/report/billing_summary.py +++ b/erpnext/projects/report/billing_summary.py @@ -30,23 +30,23 @@ def get_columns(): "options": "Timesheet", "width": 150 }, - { - "label": _("Billable Hours"), - "fieldtype": "Float", - "fieldname": "total_billable_hours", - "width": 50 - }, { "label": _("Working Hours"), "fieldtype": "Float", "fieldname": "total_hours", - "width": 50 + "width": 150 + }, + { + "label": _("Billable Hours"), + "fieldtype": "Float", + "fieldname": "total_billable_hours", + "width": 150 }, { "label": _("Billing Amount"), "fieldtype": "Currency", "fieldname": "amount", - "width": 100 + "width": 150 } ] From a59aaf48f2476a681181ea8a8666c9c8321827b1 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 13 Jun 2019 19:43:47 +0530 Subject: [PATCH 022/115] fix: salary slip amount calculation based on formula --- erpnext/hr/doctype/salary_slip/salary_slip.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index ffd786836a5..d3b960d29eb 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -445,6 +445,8 @@ class SalarySlip(TransactionBase): if not overwrite and component_row.default_amount: amount += component_row.default_amount + else: + component_row.default_amount = amount component_row.amount = amount component_row.deduct_full_tax_on_selected_payroll_date = struct_row.deduct_full_tax_on_selected_payroll_date From f7af9b87457564506c89564165c0cce137ae3fca Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 14 Jun 2019 11:22:23 +0530 Subject: [PATCH 023/115] fix: trial balance opening balance not showing in the debit side for the liability account (#17786) --- .../report/trial_balance/trial_balance.py | 57 +++++++++---------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index 6b18c5d8731..b5f0186d4d2 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -180,20 +180,28 @@ def calculate_values(accounts, gl_entries_by_account, opening_balances, filters, if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense": d["opening_debit"] -= d["opening_credit"] - d["opening_credit"] = 0.0 - total_row["opening_debit"] += d["opening_debit"] + d["closing_debit"] -= d["closing_credit"] + + # For opening + check_opening_closing_has_negative_value(d, "opening_debit", "opening_credit") + + # For closing + check_opening_closing_has_negative_value(d, "closing_debit", "closing_credit") + if d["root_type"] == "Liability" or d["root_type"] == "Income": d["opening_credit"] -= d["opening_debit"] - d["opening_debit"] = 0.0 - total_row["opening_credit"] += d["opening_credit"] - if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense": - d["closing_debit"] -= d["closing_credit"] - d["closing_credit"] = 0.0 - total_row["closing_debit"] += d["closing_debit"] - if d["root_type"] == "Liability" or d["root_type"] == "Income": d["closing_credit"] -= d["closing_debit"] - d["closing_debit"] = 0.0 - total_row["closing_credit"] += d["closing_credit"] + + # For opening + check_opening_closing_has_negative_value(d, "opening_credit", "opening_debit") + + # For closing + check_opening_closing_has_negative_value(d, "closing_credit", "closing_debit") + + total_row["opening_debit"] += d["opening_debit"] + total_row["closing_debit"] += d["closing_debit"] + total_row["opening_credit"] += d["opening_credit"] + total_row["closing_credit"] += d["closing_credit"] return total_row @@ -219,8 +227,6 @@ def prepare_data(accounts, filters, total_row, parent_children_map, company_curr if d.account_number else d.account_name) } - prepare_opening_and_closing(d) - for key in value_fields: row[key] = flt(d.get(key, 0.0), 3) @@ -295,22 +301,11 @@ def get_columns(): } ] -def prepare_opening_and_closing(d): - d["closing_debit"] = d["opening_debit"] + d["debit"] - d["closing_credit"] = d["opening_credit"] + d["credit"] +def check_opening_closing_has_negative_value(d, dr_or_cr, switch_to_column): + # If opening debit has negetive value then move it to opening credit and vice versa. - if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense": - d["opening_debit"] -= d["opening_credit"] - d["opening_credit"] = 0.0 - - if d["root_type"] == "Liability" or d["root_type"] == "Income": - d["opening_credit"] -= d["opening_debit"] - d["opening_debit"] = 0.0 - - if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense": - d["closing_debit"] -= d["closing_credit"] - d["closing_credit"] = 0.0 - - if d["root_type"] == "Liability" or d["root_type"] == "Income": - d["closing_credit"] -= d["closing_debit"] - d["closing_debit"] = 0.0 + if d[dr_or_cr] < 0: + d[switch_to_column] = abs(d[dr_or_cr]) + d[dr_or_cr] = 0.0 + else: + d[switch_to_column] = 0.0 From 1450a7b40822d487c6940dde465f60c97fa4b74c Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Fri, 14 Jun 2019 11:29:29 +0530 Subject: [PATCH 024/115] fix column width (#17936) --- .../budget_variance_report.py | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py index b292bd33b9b..0f802d88cc4 100644 --- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py +++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py @@ -45,8 +45,8 @@ def execute(filters=None): if(filters.get("show_cumulative")): last_total = period_data[0] - period_data[1] - - period_data[2] = period_data[0] - period_data[1] + + period_data[2] = period_data[0] - period_data[1] row += period_data totals[2] = totals[0] - totals[1] if filters["period"] != "Yearly" : @@ -60,7 +60,7 @@ def validate_filters(filters): frappe.throw(_("Filter based on Cost Center is only applicable if Budget Against is selected as Cost Center")) def get_columns(filters): - columns = [_(filters.get("budget_against")) + ":Link/%s:80"%(filters.get("budget_against")), _("Account") + ":Link/Account:80"] + columns = [_(filters.get("budget_against")) + ":Link/%s:150"%(filters.get("budget_against")), _("Account") + ":Link/Account:150"] group_months = False if filters["period"] == "Monthly" else True @@ -71,7 +71,7 @@ def get_columns(filters): if filters["period"] == "Yearly": labels = [_("Budget") + " " + str(year[0]), _("Actual ") + " " + str(year[0]), _("Varaiance ") + " " + str(year[0])] for label in labels: - columns.append(label+":Float:80") + columns.append(label+":Float:150") else: for label in [_("Budget") + " (%s)" + " " + str(year[0]), _("Actual") + " (%s)" + " " + str(year[0]), _("Variance") + " (%s)" + " " + str(year[0])]: if group_months: @@ -79,20 +79,20 @@ def get_columns(filters): else: label = label % formatdate(from_date, format_string="MMM") - columns.append(label+":Float:80") + columns.append(label+":Float:150") if filters["period"] != "Yearly" : - return columns + [_("Total Budget") + ":Float:80", _("Total Actual") + ":Float:80", - _("Total Variance") + ":Float:80"] + return columns + [_("Total Budget") + ":Float:150", _("Total Actual") + ":Float:150", + _("Total Variance") + ":Float:150"] else: return columns - + def get_cost_centers(filters): cond = "and 1=1" if filters.get("budget_against") == "Cost Center": cond = "order by lft" - return frappe.db.sql_list("""select name from `tab{tab}` where company=%s + return frappe.db.sql_list("""select name from `tab{tab}` where company=%s {cond}""".format(tab=filters.get("budget_against"), cond=cond), filters.get("company")) #Get cost center & target details @@ -109,7 +109,7 @@ def get_cost_center_target_details(filters): """.format(budget_against=filters.get("budget_against").replace(" ", "_").lower(), cond=cond), (filters.from_fiscal_year,filters.to_fiscal_year,filters.budget_against, filters.company), as_dict=True) - + #Get target distribution details of accounts of cost center def get_target_distribution_details(filters): @@ -118,7 +118,7 @@ def get_target_distribution_details(filters): from `tabMonthly Distribution Percentage` mdp, `tabMonthly Distribution` md where mdp.parent=md.name and md.fiscal_year between %s and %s order by md.fiscal_year""",(filters.from_fiscal_year, filters.to_fiscal_year), as_dict=1): target_details.setdefault(d.name, {}).setdefault(d.month, flt(d.percentage_allocation)) - + return target_details #Get actual details from gl entry @@ -129,7 +129,7 @@ def get_actual_details(name, filters): if filters.get("budget_against") == "Cost Center": cc_lft, cc_rgt = frappe.db.get_value("Cost Center", name, ["lft", "rgt"]) cond = "lft>='{lft}' and rgt<='{rgt}'".format(lft = cc_lft, rgt=cc_rgt) - + ac_details = frappe.db.sql("""select gl.account, gl.debit, gl.credit,gl.fiscal_year, MONTHNAME(gl.posting_date) as month_name, b.{budget_against} as budget_against from `tabGL Entry` gl, `tabBudget Account` ba, `tabBudget` b @@ -159,7 +159,7 @@ def get_cost_center_account_month_map(filters): for ccd in cost_center_target_details: actual_details = get_actual_details(ccd.budget_against, filters) - + for month_id in range(1, 13): month = datetime.date(2013, month_id, 1).strftime('%B') cam_map.setdefault(ccd.budget_against, {}).setdefault(ccd.account, {}).setdefault(ccd.fiscal_year,{})\ @@ -172,7 +172,7 @@ def get_cost_center_account_month_map(filters): if ccd.monthly_distribution else 100.0/12 tav_dict.target = flt(ccd.budget_amount) * month_percentage / 100 - + for ad in actual_details.get(ccd.account, []): if ad.month_name == month: tav_dict.actual += flt(ad.debit) - flt(ad.credit) From dc24fe60be702ad2e0b95ef6867a871179e0a0fe Mon Sep 17 00:00:00 2001 From: Khadija Tul Kubra Zaki Date: Fri, 14 Jun 2019 11:29:45 +0500 Subject: [PATCH 025/115] fix: leave without pay spelling in salary register (#17938) * leave without pay spelling in salary register * fixed typo --- erpnext/hr/report/salary_register/salary_register.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/hr/report/salary_register/salary_register.py b/erpnext/hr/report/salary_register/salary_register.py index 3326ac7a6c8..9c45a628a3f 100644 --- a/erpnext/hr/report/salary_register/salary_register.py +++ b/erpnext/hr/report/salary_register/salary_register.py @@ -19,12 +19,12 @@ def execute(filters=None): data = [] for ss in salary_slips: row = [ss.name, ss.employee, ss.employee_name, ss.branch, ss.department, ss.designation, - ss.company, ss.start_date, ss.end_date, ss.leave_withut_pay, ss.payment_days] + ss.company, ss.start_date, ss.end_date, ss.leave_without_pay, ss.payment_days] if not ss.branch == None:columns[3] = columns[3].replace('-1','120') if not ss.department == None: columns[4] = columns[4].replace('-1','120') if not ss.designation == None: columns[5] = columns[5].replace('-1','120') - if not ss.leave_withut_pay == None: columns[9] = columns[9].replace('-1','130') + if not ss.leave_without_pay == None: columns[9] = columns[9].replace('-1','130') for e in earning_types: @@ -117,4 +117,4 @@ def get_ss_ded_map(salary_slips): ss_ded_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, []) ss_ded_map[d.parent][d.salary_component] = flt(d.amount) - return ss_ded_map \ No newline at end of file + return ss_ded_map From 740c9546790ccc9f2ad5b2fb71aaed4b904d3ee3 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 17 Jun 2019 07:40:21 +0530 Subject: [PATCH 026/115] fix: revert group by voucher general ledger changes --- erpnext/accounts/report/general_ledger/general_ledger.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 4bea0978025..ccb427665b2 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -127,8 +127,7 @@ def get_gl_entries(filters): 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, against_voucher_type, against_voucher, posting_date""" + 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, From 6b5c365cb6640dd67899e2afa6cb66bf67325785 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 17 Jun 2019 13:32:36 +0530 Subject: [PATCH 027/115] fix: not able to save asset if depreciation method is manual --- erpnext/assets/doctype/asset/asset.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 72f5c627a71..45f7b30ae8a 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -291,16 +291,19 @@ class Asset(AccountsController): def validate_expected_value_after_useful_life(self): for row in self.get('finance_books'): - accumulated_depreciation_after_full_schedule = max([d.accumulated_depreciation_amount - for d in self.get("schedules") if cint(d.finance_book_id) == row.idx]) + accumulated_depreciation_after_full_schedule = [d.accumulated_depreciation_amount + for d in self.get("schedules") if cint(d.finance_book_id) == row.idx] - asset_value_after_full_schedule = flt(flt(self.gross_purchase_amount) - - flt(accumulated_depreciation_after_full_schedule), - self.precision('gross_purchase_amount')) + if accumulated_depreciation_after_full_schedule: + accumulated_depreciation_after_full_schedule = max(accumulated_depreciation_after_full_schedule) - if 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)) + asset_value_after_full_schedule = flt(flt(self.gross_purchase_amount) - + flt(accumulated_depreciation_after_full_schedule), + self.precision('gross_purchase_amount')) + + if 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)) def validate_cancellation(self): if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"): From 7987b1a6817c7db41c0f6087a3ed81d89f7ae37b Mon Sep 17 00:00:00 2001 From: Rohan Bansal Date: Mon, 15 Apr 2019 15:34:38 +0530 Subject: [PATCH 028/115] fix(delivery): Add more context for dispatch notification email + formatting fixes --- .../doctype/delivery_trip/delivery_trip.py | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py index 01b4734bf58..bc8c7493d5c 100644 --- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py +++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py @@ -20,8 +20,7 @@ class DeliveryTrip(Document): # Google Maps returns distances in meters by default self.default_distance_uom = frappe.db.get_single_value("Global Defaults", "default_distance_unit") or "Meter" self.uom_conversion_factor = frappe.db.get_value("UOM Conversion Factor", - {"from_uom": "Meter", "to_uom": self.default_distance_uom}, - "value") + {"from_uom": "Meter", "to_uom": self.default_distance_uom}, "value") def validate(self): self.validate_stop_addresses() @@ -139,7 +138,7 @@ class DeliveryTrip(Document): # Include last leg in the final distance calculation self.uom = self.default_distance_uom total_distance = sum([leg.get("distance", {}).get("value", 0.0) - for leg in directions.get("legs")]) # in meters + for leg in directions.get("legs")]) # in meters self.total_distance = total_distance * self.uom_conversion_factor else: idx += len(route) - 1 @@ -358,8 +357,12 @@ def notify_customers(delivery_trip): email_recipients = [] for stop in delivery_trip.delivery_stops: - contact_info = frappe.db.get_value("Contact", stop.contact, - ["first_name", "last_name", "email_id", "gender"], as_dict=1) + contact_info = frappe.db.get_value("Contact", stop.contact, ["first_name", "last_name", "email_id"], as_dict=1) + + context.update({"items": []}) + if stop.delivery_note: + items = frappe.get_all("Delivery Note Item", filters={"parent": stop.delivery_note, "docstatus": 1}, fields=["*"]) + context.update({"items": items}) if contact_info and contact_info.email_id: context.update(stop.as_dict()) @@ -369,9 +372,9 @@ def notify_customers(delivery_trip): dispatch_template = frappe.get_doc("Email Template", dispatch_template_name) frappe.sendmail(recipients=contact_info.email_id, - subject=dispatch_template.subject, - message=frappe.render_template(dispatch_template.response, context), - attachments=get_attachments(stop)) + subject=dispatch_template.subject, + message=frappe.render_template(dispatch_template.response, context), + attachments=get_attachments(stop)) stop.db_set("email_sent_to", contact_info.email_id) email_recipients.append(contact_info.email_id) @@ -388,9 +391,7 @@ def get_attachments(delivery_stop): return [] dispatch_attachment = frappe.db.get_single_value("Delivery Settings", "dispatch_attachment") - attachments = frappe.attach_print("Delivery Note", - delivery_stop.delivery_note, - file_name="Delivery Note", - print_format=dispatch_attachment) + attachments = frappe.attach_print("Delivery Note", delivery_stop.delivery_note, + file_name="Delivery Note", print_format=dispatch_attachment) return [attachments] From 8fb018de47e553ffc29cc9f4602fa852f36c4d2d Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 17 Jun 2019 16:19:23 +0530 Subject: [PATCH 029/115] fix: allow edit is enabled in the pos profile still user not able to edit the rates --- .../page/point_of_sale/point_of_sale.js | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) 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 3e6ee86df00..a16a77f1340 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.js +++ b/erpnext/selling/page/point_of_sale/point_of_sale.js @@ -737,6 +737,17 @@ class POSCart { const customer = this.frm.doc.customer; this.customer_field.set_value(customer); + + if (this.numpad) { + const disable_btns = this.disable_numpad_control() + const enable_btns = [__('Rate'), __('Disc')] + + if (disable_btns) { + enable_btns.filter(btn => !disable_btns.includes(btn)) + } + + this.numpad.enable_buttons(enable_btns); + } } get_grand_total() { @@ -1507,6 +1518,16 @@ class NumberPad { } } + enable_buttons(btns) { + btns.forEach((btn) => { + const $btn = this.get_btn(btn); + $btn.prop("disabled", false) + $btn.hover(() => { + $btn.css('cursor','pointer'); + }) + }) + } + set_class() { for (const btn in this.add_class) { const class_name = this.add_class[btn]; From 2493d5e0d3a3ef405ceadbfa03c798396c1551f0 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 17 Jun 2019 14:57:05 +0530 Subject: [PATCH 030/115] fix: bank guarantee, not able to select the purchase order --- erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js index 2a44cb3b52f..0acbe2009f5 100644 --- a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js +++ b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js @@ -43,8 +43,13 @@ frappe.ui.form.on('Bank Guarantee', { reference_docname: function(frm) { if (frm.doc.reference_docname && frm.doc.reference_doctype) { - let fields_to_fetch = ["project", "grand_total"]; + let fields_to_fetch = ["grand_total"]; let party_field = frm.doc.reference_doctype == "Sales Order" ? "customer" : "supplier"; + + if (frm.doc.reference_doctype == "Sales Order") { + fields_to_fetch.push("project"); + } + fields_to_fetch.push(party_field); frappe.call({ method: "erpnext.accounts.doctype.bank_guarantee.bank_guarantee.get_vouchar_detials", From acbdeb833f79b24e3e89f1ea4710c94c4227bf59 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 17 Jun 2019 18:05:41 +0530 Subject: [PATCH 031/115] fix(employee-benefit-application): remove query from setup --- .../employee_benefit_application.js | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js index e71ce1276b5..c55c46db993 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js @@ -2,20 +2,8 @@ // For license information, please see license.txt frappe.ui.form.on('Employee Benefit Application', { - setup: function(frm) { - if(!frm.doc.employee || !frm.doc.date) { - frappe.throw(__("Please select Employee and Date first")); - } else { - frm.set_query("earning_component", "employee_benefits", function() { - return { - query : "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_earning_components", - filters: {date: frm.doc.date, employee: frm.doc.employee} - }; - }); - } - }, - employee: function(frm) { + frm.trigger('set_earning_component'); var method, args; if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){ method = "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits_remaining"; @@ -35,6 +23,21 @@ frappe.ui.form.on('Employee Benefit Application', { get_max_benefits(frm, method, args); } }, + + date: function(frm) { + frm.trigger('set_earning_component'); + }, + + set_earning_component: function(frm) { + if(!frm.doc.employee && !frm.doc.date) return; + frm.set_query("earning_component", "employee_benefits", function() { + return { + query : "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_earning_components", + filters: {date: frm.doc.date, employee: frm.doc.employee} + } + }); + }, + payroll_period: function(frm) { var method, args; if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){ From 77ed46242f0953eb33dcc18bb056882171e97a4a Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 17 Jun 2019 19:03:46 +0530 Subject: [PATCH 032/115] fix: change formatting --- .../employee_benefit_application.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js index c55c46db993..b73dcf8ac36 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js @@ -34,7 +34,7 @@ frappe.ui.form.on('Employee Benefit Application', { return { query : "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_earning_components", filters: {date: frm.doc.date, employee: frm.doc.employee} - } + }; }); }, From 0c7afb389d2db9bf18461439431e0a3cf2c8745d Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Mon, 17 Jun 2019 20:48:11 +0530 Subject: [PATCH 033/115] fix: Company Filter in Total Stock Summary Report (#17973) --- .../total_stock_summary.js | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/report/total_stock_summary/total_stock_summary.js b/erpnext/stock/report/total_stock_summary/total_stock_summary.js index b7461c485f6..264642856da 100644 --- a/erpnext/stock/report/total_stock_summary/total_stock_summary.js +++ b/erpnext/stock/report/total_stock_summary/total_stock_summary.js @@ -10,8 +10,23 @@ frappe.query_reports["Total Stock Summary"] = { "fieldtype": "Select", "width": "80", "reqd": 1, - "options": ["","Warehouse", "Company"], - "default": "Warehouse" + "options": ["", "Warehouse", "Company"], + "change": function() { + let group_by = frappe.query_report.get_filter_value("group_by") + let company_filter = frappe.query_report.get_filter("company") + if (group_by == "Company") { + company_filter.df.reqd = 0; + company_filter.df.hidden = 1; + frappe.query_report.set_filter_value("company", ""); + company_filter.refresh(); + } + else { + company_filter.df.reqd = 1; + company_filter.df.hidden = 0; + company_filter.refresh(); + frappe.query_report.refresh(); + } + } }, { "fieldname": "company", @@ -23,4 +38,4 @@ frappe.query_reports["Total Stock Summary"] = { "reqd": 1 }, ] -} +} \ No newline at end of file From e5647f744185afd4ed0308e2a8e1d6a19c54e1b7 Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Tue, 18 Jun 2019 15:01:56 +0550 Subject: [PATCH 034/115] bumped to version 11.1.39 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 0fdf7031ab3..a06efa0ff75 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.38' +__version__ = '11.1.39' def get_default_company(user=None): '''Get default company for user''' From 8ef80fb6695d1102dbb0777f3cb5c3b3b5254ecf Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 18 Jun 2019 16:09:17 +0530 Subject: [PATCH 035/115] fix: could not find company all --- .../employee_attendance_tool.js | 5 ++--- .../employee_attendance_tool.py | 11 +++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js index 376d0c0a5a5..22ba5ad473e 100644 --- a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js +++ b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js @@ -2,9 +2,8 @@ frappe.ui.form.on("Employee Attendance Tool", { refresh: function(frm) { frm.disable_save(); }, - + onload: function(frm) { - frm.doc.department = frm.doc.branch = frm.doc.company = "All"; frm.set_value("date", frappe.datetime.get_today()); erpnext.employee_attendance_tool.load_employees(frm); }, @@ -24,7 +23,7 @@ frappe.ui.form.on("Employee Attendance Tool", { company: function(frm) { erpnext.employee_attendance_tool.load_employees(frm); } - + }); diff --git a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.py b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.py index ea5f4bdecab..32fcee1abe4 100644 --- a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.py +++ b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.py @@ -17,12 +17,11 @@ def get_employees(date, department = None, branch = None, company = None): attendance_not_marked = [] attendance_marked = [] filters = {"status": "Active", "date_of_joining": ["<=", date]} - if department != "All": - filters["department"] = department - if branch != "All": - filters["branch"] = branch - if company != "All": - filters["company"] = company + + for field, value in {'department': department, + 'branch': branch, 'company': company}.items(): + if value: + filters[field] = value employee_list = frappe.get_list("Employee", fields=["employee", "employee_name"], filters=filters, order_by="employee_name") marked_employee = {} From 072948e827f9a63de753a7178edd5c2f761e2be3 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 18 Jun 2019 18:34:14 +0530 Subject: [PATCH 036/115] fix: finance book filters includes the gl data which don't have finance book --- .../report/balance_sheet/balance_sheet.js | 6 +++ .../accounts/report/cash_flow/cash_flow.js | 6 +++ .../accounts/report/cash_flow/cash_flow.py | 46 ++++++++++++------- .../consolidated_financial_statement.js | 5 ++ .../consolidated_financial_statement.py | 8 +++- .../accounts/report/financial_statements.py | 8 +++- .../report/general_ledger/general_ledger.js | 5 ++ .../report/general_ledger/general_ledger.py | 9 +++- .../profit_and_loss_statement.js | 5 ++ .../report/trial_balance/trial_balance.py | 2 +- 10 files changed, 77 insertions(+), 23 deletions(-) diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.js b/erpnext/accounts/report/balance_sheet/balance_sheet.js index f22f3a10091..4bc29da2c7d 100644 --- a/erpnext/accounts/report/balance_sheet/balance_sheet.js +++ b/erpnext/accounts/report/balance_sheet/balance_sheet.js @@ -10,4 +10,10 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "fieldtype": "Check", "default": 1 }); + + frappe.query_reports["Balance Sheet"]["filters"].push({ + "fieldname": "include_default_book_entries", + "label": __("Include Default Book Entries"), + "fieldtype": "Check" + }); }); diff --git a/erpnext/accounts/report/cash_flow/cash_flow.js b/erpnext/accounts/report/cash_flow/cash_flow.js index 391f57beac6..04221110930 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.js +++ b/erpnext/accounts/report/cash_flow/cash_flow.js @@ -15,4 +15,10 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "label": __("Accumulated Values"), "fieldtype": "Check" }); + + frappe.query_reports["Cash Flow"]["filters"].push({ + "fieldname": "include_default_book_entries", + "label": __("Include Default Book Entries"), + "fieldtype": "Check" + }); }); \ No newline at end of file diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py index f048c1acda5..0f9813947a7 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.py +++ b/erpnext/accounts/report/cash_flow/cash_flow.py @@ -14,8 +14,8 @@ def execute(filters=None): if cint(frappe.db.get_single_value('Accounts Settings', 'use_custom_cash_flow')): from erpnext.accounts.report.cash_flow.custom_cash_flow import execute as execute_custom return execute_custom(filters=filters) - - period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year, + + period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year, filters.periodicity, filters.accumulated_values, filters.company) cash_flow_accounts = get_cash_flow_accounts() @@ -25,18 +25,18 @@ def execute(filters=None): accumulated_values=filters.accumulated_values, ignore_closing_entries=True, ignore_accumulated_values_for_fy= True) expense = get_data(filters.company, "Expense", "Debit", period_list, filters=filters, accumulated_values=filters.accumulated_values, ignore_closing_entries=True, ignore_accumulated_values_for_fy= True) - + net_profit_loss = get_net_profit_loss(income, expense, period_list, filters.company) data = [] company_currency = frappe.get_cached_value('Company', filters.company, "default_currency") - + for cash_flow_account in cash_flow_accounts: section_data = [] data.append({ - "account_name": cash_flow_account['section_header'], + "account_name": cash_flow_account['section_header'], "parent_account": None, - "indent": 0.0, + "indent": 0.0, "account": cash_flow_account['section_header'] }) @@ -44,18 +44,18 @@ def execute(filters=None): # add first net income in operations section if net_profit_loss: net_profit_loss.update({ - "indent": 1, + "indent": 1, "parent_account": cash_flow_accounts[0]['section_header'] }) data.append(net_profit_loss) section_data.append(net_profit_loss) for account in cash_flow_account['account_types']: - account_data = get_account_type_based_data(filters.company, - account['account_type'], period_list, filters.accumulated_values) + account_data = get_account_type_based_data(filters.company, + account['account_type'], period_list, filters.accumulated_values, filters) account_data.update({ "account_name": account['label'], - "account": account['label'], + "account": account['label'], "indent": 1, "parent_account": cash_flow_account['section_header'], "currency": company_currency @@ -63,7 +63,7 @@ def execute(filters=None): data.append(account_data) section_data.append(account_data) - add_total_row_account(data, section_data, cash_flow_account['section_footer'], + add_total_row_account(data, section_data, cash_flow_account['section_footer'], period_list, company_currency) add_total_row_account(data, data, _("Net Change in Cash"), period_list, company_currency) @@ -105,13 +105,15 @@ def get_cash_flow_accounts(): # combine all cash flow accounts for iteration return [operation_accounts, investing_accounts, financing_accounts] -def get_account_type_based_data(company, account_type, period_list, accumulated_values): +def get_account_type_based_data(company, account_type, period_list, accumulated_values, filters): data = {} total = 0 for period in period_list: start_date = get_start_date(period, accumulated_values, company) - amount = get_account_type_based_gl_data(company, start_date, period['to_date'], account_type) + amount = get_account_type_based_gl_data(company, start_date, + period['to_date'], account_type, filters) + if amount and account_type == "Depreciation": amount *= -1 @@ -121,14 +123,24 @@ def get_account_type_based_data(company, account_type, period_list, accumulated_ data["total"] = total return data -def get_account_type_based_gl_data(company, start_date, end_date, account_type): +def get_account_type_based_gl_data(company, start_date, end_date, account_type, filters): + cond = "" + + if filters.finance_book: + cond = " and finance_book = '%s'" %(frappe.db.escape(filters.finance_book)) + if filters.include_default_book_entries: + company_fb = frappe.db.get_value("Company", company, 'default_finance_book') + + cond = """ and finance_book in ('%s', '%s') + """ %(frappe.db.escape(filters.finance_book), frappe.db.escape(company_fb)) + gl_sum = frappe.db.sql_list(""" select sum(credit) - sum(debit) from `tabGL Entry` where company=%s and posting_date >= %s and posting_date <= %s and voucher_type != 'Period Closing Voucher' - and account in ( SELECT name FROM tabAccount WHERE account_type = %s) - """, (company, start_date, end_date, account_type)) + and account in ( SELECT name FROM tabAccount WHERE account_type = %s) {cond} + """.format(cond=cond), (company, start_date, end_date, account_type)) return gl_sum[0] if gl_sum and gl_sum[0] else 0 @@ -154,7 +166,7 @@ def add_total_row_account(out, data, label, period_list, currency, consolidated key = period if consolidated else period['key'] total_row.setdefault(key, 0.0) total_row[key] += row.get(key, 0.0) - + total_row.setdefault("total", 0.0) total_row["total"] += row["total"] diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js index 7b373f0d9ae..e69a993e8ce 100644 --- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js +++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js @@ -55,5 +55,10 @@ frappe.query_reports["Consolidated Financial Statement"] = { "fieldtype": "Check", "default": 0 }, + { + "fieldname": "include_default_book_entries", + "label": __("Include Default Book Entries"), + "fieldtype": "Check" + } ] } diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py index 1bb8580f644..ed000bbac4c 100644 --- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py +++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py @@ -355,7 +355,8 @@ def set_gl_entries_by_account(from_date, to_date, root_lft, root_rgt, filters, g "lft": root_lft, "rgt": root_rgt, "company": d.name, - "finance_book": filters.get("finance_book") + "finance_book": filters.get("finance_book"), + "company_fb": frappe.db.get_value("Company", d.name, 'default_finance_book') }, as_dict=True) @@ -386,7 +387,10 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters): additional_conditions.append("gl.posting_date >= %(from_date)s") if filters.get("finance_book"): - additional_conditions.append("ifnull(finance_book, '') in (%(finance_book)s, '')") + if filters.get("include_default_book_entries"): + additional_conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)") + else: + additional_conditions.append("finance_book in (%(finance_book)s)") return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else "" diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index fe030c5f1ce..9765310fc9b 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -359,7 +359,8 @@ def set_gl_entries_by_account( "to_date": to_date, "cost_center": filters.cost_center, "project": filters.project, - "finance_book": filters.get("finance_book") + "finance_book": filters.get("finance_book"), + "company_fb": frappe.db.get_value("Company", company, 'default_finance_book') }, as_dict=True) @@ -393,7 +394,10 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters): additional_conditions.append("cost_center in %(cost_center)s") if filters.get("finance_book"): - additional_conditions.append("ifnull(finance_book, '') in (%(finance_book)s, '')") + if filters.get("include_default_book_entries"): + additional_conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)") + else: + additional_conditions.append("finance_book in (%(finance_book)s)") return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else "" diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index e74c16af6fe..e162606b7ac 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -216,6 +216,11 @@ frappe.query_reports["General Ledger"] = { "fieldname": "show_opening_entries", "label": __("Show Opening Entries"), "fieldtype": "Check" + }, + { + "fieldname": "include_default_book_entries", + "label": __("Include Default Book Entries"), + "fieldtype": "Check" } ] } diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index ccb427665b2..ae63ab60329 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -133,6 +133,10 @@ def get_gl_entries(filters): 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') + gl_entries = frappe.db.sql( """ select @@ -188,7 +192,10 @@ def get_conditions(filters): conditions.append("project in %(project)s") if filters.get("finance_book"): - conditions.append("ifnull(finance_book, '') in (%(finance_book)s, '')") + if filters.get("include_default_book_entries"): + conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)") + else: + conditions.append("finance_book in (%(finance_book)s)") from frappe.desk.reportview import build_match_conditions match_conditions = build_match_conditions("GL Entry") diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js index 250e516d7d2..7741a45feeb 100644 --- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js +++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js @@ -41,6 +41,11 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "fieldname": "accumulated_values", "label": __("Accumulated Values"), "fieldtype": "Check" + }, + { + "fieldname": "include_default_book_entries", + "label": __("Include Default Book Entries"), + "fieldtype": "Check" } ); }); diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index b5f0186d4d2..5758b0bc6b1 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -105,7 +105,7 @@ def get_rootwise_opening_balances(filters, report_type): if filters.finance_book: fb_conditions = " and finance_book = %(finance_book)s" if filters.include_default_book_entries: - fb_conditions = " and (finance_book in (%(finance_book)s, %(company_fb)s) or finance_book is null)" + fb_conditions = " and (finance_book in (%(finance_book)s, %(company_fb)s))" additional_conditions += fb_conditions From e5c7f3e542774c63a92f3c5da98afb3dbf448209 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Wed, 19 Jun 2019 18:25:38 +0530 Subject: [PATCH 037/115] fix: From date and to date filters in HSN wise summary of out ward supplies --- .../hsn_wise_summary_of_outward_supplies.js | 15 ++++++++++++++- .../hsn_wise_summary_of_outward_supplies.py | 4 +++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js index dcb81cb087e..dfdf9dc0958 100644 --- a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js +++ b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js @@ -29,7 +29,20 @@ frappe.query_reports["HSN-wise-summary of outward supplies"] = { "placeholder":"Company GSTIN", "options": [""], "width": "80" - } + }, + { + "fieldname":"from_date", + "label": __("From Date"), + "fieldtype": "Date", + "width": "80" + }, + { + "fieldname":"to_date", + "label": __("To Date"), + "fieldtype": "Date", + "width": "80" + }, + ], onload: (report) => { fetch_gstins(report); diff --git a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py index e938e29c440..222dfa1eb78 100644 --- a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py +++ b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py @@ -88,7 +88,9 @@ def get_conditions(filters): for opts in (("company", " and company=%(company)s"), ("gst_hsn_code", " and gst_hsn_code=%(gst_hsn_code)s"), - ("company_gstin", " and company_gstin=%(company_gstin)s")): + ("company_gstin", " and company_gstin=%(company_gstin)s"), + ("from_date", " and posting_date >= %(from_date)s"), + ("to_date", "and posting_date <= %(to_date)s")): if filters.get(opts[0]): conditions += opts[1] From ac57edf7d3595e3c86b0204632419a32369c8106 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Thu, 20 Jun 2019 19:12:16 +0530 Subject: [PATCH 038/115] fix: Default cost center fix for delivery note item (#17988) --- erpnext/selling/doctype/sales_order/sales_order.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 184c6bd70d6..a490082c42c 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -574,8 +574,8 @@ def make_delivery_note(source_name, target_doc=None): if item: target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center") \ - or item.get("selling_cost_center") \ - or item_group.get("selling_cost_center") + or item.get("buying_cost_center") \ + or item_group.get("buying_cost_center") target_doc = get_mapped_doc("Sales Order", source_name, { "Sales Order": { From 523d89a2d9ad7c58a4a38e46c8c839c014783a22 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 19 Jun 2019 12:52:07 +0530 Subject: [PATCH 039/115] fix: as limit 100 was set in the query therefore not all item's default value moved to the Item Default table --- erpnext/patches.txt | 2 +- ...efaults_to_child_table_for_multicompany.py | 84 +++++++++++++------ 2 files changed, 58 insertions(+), 28 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index b6083ef44c0..ae06b5dba35 100755 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -533,7 +533,7 @@ erpnext.patches.v11_0.create_department_records_for_each_company erpnext.patches.v11_0.make_location_from_warehouse erpnext.patches.v11_0.make_asset_finance_book_against_old_entries erpnext.patches.v11_0.check_buying_selling_in_currency_exchange -erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany #02-07-2018 +erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany #02-07-2018 #19-06-2019 erpnext.patches.v11_0.refactor_erpnext_shopify #2018-09-07 erpnext.patches.v11_0.rename_overproduction_percent_field erpnext.patches.v11_0.update_backflush_subcontract_rm_based_on_bom diff --git a/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py b/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py index 01f84a03136..c7c76355400 100644 --- a/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py +++ b/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py @@ -17,10 +17,8 @@ def execute(): frappe.reload_doc('stock', 'doctype', 'item_default') frappe.reload_doc('stock', 'doctype', 'item') - if frappe.db.a_row_exists('Item Default'): return - companies = frappe.get_all("Company") - if len(companies) == 1: + if len(companies) == 1 and not frappe.get_all("Item Default", limit=1): try: frappe.db.sql(''' INSERT INTO `tabItem Default` @@ -35,32 +33,64 @@ def execute(): except: pass else: - item_details = frappe.get_all("Item", fields=["name", "default_warehouse", "buying_cost_center", - "expense_account", "selling_cost_center", "income_account"], limit=100) + item_details = frappe.db.sql(""" SELECT name, default_warehouse, + buying_cost_center, expense_account, selling_cost_center, income_account + FROM tabItem + WHERE + name not in (select distinct parent from `tabItem Default`) and ifnull(disabled, 0) = 0""" + , as_dict=1) - for item in item_details: - item_defaults = [] + items_default_data = {} + for item_data in item_details: + for d in [["default_warehouse", "Warehouse"], ["expense_account", "Account"], + ["income_account", "Account"], ["buying_cost_center", "Cost Center"], + ["selling_cost_center", "Cost Center"]]: + if item_data.get(d[0]): + company = frappe.get_value(d[1], item_data.get(d[0]), "company", cache=True) - def insert_into_item_defaults(doc_field_name, doc_field_value, company): - for d in item_defaults: - if d.get("company") == company: - d[doc_field_name] = doc_field_value - return - item_defaults.append({ - "company": company, - doc_field_name: doc_field_value - }) + if item_data.name not in items_default_data: + items_default_data[item_data.name] = {} - for d in [ - ["default_warehouse", "Warehouse"], ["expense_account", "Account"], ["income_account", "Account"], - ["buying_cost_center", "Cost Center"], ["selling_cost_center", "Cost Center"] - ]: - if item.get(d[0]): - company = frappe.get_value(d[1], item.get(d[0]), "company", cache=True) - insert_into_item_defaults(d[0], item.get(d[0]), company) + company_wise_data = items_default_data[item_data.name] - doc = frappe.get_doc("Item", item.name) - doc.extend("item_defaults", item_defaults) + if company not in company_wise_data: + company_wise_data[company] = {} - for child_doc in doc.item_defaults: - child_doc.db_insert() \ No newline at end of file + default_data = company_wise_data[company] + default_data[d[0]] = item_data.get(d[0]) + + to_insert_data = [] + + # items_default_data data structure will be as follow + # { + # 'item_code 1': {'company 1': {'default_warehouse': 'Test Warehouse 1'}}, + # 'item_code 2': { + # 'company 1': {'default_warehouse': 'Test Warehouse 1'}, + # 'company 2': {'default_warehouse': 'Test Warehouse 1'} + # } + # } + + for item_code, companywise_item_data in items_default_data.items(): + for company, item_default_data in companywise_item_data.items(): + to_insert_data.append(( + frappe.generate_hash("", 10), + item_code, + 'Item', + 'item_defaults', + company, + item_default_data.get('default_warehouse'), + item_default_data.get('expense_account'), + item_default_data.get('income_account'), + item_default_data.get('buying_cost_center'), + item_default_data.get('selling_cost_center'), + )) + + if to_insert_data: + frappe.db.sql(''' + INSERT INTO `tabItem Default` + ( + `name`, `parent`, `parenttype`, `parentfield`, `company`, `default_warehouse`, + `expense_account`, `income_account`, `buying_cost_center`, `selling_cost_center` + ) + VALUES {} + '''.format(', '.join(['%s'] * len(to_insert_data))), tuple(to_insert_data)) \ No newline at end of file From 8f1f6a89f1211227cbb2e97468c5d07cef64c90c Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 1 May 2019 11:16:25 +0530 Subject: [PATCH 040/115] feat(travis): Python 3.6 tests --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 869fe959c00..f2ba2c43261 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ dist: trusty python: - "2.7" + - "3.6" services: - mysql From 508b3ab8deea1d1994abbc668d41081a44f37a32 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 1 May 2019 11:31:08 +0530 Subject: [PATCH 041/115] fix(travis): Refactor .travis.yml --- .travis.yml | 24 +++++++++--------------- travis/run-tests.sh | 12 ++++++++++++ 2 files changed, 21 insertions(+), 15 deletions(-) create mode 100644 travis/run-tests.sh diff --git a/.travis.yml b/.travis.yml index f2ba2c43261..26a4caa0fbe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,10 @@ python: - "2.7" - "3.6" +env: + - TEST_TYPE=Server Side Test + - TEST_TYPE=Patch Test + services: - mysql @@ -40,18 +44,8 @@ before_script: - bench start & - sleep 10 -jobs: - include: - - stage: test - script: - - set -e - - bench run-tests --app erpnext --coverage - after_script: - - coveralls -b apps/erpnext -d ../../sites/.coverage - env: Server Side Test - - # stage - 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 migrate - env: Patch Testing +script: + - $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 new file mode 100644 index 00000000000..7cfd64833b7 --- /dev/null +++ b/travis/run-tests.sh @@ -0,0 +1,12 @@ +#!/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 8738f2e1c970f1d931a1878eddf635e6e0e1c340 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 1 May 2019 17:41:36 +0530 Subject: [PATCH 042/115] fix: Set file permissions 755 on travis/run-tests.sh --- travis/run-tests.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 travis/run-tests.sh diff --git a/travis/run-tests.sh b/travis/run-tests.sh old mode 100644 new mode 100755 From 4e94e26ef8c2cf32cdce0fec552dc67cf09a518e Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 1 May 2019 18:08:44 +0530 Subject: [PATCH 043/115] fix: Minor --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 26a4caa0fbe..ae4bc02fe63 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,8 @@ python: - "3.6" env: - - TEST_TYPE=Server Side Test - - TEST_TYPE=Patch Test + - TEST_TYPE="Server Side Test" + - TEST_TYPE="Patch Test" services: - mysql From 13d01dd69070849d48d4067dcf0e8ca6644b788a Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 1 May 2019 18:25:53 +0530 Subject: [PATCH 044/115] fix: Run script with bash --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ae4bc02fe63..a8a0d826145 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,7 @@ before_script: - sleep 10 script: - - $TRAVIS_BUILD_DIR/travis/run-tests.sh + - bash $TRAVIS_BUILD_DIR/travis/run-tests.sh after_script: - coveralls -b apps/erpnext -d ../../sites/.coverage From c5e959fe9c363456a556c4500cae79f67c490685 Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Fri, 21 Jun 2019 11:42:58 +0530 Subject: [PATCH 045/115] fix(BOM): set default value of include_exploded_item to 0 --- .../doctype/purchase_order_item/purchase_order_item.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json index 3d981c56da7..350a1894467 100755 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -1915,7 +1915,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "default": "1", + "default": "0", "depends_on": "eval:parent.is_subcontracted == 'Yes'", "fieldname": "include_exploded_items", "fieldtype": "Check", @@ -2359,4 +2359,4 @@ "track_changes": 1, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} From 12cb0ea6339cfeb2c996de35796fd08439a4b890 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Tue, 18 Jun 2019 21:50:05 +0530 Subject: [PATCH 046/115] fix(tests): Timesheet tests --- erpnext/projects/doctype/timesheet/test_timesheet.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py index f1179033bed..32f0428fcd8 100644 --- a/erpnext/projects/doctype/timesheet/test_timesheet.py +++ b/erpnext/projects/doctype/timesheet/test_timesheet.py @@ -103,8 +103,8 @@ class TestTimesheet(unittest.TestCase): { "billable": 1, "activity_type": "_Test Activity Type", - "from_type": now_datetime(), - "hours": 3, + "from_time": now_datetime(), + "to_time": now_datetime() + datetime.timedelta(hours=3), "company": "_Test Company" } ) @@ -113,8 +113,8 @@ class TestTimesheet(unittest.TestCase): { "billable": 1, "activity_type": "_Test Activity Type", - "from_type": now_datetime(), - "hours": 3, + "from_time": now_datetime(), + "to_time": now_datetime() + datetime.timedelta(hours=3), "company": "_Test Company" } ) From 3d59ab5c55a369a45dba88c5e12d98e17b280a04 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Tue, 18 Jun 2019 23:01:20 +0530 Subject: [PATCH 047/115] fix(tests): Do not test order of features in Location --- erpnext/assets/doctype/location/test_location.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/assets/doctype/location/test_location.py b/erpnext/assets/doctype/location/test_location.py index 22d25b5e11c..c98b0b0936c 100644 --- a/erpnext/assets/doctype/location/test_location.py +++ b/erpnext/assets/doctype/location/test_location.py @@ -25,9 +25,12 @@ class TestLocation(unittest.TestCase): temp['features'][0]['properties']['feature_of'] = location formatted_locations.extend(temp['features']) - formatted_location_string = str(formatted_locations) test_location = frappe.get_doc('Location', 'Test Location Area') test_location.save() - self.assertEqual(formatted_location_string, str(json.loads(test_location.get('location'))['features'])) + test_location_features = json.loads(test_location.get('location'))['features'] + ordered_test_location_features = sorted(test_location_features, key=lambda x: x['properties']['feature_of']) + ordered_formatted_locations = sorted(formatted_locations, key=lambda x: x['properties']['feature_of']) + + self.assertEqual(ordered_formatted_locations, ordered_test_location_features) self.assertEqual(area, test_location.get('area')) From d48d5c7cbd477a55f126d268cd65f36baf6a5833 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 21 Jun 2019 11:57:33 +0530 Subject: [PATCH 048/115] fix: Replace unicode with six.text_type --- .../doctype/production_order/production_order.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py index 2f2c40ef2d4..b5abb733b01 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -18,6 +18,7 @@ from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty from frappe.utils.csvutils import getlink from erpnext.stock.utils import get_bin, validate_warehouse_company, get_latest_stock_qty from erpnext.utilities.transaction_base import validate_uom_is_integer +from six import text_type class OverProductionError(frappe.ValidationError): pass class StockOverProductionError(frappe.ValidationError): pass @@ -591,10 +592,10 @@ def make_timesheet(production_order, company): @frappe.whitelist() def add_timesheet_detail(timesheet, args): - if isinstance(timesheet, unicode): + if isinstance(timesheet, text_type): timesheet = frappe.get_doc('Timesheet', timesheet) - if isinstance(args, unicode): + if isinstance(args, text_type): args = json.loads(args) timesheet.append('time_logs', args) From 14b5c96c58a674a1e5b985a2ff6fa57fdc9b10e5 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 7 Feb 2019 18:10:30 +0530 Subject: [PATCH 049/115] fix(py3): Use range instead of xrange --- .../tax_withholding_category/test_tax_withholding_category.py | 2 +- .../doctype/amazon_mws_settings/amazon_methods.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py index 25301967080..638e57ed2b9 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py @@ -22,7 +22,7 @@ class TestTaxWithholdingCategory(unittest.TestCase): invoices = [] # create invoices for lower than single threshold tax rate - for _ in xrange(2): + for _ in range(2): pi = create_purchase_invoice(supplier = "Test TDS Supplier") pi.submit() invoices.append(pi) diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py index 124910e35de..1c39d8818c4 100644 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py @@ -40,7 +40,7 @@ def get_products_details(): products_response = call_mws_method(products.get_matching_product,marketplaceid=marketplace, asins=asin_list) - matching_products_list = products_response.parsed + matching_products_list = products_response.parsed for product in matching_products_list: skus = [row["sku"] for row in sku_asin if row["asin"]==product.ASIN] for sku in skus: @@ -116,7 +116,7 @@ def call_mws_method(mws_method, *args, **kwargs): mws_settings = frappe.get_doc("Amazon MWS Settings") max_retries = mws_settings.max_retry_limit - for x in xrange(0, max_retries): + for x in range(0, max_retries): try: response = mws_method(*args, **kwargs) return response From fbab41668ddc2af4d93f4fcaf923233086fa6b18 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 21 Jun 2019 11:31:29 +0530 Subject: [PATCH 050/115] fix(py3): Undefined variable --- .../fichier_des_ecritures_comptables_[fec].py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py b/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py index e1b6c4db4f9..e903c9f00a4 100644 --- a/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py +++ b/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py @@ -69,13 +69,13 @@ def get_gl_entries(filters): gl_entries = frappe.db.sql(""" select - gl.posting_date as GlPostDate, gl.name as GlName, gl.account, gl.transaction_date, + gl.posting_date as GlPostDate, gl.name as GlName, gl.account, gl.transaction_date, sum(gl.debit) as debit, sum(gl.credit) as credit, sum(gl.debit_in_account_currency) as debitCurr, sum(gl.credit_in_account_currency) as creditCurr, - gl.voucher_type, gl.voucher_no, gl.against_voucher_type, - gl.against_voucher, gl.account_currency, gl.against, + gl.voucher_type, gl.voucher_no, gl.against_voucher_type, + gl.against_voucher, gl.account_currency, gl.against, gl.party_type, gl.party, - inv.name as InvName, inv.title as InvTitle, inv.posting_date as InvPostDate, + inv.name as InvName, inv.title as InvTitle, inv.posting_date as InvPostDate, pur.name as PurName, pur.title as PurTitle, pur.posting_date as PurPostDate, jnl.cheque_no as JnlRef, jnl.posting_date as JnlPostDate, jnl.title as JnlTitle, pay.name as PayName, pay.posting_date as PayPostDate, pay.title as PayTitle, @@ -84,7 +84,7 @@ def get_gl_entries(filters): emp.employee_name, emp.name as empName, stu.title as student_name, stu.name as stuName, member_name, mem.name as memName - + from `tabGL Entry` gl left join `tabSales Invoice` inv on gl.voucher_no = inv.name left join `tabPurchase Invoice` pur on gl.voucher_no = pur.name @@ -124,7 +124,7 @@ def get_result_as_list(data, filters): if account_number[0] is not None: CompteNum = account_number[0] else: - frappe.throw(_("Account number for account {0} is not available.
Please setup your Chart of Accounts correctly.").format(account.name)) + frappe.throw(_("Account number for account {0} is not available.
Please setup your Chart of Accounts correctly.").format(d.get("account"))) if d.get("party_type") == "Customer": CompAuxNum = d.get("cusName") From 72056c26a8ab5afb995455cf7b5156831bf3e103 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 1 May 2019 11:51:04 +0530 Subject: [PATCH 051/115] fix(py3): Undefined variable --- .../asset_value_adjustment/asset_value_adjustment.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py index ac3c3507027..56425a0dcb4 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -36,7 +36,7 @@ class AssetValueAdjustment(Document): fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \ get_depreciation_accounts(asset) - depreciation_cost_center, depreciation_series = frappe.get_cached_value('Company', asset.company, + depreciation_cost_center, depreciation_series = frappe.get_cached_value('Company', asset.company, ["depreciation_cost_center", "series_for_depreciation_entry"]) je = frappe.new_doc("Journal Entry") @@ -75,8 +75,8 @@ class AssetValueAdjustment(Document): rate_per_day = flt(d.value_after_depreciation) / flt(total_days) from_date = self.date else: - no_of_depreciations = len([e.name for e in asset.schedules - if (cint(s.finance_book_id) == d.idx and not e.journal_entry)]) + no_of_depreciations = len([s.name for s in asset.schedules + if (cint(s.finance_book_id) == d.idx and not s.journal_entry)]) value_after_depreciation = d.value_after_depreciation for data in asset.schedules: From 4acd39b6a40b36aa2cb2ca72df644072acc587fb Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 21 Jun 2019 12:08:23 +0530 Subject: [PATCH 052/115] fix(py3): Convert filter to list --- erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index 7f0f60ff02e..fca914e3139 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -350,7 +350,7 @@ def filter_pricing_rules(args, pricing_rules): if len(pricing_rules) > 1: rate_or_discount = list(set([d.rate_or_discount for d in pricing_rules])) if len(rate_or_discount) == 1 and rate_or_discount[0] == "Discount Percentage": - pricing_rules = filter(lambda x: x.for_price_list==args.price_list, pricing_rules) \ + pricing_rules = list(filter(lambda x: x.for_price_list==args.price_list, pricing_rules)) \ or pricing_rules if len(pricing_rules) > 1 and not args.for_shopping_cart: From 618146cc6377907b2ce71d106cdc21fd471d8327 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 21 Jun 2019 12:09:44 +0530 Subject: [PATCH 053/115] fix(py3): Replace unicode with six.text_type --- erpnext/templates/pages/search_help.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/templates/pages/search_help.py b/erpnext/templates/pages/search_help.py index 4a4b0dbd934..cd767b3099c 100644 --- a/erpnext/templates/pages/search_help.py +++ b/erpnext/templates/pages/search_help.py @@ -5,6 +5,7 @@ from jinja2 import utils from html2text import html2text from frappe.utils import sanitize_html from frappe.utils.global_search import search +from six import text_type def get_context(context): context.no_cache = 1 @@ -12,7 +13,7 @@ def get_context(context): query = str(utils.escape(sanitize_html(frappe.form_dict.q))) context.title = _('Help Results for') context.query = query - + context.route = '/search_help' d = frappe._dict() d.results_sections = get_help_results_sections(query) @@ -73,7 +74,7 @@ def prepare_api_results(api, topics_data): for topic in topics_data: route = api.base_url + '/' + (api.post_route + '/' if api.post_route else "") for key in api.post_route_key_list.split(','): - route += unicode(topic[key]) + route += text_type(topic[key]) results.append(frappe._dict({ 'title': topic[api.post_title_key], From 3bafada5a6e23c0706b7b8bf92bc5030ff7c2d9a Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 21 Jun 2019 17:50:44 +0530 Subject: [PATCH 054/115] fix(py3): Convert per_billed explicitly to int before comparing --- erpnext/stock/doctype/purchase_receipt/purchase_receipt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 5c1f573c457..3866c934a8d 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -8,7 +8,7 @@ from frappe.utils import flt, cint, nowdate from frappe import throw, _ import frappe.defaults -from frappe.utils import getdate +from frappe.utils import getdate, cint from erpnext.controllers.buying_controller import BuyingController from erpnext.accounts.utils import get_account_currency from frappe.desk.notifications import clear_doctype_notifications @@ -128,7 +128,7 @@ class PurchaseReceipt(BuyingController): self.company, self.base_grand_total) self.update_prevdoc_status() - if self.per_billed < 100: + if cint(self.per_billed) < 100: self.update_billing_status() else: self.status = "Completed" From 67476e7e09c876a39e9ff0b45dfdb62297aa3e91 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 21 Jun 2019 17:52:51 +0530 Subject: [PATCH 055/115] fix(py3): Convert filter to list --- erpnext/stock/doctype/stock_entry/test_stock_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index c19228fea8b..dfcce5f820b 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -562,7 +562,7 @@ class TestStockEntry(unittest.TestCase): for d in stock_entry.get("items"): if d.item_code != "_Test FG Item 2": rm_cost += flt(d.amount) - fg_cost = filter(lambda x: x.item_code=="_Test FG Item 2", stock_entry.get("items"))[0].amount + fg_cost = list(filter(lambda x: x.item_code=="_Test FG Item 2", stock_entry.get("items")))[0].amount self.assertEqual(fg_cost, flt(rm_cost + bom_operation_cost + work_order.additional_operating_cost, 2)) From b47caf6642e2267d28a9854f4e91eb88b5396816 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 21 Jun 2019 17:56:58 +0530 Subject: [PATCH 056/115] fix(py3): Convert dict.values() to list --- .../test_sales_payment_summary.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py b/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py index 62843e74efc..a51c4276301 100644 --- a/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py +++ b/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py @@ -47,8 +47,8 @@ class TestSalesPaymentSummary(unittest.TestCase): pe.submit() mop = get_mode_of_payments(filters) - self.assertTrue('Credit Card' in mop.values()[0]) - self.assertTrue('Cash' in mop.values()[0]) + self.assertTrue('Credit Card' in list(mop.values())[0]) + self.assertTrue('Cash' in list(mop.values())[0]) # Cancel all Cash payment entry and check if this mode of payment is still fetched. payment_entries = frappe.get_all("Payment Entry", filters={"mode_of_payment": "Cash", "docstatus": 1}, fields=["name", "docstatus"]) @@ -57,8 +57,8 @@ class TestSalesPaymentSummary(unittest.TestCase): pe.cancel() mop = get_mode_of_payments(filters) - self.assertTrue('Credit Card' in mop.values()[0]) - self.assertTrue('Cash' not in mop.values()[0]) + self.assertTrue('Credit Card' in list(mop.values())[0]) + self.assertTrue('Cash' not in list(mop.values())[0]) def test_get_mode_of_payments_details(self): filters = get_filters() @@ -84,7 +84,7 @@ class TestSalesPaymentSummary(unittest.TestCase): mopd = get_mode_of_payment_details(filters) - mopd_values = mopd.values()[0] + mopd_values = list(mopd.values())[0] for mopd_value in mopd_values: if mopd_value[0] == "Credit Card": cc_init_amount = mopd_value[1] @@ -96,7 +96,7 @@ class TestSalesPaymentSummary(unittest.TestCase): pe.cancel() mopd = get_mode_of_payment_details(filters) - mopd_values = mopd.values()[0] + mopd_values = list(mopd.values())[0] for mopd_value in mopd_values: if mopd_value[0] == "Credit Card": cc_final_amount = mopd_value[1] From 6edd2b7f9feb8c84f02ef07e3b5a027066caba10 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 21 Jun 2019 17:58:45 +0530 Subject: [PATCH 057/115] fix(py3): Convert filter to list --- erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index fca914e3139..186f3fd1e60 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -373,7 +373,7 @@ def apply_internal_priority(pricing_rules, field_set, args): filtered_rules = [] for field in field_set: if args.get(field): - filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules) + filtered_rules = list(filter(lambda x: x[field]==args[field], pricing_rules)) if filtered_rules: break return filtered_rules or pricing_rules From 9de95528ef88aac5d12078bb2c2f795b6367599f Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 21 Jun 2019 22:57:31 +0530 Subject: [PATCH 058/115] style: Remove unused imports --- .../accounts/doctype/pricing_rule/test_pricing_rule.py | 9 --------- erpnext/agriculture/doctype/disease/disease.py | 1 - erpnext/agriculture/doctype/soil_texture/soil_texture.py | 5 ++--- .../agriculture/doctype/water_analysis/water_analysis.py | 1 - erpnext/hr/doctype/salary_slip/salary_slip.py | 2 +- .../stock/doctype/purchase_receipt/purchase_receipt.py | 3 +-- 6 files changed, 4 insertions(+), 17 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py index e4f37c44ffc..9b1ee496753 100644 --- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py @@ -18,9 +18,6 @@ class TestPricingRule(unittest.TestCase): frappe.db.sql("delete from `tabPricing Rule`") def test_pricing_rule_for_discount(self): - from erpnext.stock.get_item_details import get_item_details - from frappe import MandatoryError - test_record = { "doctype": "Pricing Rule", "title": "_Test Pricing Rule", @@ -94,9 +91,6 @@ class TestPricingRule(unittest.TestCase): self.assertEquals(details.get("discount_percentage"), 15) def test_pricing_rule_for_margin(self): - from erpnext.stock.get_item_details import get_item_details - from frappe import MandatoryError - test_record = { "doctype": "Pricing Rule", "title": "_Test Pricing Rule", @@ -139,9 +133,6 @@ class TestPricingRule(unittest.TestCase): self.assertEquals(details.get("margin_rate_or_amount"), 10) def test_pricing_rule_for_variants(self): - from erpnext.stock.get_item_details import get_item_details - from frappe import MandatoryError - if not frappe.db.exists("Item", "Test Variant PRT"): frappe.get_doc({ "doctype": "Item", diff --git a/erpnext/agriculture/doctype/disease/disease.py b/erpnext/agriculture/doctype/disease/disease.py index c7707a54652..8a0e6f33d68 100644 --- a/erpnext/agriculture/doctype/disease/disease.py +++ b/erpnext/agriculture/doctype/disease/disease.py @@ -6,7 +6,6 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document -from frappe import _ class Disease(Document): def validate(self): diff --git a/erpnext/agriculture/doctype/soil_texture/soil_texture.py b/erpnext/agriculture/doctype/soil_texture/soil_texture.py index 8c1d7ed5ac1..2254bf87914 100644 --- a/erpnext/agriculture/doctype/soil_texture/soil_texture.py +++ b/erpnext/agriculture/doctype/soil_texture/soil_texture.py @@ -7,7 +7,6 @@ import frappe from frappe import _ from frappe.model.document import Document from frappe.utils import flt, cint -from frappe import _ class SoilTexture(Document): soil_edit_order = [2, 1, 0] @@ -35,8 +34,8 @@ class SoilTexture(Document): if sum(self.soil_edit_order) < 5: return last_edit_index = self.soil_edit_order.index(min(self.soil_edit_order)) - # set composition of the last edited soil - self.set( self.soil_types[last_edit_index], + # set composition of the last edited soil + self.set( self.soil_types[last_edit_index], 100 - sum(cint(self.get(soil_type)) for soil_type in self.soil_types) + cint(self.get(self.soil_types[last_edit_index]))) # calculate soil type diff --git a/erpnext/agriculture/doctype/water_analysis/water_analysis.py b/erpnext/agriculture/doctype/water_analysis/water_analysis.py index 88f1fbd9cce..bd2cd118e1d 100644 --- a/erpnext/agriculture/doctype/water_analysis/water_analysis.py +++ b/erpnext/agriculture/doctype/water_analysis/water_analysis.py @@ -6,7 +6,6 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document -from frappe import _ class WaterAnalysis(Document): def load_contents(self): diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index d3b960d29eb..c73c708b204 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe, erpnext import datetime, math -from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words, getdate +from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words from frappe.model.naming import make_autoname from frappe import msgprint, _ diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 3866c934a8d..052118f67ea 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -4,11 +4,10 @@ from __future__ import unicode_literals import frappe -from frappe.utils import flt, cint, nowdate +from frappe.utils import flt, cint, nowdate, getdate from frappe import throw, _ import frappe.defaults -from frappe.utils import getdate, cint from erpnext.controllers.buying_controller import BuyingController from erpnext.accounts.utils import get_account_currency from frappe.desk.notifications import clear_doctype_notifications From b724e080b01558ec7b55ae1b3e063c7edac1fa57 Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Sun, 23 Jun 2019 20:05:02 +0530 Subject: [PATCH 059/115] fix(BOM): update modified field --- .../buying/doctype/purchase_order_item/purchase_order_item.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json index 350a1894467..238d9545342 100755 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -2344,7 +2344,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2019-01-07 16:51:57.546323", + "modified": "2019-06-23 20:03:13.818917", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order Item", From 2ed653f433872329369897cad38895754a34bf25 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 24 Jun 2019 17:28:47 +0530 Subject: [PATCH 060/115] fix(price list): change the field name --- erpnext/manufacturing/doctype/bom/test_bom.py | 2 +- erpnext/stock/doctype/price_list/price_list.json | 16 +++++++++++++--- .../doctype/price_list/test_price_list_uom.js | 2 +- erpnext/stock/get_item_details.py | 4 ++-- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index e230e598489..45a7b935d38 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -90,7 +90,7 @@ class TestBOM(unittest.TestCase): self.assertEqual(bom.base_total_cost, 486000) def test_bom_cost_multi_uom_multi_currency_based_on_price_list(self): - frappe.db.set_value("Price List", "_Test Price List", "price_not_uom_dependant", 1) + frappe.db.set_value("Price List", "_Test Price List", "price_not_uom_dependent", 1) for item_code, rate in (("_Test Item", 3600), ("_Test Item Home Desktop Manufactured", 3000)): frappe.db.sql("delete from `tabItem Price` where price_list='_Test Price List' and item_code=%s", item_code) diff --git a/erpnext/stock/doctype/price_list/price_list.json b/erpnext/stock/doctype/price_list/price_list.json index 6b447ee8834..56340fb05ca 100644 --- a/erpnext/stock/doctype/price_list/price_list.json +++ b/erpnext/stock/doctype/price_list/price_list.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 1, @@ -22,6 +23,7 @@ "collapsible": 0, "columns": 0, "default": "1", + "fetch_if_empty": 0, "fieldname": "enabled", "fieldtype": "Check", "hidden": 0, @@ -53,6 +55,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sb_1", "fieldtype": "Section Break", "hidden": 0, @@ -83,6 +86,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "price_list_name", "fieldtype": "Data", "hidden": 0, @@ -116,6 +120,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "currency", "fieldtype": "Link", "hidden": 0, @@ -148,6 +153,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "buying", "fieldtype": "Check", "hidden": 0, @@ -179,6 +185,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "selling", "fieldtype": "Check", "hidden": 0, @@ -210,7 +217,8 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "price_not_uom_dependant", + "fetch_if_empty": 0, + "fieldname": "price_not_uom_dependent", "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, @@ -219,7 +227,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Price Not UOM Dependant", + "label": "Price Not UOM Dependent", "length": 0, "no_copy": 0, "permlevel": 0, @@ -242,6 +250,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_3", "fieldtype": "Column Break", "hidden": 0, @@ -272,6 +281,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "countries", "fieldtype": "Table", "hidden": 0, @@ -310,7 +320,7 @@ "issingle": 0, "istable": 0, "max_attachments": 1, - "modified": "2018-08-29 06:35:16.546274", + "modified": "2019-06-24 17:16:28.027302", "modified_by": "Administrator", "module": "Stock", "name": "Price List", diff --git a/erpnext/stock/doctype/price_list/test_price_list_uom.js b/erpnext/stock/doctype/price_list/test_price_list_uom.js index 526d0da97d8..7fbce7d59d2 100644 --- a/erpnext/stock/doctype/price_list/test_price_list_uom.js +++ b/erpnext/stock/doctype/price_list/test_price_list_uom.js @@ -7,7 +7,7 @@ QUnit.test("test price list with uom dependancy", function(assert) { () => frappe.set_route('Form', 'Price List', 'Standard Buying'), () => { - cur_frm.set_value('price_not_uom_dependant','1'); + cur_frm.set_value('price_not_uom_dependent','1'); frappe.timeout(1); }, () => cur_frm.save(), diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 851088be948..0828a5ca543 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -834,12 +834,12 @@ def get_price_list_currency(price_list): def get_price_list_uom_dependant(price_list): if price_list: result = frappe.db.get_value("Price List", {"name": price_list, - "enabled": 1}, ["name", "price_not_uom_dependant"], as_dict=True) + "enabled": 1}, ["name", "price_not_uom_dependent"], as_dict=True) if not result: throw(_("Price List {0} is disabled or does not exist").format(price_list)) - return not result.price_not_uom_dependant + return not result.price_not_uom_dependent def get_price_list_currency_and_exchange_rate(args): From a8289d4fd560ae606bac0783c016de1a58bdd84b Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 24 Jun 2019 11:17:45 +0530 Subject: [PATCH 061/115] fix: test case for payment terms in quotation --- erpnext/selling/doctype/quotation/test_quotation.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py index 8bb8c618f29..7ee4a76ca66 100644 --- a/erpnext/selling/doctype/quotation/test_quotation.py +++ b/erpnext/selling/doctype/quotation/test_quotation.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe -from frappe.utils import flt, add_days, nowdate, add_months +from frappe.utils import flt, add_days, nowdate, add_months, getdate import unittest test_dependencies = ["Product Bundle"] @@ -18,7 +18,7 @@ class TestQuotation(unittest.TestCase): self.assertTrue(quotation.payment_schedule) - def test_make_sales_order_terms_not_copied(self): + def test_make_sales_order_terms_copied(self): from erpnext.selling.doctype.quotation.quotation import make_sales_order quotation = frappe.copy_doc(test_records[0]) @@ -29,7 +29,7 @@ class TestQuotation(unittest.TestCase): sales_order = make_sales_order(quotation.name) - self.assertFalse(sales_order.get('payment_schedule')) + self.assertTrue(sales_order.get('payment_schedule')) def test_make_sales_order_with_different_currency(self): from erpnext.selling.doctype.quotation.quotation import make_sales_order @@ -109,10 +109,10 @@ class TestQuotation(unittest.TestCase): sales_order.insert() self.assertEqual(sales_order.payment_schedule[0].payment_amount, 8906.00) - self.assertEqual(sales_order.payment_schedule[0].due_date, quotation.transaction_date) + self.assertEqual(sales_order.payment_schedule[0].due_date, getdate(quotation.transaction_date)) self.assertEqual(sales_order.payment_schedule[1].payment_amount, 8906.00) self.assertEqual( - sales_order.payment_schedule[1].due_date, add_days(quotation.transaction_date, 30) + sales_order.payment_schedule[1].due_date, getdate(add_days(quotation.transaction_date, 30)) ) def test_valid_till(self): From 069276473f0627f297e82d4d222f360579373642 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 24 Jun 2019 17:46:44 +0530 Subject: [PATCH 062/115] fix: Division by zero error fix in group similar item --- erpnext/controllers/accounts_controller.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 92d380421d7..79695732683 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -747,7 +747,12 @@ class AccountsController(TransactionBase): count += 1 item.qty = group_item_qty[item.item_code] item.amount = group_item_amount[item.item_code] - item.rate = flt(flt(item.amount) / flt(item.qty), item.precision("rate")) + + if item.qty: + item.rate = flt(flt(item.amount) / flt(item.qty), item.precision("rate")) + else: + item.rate = 0 + item.idx = count del group_item_qty[item.item_code] else: From ee227061826d4b032714d05d7d84b8913149da89 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 24 Jun 2019 17:52:14 +0530 Subject: [PATCH 063/115] fix: Closed job opening disaplying in job applicant --- erpnext/hr/doctype/job_applicant/job_applicant.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/erpnext/hr/doctype/job_applicant/job_applicant.js b/erpnext/hr/doctype/job_applicant/job_applicant.js index 977702e314c..05071e19743 100644 --- a/erpnext/hr/doctype/job_applicant/job_applicant.js +++ b/erpnext/hr/doctype/job_applicant/job_applicant.js @@ -25,5 +25,13 @@ frappe.ui.form.on("Job Applicant", { } } + frm.set_query("job_title", function() { + return { + filters: { + 'status': 'Open' + } + }; + }); + } }); \ No newline at end of file From 5d6ccafac9bda62bcb05aa67095a93e780d3cb37 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 24 Jun 2019 21:12:16 +0530 Subject: [PATCH 064/115] fix: Currency symbol fix for rounded total --- .../purchase_order/purchase_order.json | 119 +++++++++++++++++- 1 file changed, 118 insertions(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index 8c586d14669..0e145009efa 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -20,6 +20,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "supplier_section", "fieldtype": "Section Break", "hidden": 0, @@ -53,6 +54,7 @@ "collapsible": 0, "columns": 0, "default": "{supplier_name}", + "fetch_if_empty": 0, "fieldname": "title", "fieldtype": "Data", "hidden": 1, @@ -86,6 +88,7 @@ "collapsible": 0, "columns": 0, "default": "", + "fetch_if_empty": 0, "fieldname": "naming_series", "fieldtype": "Select", "hidden": 0, @@ -121,6 +124,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "supplier", "fieldtype": "Link", "hidden": 0, @@ -156,6 +160,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.supplier && doc.docstatus===0 && (!(doc.items && doc.items.length) || (doc.items.length==1 && !doc.items[0].item_code))", + "fetch_if_empty": 0, "fieldname": "get_items_from_open_material_requests", "fieldtype": "Button", "hidden": 0, @@ -189,6 +194,7 @@ "collapsible": 0, "columns": 0, "fetch_from": "supplier.supplier_name", + "fetch_if_empty": 0, "fieldname": "supplier_name", "fieldtype": "Data", "hidden": 0, @@ -222,6 +228,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "company", "fieldtype": "Link", "hidden": 0, @@ -256,6 +263,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break1", "fieldtype": "Column Break", "hidden": 0, @@ -290,6 +298,7 @@ "collapsible": 0, "columns": 0, "default": "Today", + "fetch_if_empty": 0, "fieldname": "transaction_date", "fieldtype": "Date", "hidden": 0, @@ -324,6 +333,7 @@ "collapsible": 0, "columns": 0, "default": "", + "fetch_if_empty": 0, "fieldname": "schedule_date", "fieldtype": "Date", "hidden": 0, @@ -357,6 +367,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.docstatus===1", + "fetch_if_empty": 0, "fieldname": "order_confirmation_no", "fieldtype": "Data", "hidden": 0, @@ -390,6 +401,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.order_confirmation_no", + "fetch_if_empty": 0, "fieldname": "order_confirmation_date", "fieldtype": "Date", "hidden": 0, @@ -422,6 +434,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "amended_from", "fieldtype": "Link", "hidden": 0, @@ -457,6 +470,7 @@ "collapsible": 0, "collapsible_depends_on": "", "columns": 0, + "fetch_if_empty": 0, "fieldname": "drop_ship", "fieldtype": "Section Break", "hidden": 0, @@ -490,6 +504,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "customer", "fieldtype": "Link", "hidden": 0, @@ -524,6 +539,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "customer_name", "fieldtype": "Data", "hidden": 0, @@ -556,6 +572,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_19", "fieldtype": "Column Break", "hidden": 0, @@ -588,6 +605,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "customer_contact_person", "fieldtype": "Link", "hidden": 0, @@ -621,6 +639,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "customer_contact_display", "fieldtype": "Small Text", "hidden": 1, @@ -653,6 +672,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "customer_contact_mobile", "fieldtype": "Small Text", "hidden": 1, @@ -685,6 +705,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "customer_contact_email", "fieldtype": "Code", "hidden": 1, @@ -718,6 +739,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_addresses", "fieldtype": "Section Break", "hidden": 0, @@ -750,6 +772,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "supplier_address", "fieldtype": "Link", "hidden": 0, @@ -782,6 +805,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "contact_person", "fieldtype": "Link", "hidden": 0, @@ -815,6 +839,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "address_display", "fieldtype": "Small Text", "hidden": 0, @@ -846,6 +871,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "contact_display", "fieldtype": "Small Text", "hidden": 0, @@ -877,6 +903,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "contact_mobile", "fieldtype": "Small Text", "hidden": 0, @@ -908,6 +935,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "contact_email", "fieldtype": "Small Text", "hidden": 0, @@ -939,6 +967,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "col_break_address", "fieldtype": "Column Break", "hidden": 0, @@ -971,6 +1000,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "shipping_address", "fieldtype": "Link", "hidden": 0, @@ -1004,6 +1034,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "shipping_address_display", "fieldtype": "Small Text", "hidden": 0, @@ -1036,6 +1067,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "currency_and_price_list", "fieldtype": "Section Break", "hidden": 0, @@ -1068,6 +1100,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "currency", "fieldtype": "Link", "hidden": 0, @@ -1103,6 +1136,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "conversion_rate", "fieldtype": "Float", "hidden": 0, @@ -1137,6 +1171,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "cb_price_list", "fieldtype": "Column Break", "hidden": 0, @@ -1167,6 +1202,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "buying_price_list", "fieldtype": "Link", "hidden": 0, @@ -1199,6 +1235,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "price_list_currency", "fieldtype": "Link", "hidden": 0, @@ -1231,6 +1268,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "plc_conversion_rate", "fieldtype": "Float", "hidden": 0, @@ -1263,6 +1301,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "ignore_pricing_rule", "fieldtype": "Check", "hidden": 0, @@ -1294,6 +1333,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sec_warehouse", "fieldtype": "Section Break", "hidden": 0, @@ -1325,6 +1365,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "set_warehouse", "fieldtype": "Link", "hidden": 0, @@ -1358,6 +1399,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "col_break_warehouse", "fieldtype": "Column Break", "hidden": 0, @@ -1390,6 +1432,7 @@ "collapsible": 0, "columns": 0, "default": "No", + "fetch_if_empty": 0, "fieldname": "is_subcontracted", "fieldtype": "Select", "hidden": 0, @@ -1423,6 +1466,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.is_subcontracted==\"Yes\"", + "fetch_if_empty": 0, "fieldname": "supplier_warehouse", "fieldtype": "Link", "hidden": 0, @@ -1456,6 +1500,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "items_section", "fieldtype": "Section Break", "hidden": 0, @@ -1489,6 +1534,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "scan_barcode", "fieldtype": "Data", "hidden": 0, @@ -1521,6 +1567,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "items", "fieldtype": "Table", "hidden": 0, @@ -1556,6 +1603,7 @@ "collapsible": 0, "collapsible_depends_on": "supplied_items", "columns": 0, + "fetch_if_empty": 0, "fieldname": "raw_material_details", "fieldtype": "Section Break", "hidden": 0, @@ -1589,6 +1637,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "supplied_items", "fieldtype": "Table", "hidden": 0, @@ -1623,6 +1672,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sb_last_purchase", "fieldtype": "Section Break", "hidden": 0, @@ -1653,6 +1703,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_qty", "fieldtype": "Float", "hidden": 0, @@ -1685,6 +1736,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_total", "fieldtype": "Currency", "hidden": 0, @@ -1718,6 +1770,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_net_total", "fieldtype": "Currency", "hidden": 0, @@ -1752,6 +1805,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_26", "fieldtype": "Column Break", "hidden": 0, @@ -1782,6 +1836,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total", "fieldtype": "Currency", "hidden": 0, @@ -1815,6 +1870,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "net_total", "fieldtype": "Currency", "hidden": 0, @@ -1849,6 +1905,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_net_weight", "fieldtype": "Float", "hidden": 0, @@ -1881,6 +1938,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "taxes_section", "fieldtype": "Section Break", "hidden": 0, @@ -1915,6 +1973,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "taxes_and_charges", "fieldtype": "Link", "hidden": 0, @@ -1949,6 +2008,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_50", "fieldtype": "Column Break", "hidden": 0, @@ -1980,6 +2040,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "shipping_rule", "fieldtype": "Link", "hidden": 0, @@ -2013,6 +2074,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_52", "fieldtype": "Section Break", "hidden": 0, @@ -2044,6 +2106,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "taxes", "fieldtype": "Table", "hidden": 0, @@ -2078,6 +2141,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sec_tax_breakup", "fieldtype": "Section Break", "hidden": 0, @@ -2110,6 +2174,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "other_charges_calculation", "fieldtype": "Text", "hidden": 0, @@ -2142,6 +2207,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "totals", "fieldtype": "Section Break", "hidden": 0, @@ -2175,6 +2241,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_taxes_and_charges_added", "fieldtype": "Currency", "hidden": 0, @@ -2209,6 +2276,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_taxes_and_charges_deducted", "fieldtype": "Currency", "hidden": 0, @@ -2243,6 +2311,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_total_taxes_and_charges", "fieldtype": "Currency", "hidden": 0, @@ -2277,6 +2346,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_39", "fieldtype": "Column Break", "hidden": 0, @@ -2308,6 +2378,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "taxes_and_charges_added", "fieldtype": "Currency", "hidden": 0, @@ -2342,6 +2413,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "taxes_and_charges_deducted", "fieldtype": "Currency", "hidden": 0, @@ -2376,6 +2448,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_taxes_and_charges", "fieldtype": "Currency", "hidden": 0, @@ -2410,6 +2483,7 @@ "collapsible": 1, "collapsible_depends_on": "discount_amount", "columns": 0, + "fetch_if_empty": 0, "fieldname": "discount_section", "fieldtype": "Section Break", "hidden": 0, @@ -2443,6 +2517,7 @@ "collapsible": 0, "columns": 0, "default": "Grand Total", + "fetch_if_empty": 0, "fieldname": "apply_discount_on", "fieldtype": "Select", "hidden": 0, @@ -2476,6 +2551,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_discount_amount", "fieldtype": "Currency", "hidden": 0, @@ -2509,6 +2585,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_45", "fieldtype": "Column Break", "hidden": 0, @@ -2540,6 +2617,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "additional_discount_percentage", "fieldtype": "Float", "hidden": 0, @@ -2572,6 +2650,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "discount_amount", "fieldtype": "Currency", "hidden": 0, @@ -2605,6 +2684,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "totals_section", "fieldtype": "Section Break", "hidden": 0, @@ -2636,6 +2716,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_grand_total", "fieldtype": "Currency", "hidden": 0, @@ -2670,6 +2751,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_rounding_adjustment", "fieldtype": "Currency", "hidden": 0, @@ -2704,6 +2786,7 @@ "collapsible": 0, "columns": 0, "description": "In Words will be visible once you save the Purchase Order.", + "fetch_if_empty": 0, "fieldname": "base_in_words", "fieldtype": "Data", "hidden": 0, @@ -2737,6 +2820,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_rounded_total", "fieldtype": "Currency", "hidden": 0, @@ -2771,6 +2855,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break4", "fieldtype": "Column Break", "hidden": 0, @@ -2802,6 +2887,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "grand_total", "fieldtype": "Currency", "hidden": 0, @@ -2836,6 +2922,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "rounding_adjustment", "fieldtype": "Currency", "hidden": 0, @@ -2869,6 +2956,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "rounded_total", "fieldtype": "Currency", "hidden": 0, @@ -2881,6 +2969,7 @@ "label": "Rounded Total", "length": 0, "no_copy": 0, + "options": "currency", "permlevel": 0, "precision": "", "print_hide": 0, @@ -2901,6 +2990,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "disable_rounded_total", "fieldtype": "Check", "hidden": 0, @@ -2933,6 +3023,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "in_words", "fieldtype": "Data", "hidden": 0, @@ -2966,6 +3057,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "advance_paid", "fieldtype": "Currency", "hidden": 0, @@ -2998,6 +3090,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "payment_schedule_section", "fieldtype": "Section Break", "hidden": 0, @@ -3030,6 +3123,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "payment_terms_template", "fieldtype": "Link", "hidden": 0, @@ -3063,6 +3157,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "payment_schedule", "fieldtype": "Table", "hidden": 0, @@ -3097,6 +3192,7 @@ "collapsible": 1, "collapsible_depends_on": "terms", "columns": 0, + "fetch_if_empty": 0, "fieldname": "terms_section_break", "fieldtype": "Section Break", "hidden": 0, @@ -3130,6 +3226,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "tc_name", "fieldtype": "Link", "hidden": 0, @@ -3164,6 +3261,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "terms", "fieldtype": "Text Editor", "hidden": 0, @@ -3197,6 +3295,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "more_info", "fieldtype": "Section Break", "hidden": 0, @@ -3230,6 +3329,7 @@ "collapsible": 0, "columns": 0, "default": "Draft", + "fetch_if_empty": 0, "fieldname": "status", "fieldtype": "Select", "hidden": 0, @@ -3264,6 +3364,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "ref_sq", "fieldtype": "Data", "hidden": 1, @@ -3297,6 +3398,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "party_account_currency", "fieldtype": "Link", "hidden": 1, @@ -3330,6 +3432,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_74", "fieldtype": "Column Break", "hidden": 0, @@ -3363,6 +3466,7 @@ "columns": 0, "depends_on": "eval:!doc.__islocal", "description": "", + "fetch_if_empty": 0, "fieldname": "per_received", "fieldtype": "Percent", "hidden": 0, @@ -3398,6 +3502,7 @@ "columns": 0, "depends_on": "eval:!doc.__islocal", "description": "", + "fetch_if_empty": 0, "fieldname": "per_billed", "fieldtype": "Percent", "hidden": 0, @@ -3431,6 +3536,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break5", "fieldtype": "Section Break", "hidden": 0, @@ -3465,6 +3571,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "letter_head", "fieldtype": "Link", "hidden": 0, @@ -3499,6 +3606,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "select_print_heading", "fieldtype": "Link", "hidden": 0, @@ -3533,6 +3641,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_86", "fieldtype": "Column Break", "hidden": 0, @@ -3565,6 +3674,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "group_same_items", "fieldtype": "Check", "hidden": 0, @@ -3598,6 +3708,7 @@ "collapsible": 0, "columns": 0, "default": "", + "fetch_if_empty": 0, "fieldname": "language", "fieldtype": "Data", "hidden": 0, @@ -3631,6 +3742,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "subscription_section", "fieldtype": "Section Break", "hidden": 0, @@ -3665,6 +3777,7 @@ "columns": 0, "depends_on": "", "description": "", + "fetch_if_empty": 0, "fieldname": "from_date", "fieldtype": "Date", "hidden": 0, @@ -3698,6 +3811,7 @@ "columns": 0, "depends_on": "", "description": "", + "fetch_if_empty": 0, "fieldname": "to_date", "fieldtype": "Date", "hidden": 0, @@ -3729,6 +3843,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_97", "fieldtype": "Column Break", "hidden": 0, @@ -3760,6 +3875,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "auto_repeat", "fieldtype": "Link", "hidden": 0, @@ -3794,6 +3910,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval: doc.auto_repeat", + "fetch_if_empty": 0, "fieldname": "update_auto_repeat_reference", "fieldtype": "Button", "hidden": 0, @@ -3831,7 +3948,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-01-07 16:51:56.739693", + "modified": "2019-06-24 20:55:03.466766", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", From ae255d6328b70b148d28d9a88a695932656bf276 Mon Sep 17 00:00:00 2001 From: karthikeyan5 Date: Tue, 25 Jun 2019 14:01:13 +0530 Subject: [PATCH 065/115] Fix(integrations): Adding Error Logs for Woocommerce --- .../connectors/woocommerce_connection.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py index 4700202213f..0b6ea8cc7ca 100644 --- a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py +++ b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py @@ -22,7 +22,16 @@ def verify_request(): frappe.set_user(woocommerce_settings.creation_user) @frappe.whitelist(allow_guest=True) -def order(): +def order(*args, **kwargs): + try: + _order(*args, **kwargs) + except Exception: + error_message = frappe.get_traceback()+"\n\n Request Data: \n"+json.loads(frappe.request.data).__str__() + frappe.log_error(error_message, "WooCommerce Error") + raise + + +def _order(*args, **kwargs): woocommerce_settings = frappe.get_doc("Woocommerce Settings") if frappe.flags.woocomm_test_order_data: fd = frappe.flags.woocomm_test_order_data From 10878c4d0ede704b563cd9d45486815299ec718b Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 26 Jun 2019 10:57:39 +0530 Subject: [PATCH 066/115] fix: Show close button if per_ordered is less than 99.999999 (#18068) --- erpnext/accounts/report/non_billed_report.py | 7 ++++--- erpnext/buying/doctype/purchase_order/purchase_order.js | 2 +- erpnext/selling/doctype/sales_order/sales_order.js | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/report/non_billed_report.py b/erpnext/accounts/report/non_billed_report.py index 41ec9b74665..9f19c0d7591 100644 --- a/erpnext/accounts/report/non_billed_report.py +++ b/erpnext/accounts/report/non_billed_report.py @@ -12,20 +12,21 @@ def get_ordered_to_be_billed_data(args): child_tab = doctype + " Item" precision = get_field_precision(frappe.get_meta(child_tab).get_field("billed_amt"), currency=get_default_currency()) or 2 - + project_field = get_project_field(doctype, party) return frappe.db.sql(""" Select `{parent_tab}`.name, `{parent_tab}`.{date_field}, `{parent_tab}`.{party}, `{parent_tab}`.{party}_name, {project_field}, `{child_tab}`.item_code, `{child_tab}`.base_amount, - (`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)), + (`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)), (`{child_tab}`.base_amount - (`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1))), `{child_tab}`.item_name, `{child_tab}`.description, `{parent_tab}`.company from `{parent_tab}`, `{child_tab}` where - `{parent_tab}`.name = `{child_tab}`.parent and `{parent_tab}`.docstatus = 1 and `{parent_tab}`.status != 'Closed' + `{parent_tab}`.name = `{child_tab}`.parent and `{parent_tab}`.docstatus = 1 + and `{parent_tab}`.status not in ('Closed', 'Completed') and `{child_tab}`.amount > 0 and round(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1), {precision}) < `{child_tab}`.base_amount order by diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index c032df32706..7b90b2b2a6f 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -104,7 +104,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend( if(doc.docstatus == 1 && !in_list(["Closed", "Delivered"], doc.status)) { if (this.frm.has_perm("submit")) { - if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100) { + if(flt(doc.per_billed, 6) < 100 || flt(doc.per_received, 6) < 100) { cur_frm.add_custom_button(__('Close'), this.close_purchase_order, __("Status")); } } diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 53b3e73f5e2..84c1693d20c 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -133,7 +133,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( if (this.frm.has_perm("submit")) { // close - if(flt(doc.per_delivered, 6) < 100 || flt(doc.per_billed) < 100) { + if(flt(doc.per_delivered, 6) < 100 || flt(doc.per_billed, 6) < 100) { this.frm.add_custom_button(__('Close'), function() { me.close_sales_order() }, __("Status")) } From b2c43ee2d91599038f7bdf2038bbc4c4e7b36285 Mon Sep 17 00:00:00 2001 From: Karthikeyan S Date: Wed, 26 Jun 2019 11:00:17 +0530 Subject: [PATCH 067/115] fix(item): fix patch for barcode childtable migration in item (#18066) * fix(item): fix patch for barcode childtable migration in item * fix(item): fix patch for barcode childtable migration in item > adding condition so this patch will not execute for the site where it was executed perfectly the first time --- erpnext/patches.txt | 2 +- erpnext/patches/v10_0/item_barcode_childtable_migrate.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index ae06b5dba35..3ed19169295 100755 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -586,7 +586,7 @@ erpnext.patches.v11_0.add_permissions_in_gst_settings erpnext.patches.v11_1.setup_guardian_role execute:frappe.delete_doc('DocType', 'Notification Control') erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants -erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019 +erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019 #25-06-2019 erpnext.patches.v11_0.make_italian_localization_fields # 26-03-2019 erpnext.patches.v11_1.make_job_card_time_logs erpnext.patches.v11_1.set_variant_based_on diff --git a/erpnext/patches/v10_0/item_barcode_childtable_migrate.py b/erpnext/patches/v10_0/item_barcode_childtable_migrate.py index e30e0a74c00..c16f3554b30 100644 --- a/erpnext/patches/v10_0/item_barcode_childtable_migrate.py +++ b/erpnext/patches/v10_0/item_barcode_childtable_migrate.py @@ -7,9 +7,10 @@ import frappe def execute(): + if frappe.get_all("Item Barcode", limit=1): return frappe.reload_doc("stock", "doctype", "item_barcode") - items_barcode = frappe.get_all('Item', ['name', 'barcode'], { 'barcode': ('!=', '') }) + items_barcode = frappe.db.sql("select name, barcode from tabItem where barcode is not null", as_dict=True) frappe.reload_doc("stock", "doctype", "item") From 840bfa87e8f9799ea7d57a6b86789a66c8ffefca Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 26 Jun 2019 11:03:36 +0530 Subject: [PATCH 068/115] fix: change the department to tree view (#18056) --- erpnext/hooks.py | 2 +- erpnext/hr/doctype/department/department.js | 2 +- erpnext/hr/doctype/department/department.json | 19 +++++++++++++++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 9b18e5e1f3a..a067e28747e 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -42,7 +42,7 @@ update_and_get_user_progress = "erpnext.utilities.user_progress_utils.update_def on_session_creation = "erpnext.shopping_cart.utils.set_cart_count" on_logout = "erpnext.shopping_cart.utils.clear_cart_count" -treeviews = ['Account', 'Cost Center', 'Warehouse', 'Item Group', 'Customer Group', 'Sales Person', 'Territory', 'Assessment Group'] +treeviews = ['Account', 'Cost Center', 'Warehouse', 'Item Group', 'Customer Group', 'Sales Person', 'Territory', 'Assessment Group', 'Department'] # website update_website_context = "erpnext.shopping_cart.utils.update_website_context" diff --git a/erpnext/hr/doctype/department/department.js b/erpnext/hr/doctype/department/department.js index 76bc932144c..963f3615cc5 100644 --- a/erpnext/hr/doctype/department/department.js +++ b/erpnext/hr/doctype/department/department.js @@ -4,7 +4,7 @@ frappe.ui.form.on('Department', { refresh: function(frm) { // read-only for root department - if(!frm.doc.parent_department) { + if(!frm.doc.parent_department && !frm.is_new()) { frm.set_read_only(); frm.set_intro(__("This is a root department and cannot be edited.")); } diff --git a/erpnext/hr/doctype/department/department.json b/erpnext/hr/doctype/department/department.json index aed7f42faf8..3b400ce8d76 100644 --- a/erpnext/hr/doctype/department/department.json +++ b/erpnext/hr/doctype/department/department.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 1, @@ -19,6 +20,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "department_name", "fieldtype": "Data", "hidden": 0, @@ -52,6 +54,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "parent_department", "fieldtype": "Link", "hidden": 0, @@ -85,6 +88,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company", "fieldtype": "Link", "hidden": 0, @@ -118,6 +122,7 @@ "bold": 1, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "is_group", "fieldtype": "Check", "hidden": 0, @@ -150,6 +155,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "disabled", "fieldtype": "Check", "hidden": 0, @@ -182,6 +188,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_4", "fieldtype": "Section Break", "hidden": 0, @@ -214,6 +221,7 @@ "collapsible": 0, "columns": 0, "description": "Days for which Holidays are blocked for this department.", + "fetch_if_empty": 0, "fieldname": "leave_block_list", "fieldtype": "Link", "hidden": 0, @@ -246,6 +254,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "leave_section", "fieldtype": "Section Break", "hidden": 0, @@ -279,6 +288,7 @@ "collapsible": 0, "columns": 0, "description": "The first Leave Approver in the list will be set as the default Leave Approver.", + "fetch_if_empty": 0, "fieldname": "leave_approvers", "fieldtype": "Table", "hidden": 0, @@ -312,6 +322,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "expense_section", "fieldtype": "Section Break", "hidden": 0, @@ -345,6 +356,7 @@ "collapsible": 0, "columns": 0, "description": "The first Expense Approver in the list will be set as the default Expense Approver.", + "fetch_if_empty": 0, "fieldname": "expense_approvers", "fieldtype": "Table", "hidden": 0, @@ -378,6 +390,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "lft", "fieldtype": "Int", "hidden": 1, @@ -410,6 +423,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "rgt", "fieldtype": "Int", "hidden": 1, @@ -442,6 +456,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "old_parent", "fieldtype": "Data", "hidden": 1, @@ -479,7 +494,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-08-29 06:26:12.995703", + "modified": "2019-06-25 18:43:05.550387", "modified_by": "Administrator", "module": "HR", "name": "Department", @@ -543,7 +558,7 @@ "write": 1 } ], - "quick_entry": 1, + "quick_entry": 0, "read_only": 0, "read_only_onload": 0, "show_name_in_global_search": 1, From 3957880370eeb0df6a3a7185f6f8accab6efddfb Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Wed, 26 Jun 2019 11:06:14 +0530 Subject: [PATCH 069/115] fix: Removed submitted status from quotation (#18054) * fix: Change in list view and status updater * fix: Change status in doctype * fix: Patch for submitted status --- erpnext/controllers/status_updater.py | 2 +- erpnext/patches.txt | 3 ++- erpnext/patches/v11_1/set_quotation_status.py | 7 +++++++ erpnext/selling/doctype/quotation/quotation.json | 4 ++-- erpnext/selling/doctype/quotation/quotation_list.js | 4 ++-- 5 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 erpnext/patches/v11_1/set_quotation_status.py diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 2484586d041..a3018029bc0 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -27,7 +27,7 @@ status_map = { ], "Quotation": [ ["Draft", None], - ["Submitted", "eval:self.docstatus==1"], + ["Open", "eval:self.docstatus==1"], ["Lost", "eval:self.status=='Lost'"], ["Ordered", "has_sales_order"], ["Cancelled", "eval:self.docstatus==2"], diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 3ed19169295..962ef8a8a8d 100755 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -601,4 +601,5 @@ execute:frappe.delete_doc("Report", "Inactive Items") erpnext.patches.v11_1.delete_scheduling_tool erpnext.patches.v11_1.update_bank_transaction_status erpnext.patches.v11_1.renamed_delayed_item_report -erpnext.patches.v11_1.set_missing_opportunity_from \ No newline at end of file +erpnext.patches.v11_1.set_missing_opportunity_from +erpnext.patches.v11_1.set_quotation_status \ No newline at end of file diff --git a/erpnext/patches/v11_1/set_quotation_status.py b/erpnext/patches/v11_1/set_quotation_status.py new file mode 100644 index 00000000000..87643a23545 --- /dev/null +++ b/erpnext/patches/v11_1/set_quotation_status.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals +import frappe + +def execute(): + + frappe.db.sql(""" UPDATE `tabQuotation` set status = 'Open' + where docstatus = 1 and status = 'Submitted' """) diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json index 33fc4dbeb04..65fbe52d9a4 100644 --- a/erpnext/selling/doctype/quotation/quotation.json +++ b/erpnext/selling/doctype/quotation/quotation.json @@ -3096,7 +3096,7 @@ "no_copy": 1, "oldfieldname": "status", "oldfieldtype": "Select", - "options": "Draft\nSubmitted\nOrdered\nLost\nCancelled\nOpen\nReplied", + "options": "Draft\nOpen\nReplied\nOrdered\nLost\nCancelled", "permlevel": 0, "print_hide": 1, "print_hide_if_no_value": 0, @@ -3224,7 +3224,7 @@ "istable": 0, "max_attachments": 1, "menu_index": 0, - "modified": "2019-05-11 19:26:50.735628", + "modified": "2019-06-25 15:31:04.724730", "modified_by": "Administrator", "module": "Selling", "name": "Quotation", diff --git a/erpnext/selling/doctype/quotation/quotation_list.js b/erpnext/selling/doctype/quotation/quotation_list.js index 61a8bc1cab3..5f4e2546fbc 100644 --- a/erpnext/selling/doctype/quotation/quotation_list.js +++ b/erpnext/selling/doctype/quotation/quotation_list.js @@ -13,11 +13,11 @@ frappe.listview_settings['Quotation'] = { }, get_indicator: function(doc) { - if(doc.status==="Submitted") { + if(doc.status==="Open") { if (doc.valid_till && doc.valid_till < frappe.datetime.nowdate()) { return [__("Expired"), "darkgrey", "valid_till,<," + frappe.datetime.nowdate()]; } else { - return [__("Submitted"), "blue", "status,=,Submitted"]; + return [__("Open"), "orange", "status,=,Open"]; } } else if(doc.status==="Ordered") { return [__("Ordered"), "green", "status,=,Ordered"]; From 453d484a964fac66dec4ee9ad1acf7bc4bd1ca28 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 26 Jun 2019 11:09:39 +0530 Subject: [PATCH 070/115] fix: precision for certain calculations in buying controller (#18009) * fix: precision for certain numbers * fix: check precision of the received_qty * Update buying_controller.py --- erpnext/controllers/buying_controller.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 664bce4e4fa..917c901cfcb 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -428,8 +428,9 @@ class BuyingController(StockController): elif not flt(d.rejected_qty): d.rejected_qty = flt(d.received_qty) - flt(d.qty) + val = flt(d.qty) + flt(d.rejected_qty) # Check Received Qty = Accepted Qty + Rejected Qty - if ((flt(d.qty) + flt(d.rejected_qty)) != flt(d.received_qty)): + if (flt(val, d.precision("received_qty")) != flt(d.received_qty, d.precision("received_qty"))): frappe.throw(_("Accepted + Rejected Qty must be equal to Received quantity for Item {0}").format(d.item_code)) def validate_negative_quantity(self, item_row, field_list): From 836aa5a1e68f081d0fa76e14cd788567d85cfedb Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 26 Jun 2019 11:35:53 +0530 Subject: [PATCH 071/115] fix: attendance gantt view --- erpnext/hr/doctype/attendance/attendance_calendar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/hr/doctype/attendance/attendance_calendar.js b/erpnext/hr/doctype/attendance/attendance_calendar.js index b21afe5eaee..104f09d69ff 100644 --- a/erpnext/hr/doctype/attendance/attendance_calendar.js +++ b/erpnext/hr/doctype/attendance/attendance_calendar.js @@ -2,8 +2,8 @@ // For license information, please see license.txt frappe.views.calendar["Attendance"] = { field_map: { - "start": "date", - "end": "date", + "start": "attendance_date", + "end": "attendance_date", "id": "name", "docstatus": 1 }, From cf77740ab152b04b1005ef261311f4c2849d60bd Mon Sep 17 00:00:00 2001 From: Anurag Mishra Date: Fri, 21 Jun 2019 15:38:36 +0530 Subject: [PATCH 072/115] fix: wrong Casual Leave opening --- .../report/employee_leave_balance/employee_leave_balance.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py index 95cb30b7918..5d781dba94f 100644 --- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py +++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py @@ -35,6 +35,9 @@ def get_data(filters, leave_types): allocation_records_based_on_to_date = get_leave_allocation_records(filters.to_date) allocation_records_based_on_from_date = get_leave_allocation_records(filters.from_date) + if filters.to_date <= filters.from_date: + frappe.throw(_("From date can not be greater than than To date")) + active_employees = frappe.get_all("Employee", filters = { "status": "Active", "company": filters.company}, fields = ["name", "employee_name", "department", "user_id"]) @@ -51,7 +54,8 @@ def get_data(filters, leave_types): filters.from_date, filters.to_date) # opening balance - opening = get_total_allocated_leaves(employee.name, leave_type, filters.to_date) + opening = get_leave_balance_on(employee.name, leave_type, filters.from_date, + allocation_records_based_on_to_date.get(employee.name, frappe._dict())) # closing balance closing = get_leave_balance_on(employee.name, leave_type, filters.to_date, From a6a617122526e2d33324e931bb9afbfb6a5289ea Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 26 Jun 2019 13:30:54 +0530 Subject: [PATCH 073/115] fix: Don't append None values in against_account (#18032) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index ca94b52c532..e06db8f4bc6 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -487,7 +487,7 @@ class SalesInvoice(SellingController): """Set against account for debit to account""" against_acc = [] for d in self.get('items'): - if d.income_account not in against_acc: + if d.income_account and d.income_account not in against_acc: against_acc.append(d.income_account) self.against_income_account = ','.join(against_acc) From b3dec74c6a0faa1f671512e8991fc2c96fd78bce Mon Sep 17 00:00:00 2001 From: Anurag Mishra Date: Wed, 26 Jun 2019 13:31:09 +0530 Subject: [PATCH 074/115] fix: removed unused function --- .../doctype/leave_application/leave_application.py | 13 ------------- .../employee_leave_balance.py | 2 +- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index 88b8f77b2e0..ef8221108cf 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -400,19 +400,6 @@ def get_leave_balance_on(employee, leave_type, date, allocation_records=None, do return flt(allocation.total_leaves_allocated) - (flt(leaves_taken) + flt(leaves_encashed)) -def get_total_allocated_leaves(employee, leave_type, date): - filters= { - 'from_date': ['<=', date], - 'to_date': ['>=', date], - 'docstatus': 1, - 'leave_type': leave_type, - 'employee': employee - } - - leave_allocation_records = frappe.db.get_all('Leave Allocation', filters=filters, fields=['total_leaves_allocated']) - - return flt(leave_allocation_records[0]['total_leaves_allocated']) if leave_allocation_records else flt(0) - def get_leaves_for_period(employee, leave_type, from_date, to_date, status, docname=None): leave_applications = frappe.db.sql(""" select name, employee, leave_type, from_date, to_date, total_leave_days diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py index 5d781dba94f..18431768528 100644 --- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py +++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _ from erpnext.hr.doctype.leave_application.leave_application \ - import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period, get_total_allocated_leaves + import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period def execute(filters=None): From f269b66f39d9963a20f5e624a850f3424e9424e1 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 26 Jun 2019 13:39:52 +0530 Subject: [PATCH 075/115] fix: returned qty issue while making sales invoice from dn if same item added multiple times (#18074) --- erpnext/stock/doctype/delivery_note/delivery_note.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 23f7ed1889d..04f0c1c9a1e 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -443,7 +443,12 @@ def make_sales_invoice(source_name, target_doc=None): def get_pending_qty(item_row): pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0) - returned_qty = flt(returned_qty_map.get(item_row.item_code, 0)) + + returned_qty = 0 + if returned_qty_map.get(item_row.item_code) > 0: + returned_qty = flt(returned_qty_map.get(item_row.item_code, 0)) + returned_qty_map[item_row.item_code] -= pending_qty + if returned_qty: if returned_qty >= pending_qty: pending_qty = 0 @@ -451,6 +456,7 @@ def make_sales_invoice(source_name, target_doc=None): else: pending_qty -= returned_qty returned_qty = 0 + return pending_qty, returned_qty doc = get_mapped_doc("Delivery Note", source_name, { From e2ddc82637d433ab03ced7e9ce8cc756437e2d20 Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Wed, 26 Jun 2019 16:13:52 +0550 Subject: [PATCH 076/115] bumped to version 11.1.40 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index a06efa0ff75..8c18da086ec 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__ = '11.1.40' def get_default_company(user=None): '''Get default company for user''' From beca677276e0b5b143cd6d1d08efa8529663f60c Mon Sep 17 00:00:00 2001 From: karthikeyan5 Date: Wed, 26 Jun 2019 17:11:14 +0530 Subject: [PATCH 077/115] fix(item): fixing broken patch item_barcode_childtable_migrate --- erpnext/patches/v10_0/item_barcode_childtable_migrate.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/patches/v10_0/item_barcode_childtable_migrate.py b/erpnext/patches/v10_0/item_barcode_childtable_migrate.py index c16f3554b30..ec9c6c3b760 100644 --- a/erpnext/patches/v10_0/item_barcode_childtable_migrate.py +++ b/erpnext/patches/v10_0/item_barcode_childtable_migrate.py @@ -7,8 +7,9 @@ import frappe def execute(): - if frappe.get_all("Item Barcode", limit=1): return frappe.reload_doc("stock", "doctype", "item_barcode") + if frappe.get_all("Item Barcode", limit=1): return + if "barcode" not in frappe.db.get_table_columns("Item"): return items_barcode = frappe.db.sql("select name, barcode from tabItem where barcode is not null", as_dict=True) frappe.reload_doc("stock", "doctype", "item") From 23251d9e4d29e102ba3ad2c6fc983ae5c89fe9a6 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Wed, 26 Jun 2019 17:48:50 +0600 Subject: [PATCH 078/115] bumped to version 11.1.41 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 8c18da086ec..ce107235f50 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.40' +__version__ = '11.1.41' def get_default_company(user=None): '''Get default company for user''' From 4e9f1a08fe2369da807d2acbc92b688a9b477bc2 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 26 Jun 2019 21:57:03 +0530 Subject: [PATCH 079/115] fix: dn test cases --- .../stock/doctype/delivery_note/delivery_note.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 04f0c1c9a1e..6cd329ef2bc 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -414,6 +414,8 @@ def get_returned_qty_map(delivery_note): @frappe.whitelist() def make_sales_invoice(source_name, target_doc=None): doc = frappe.get_doc('Delivery Note', source_name) + + to_make_invoice_qty_map = {} returned_qty_map = get_returned_qty_map(source_name) invoiced_qty_map = get_invoiced_qty_map(source_name) @@ -434,8 +436,7 @@ def make_sales_invoice(source_name, target_doc=None): target.update(get_fetch_values("Sales Invoice", 'company_address', target.company_address)) def update_item(source_doc, target_doc, source_parent): - target_doc.qty, returned_qty = get_pending_qty(source_doc) - returned_qty_map[source_doc.item_code] = returned_qty + target_doc.qty = to_make_invoice_qty_map[source_doc.name] if source_doc.serial_no and source_parent.per_billed > 0: target_doc.serial_no = get_delivery_note_serial_no(source_doc.item_code, @@ -445,7 +446,7 @@ def make_sales_invoice(source_name, target_doc=None): pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0) returned_qty = 0 - if returned_qty_map.get(item_row.item_code) > 0: + if returned_qty_map.get(item_row.item_code, 0) > 0: returned_qty = flt(returned_qty_map.get(item_row.item_code, 0)) returned_qty_map[item_row.item_code] -= pending_qty @@ -457,7 +458,9 @@ def make_sales_invoice(source_name, target_doc=None): pending_qty -= returned_qty returned_qty = 0 - return pending_qty, returned_qty + to_make_invoice_qty_map[item_row.name] = pending_qty + + return pending_qty doc = get_mapped_doc("Delivery Note", source_name, { "Delivery Note": { @@ -477,7 +480,7 @@ def make_sales_invoice(source_name, target_doc=None): "cost_center": "cost_center" }, "postprocess": update_item, - "filter": lambda d: get_pending_qty(d)[0] <= 0 if not doc.get("is_return") else get_pending_qty(d)[0] > 0 + "filter": lambda d: get_pending_qty(d) <= 0 if not doc.get("is_return") else get_pending_qty(d) > 0 }, "Sales Taxes and Charges": { "doctype": "Sales Taxes and Charges", From c2e5e569a0d63b5542d0d5326947bec120e17657 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 27 Jun 2019 11:15:18 +0530 Subject: [PATCH 080/115] fix: same taxes adding multiple times in pos --- erpnext/public/js/controllers/transaction.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index d0ebce8c429..79119b262ca 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1290,10 +1290,13 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }, callback: function(r) { if(!r.exc) { - for (let tax of r.message) { - me.frm.add_child("taxes", tax); + me.frm.set_value("taxes", r.message); + + if(me.frm.doc.shipping_rule) { + me.frm.script_manager.trigger("shipping_rule"); + } else { + me.calculate_taxes_and_totals(); } - me.calculate_taxes_and_totals(); } } }); From e68d4c897bc347c84183b4455937d168be435071 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 27 Jun 2019 11:41:17 +0530 Subject: [PATCH 081/115] fix: open department in tree view via awesome bar --- erpnext/public/js/conf.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/conf.js b/erpnext/public/js/conf.js index 477781bc805..b94e9183bd8 100644 --- a/erpnext/public/js/conf.js +++ b/erpnext/public/js/conf.js @@ -41,7 +41,8 @@ $.extend(frappe.create_routes, { "Item Group": "Tree/Item Group", "Sales Person": "Tree/Sales Person", "Account": "Tree/Account", - "Cost Center": "Tree/Cost Center" + "Cost Center": "Tree/Cost Center", + "Department": "Tree/Department", }); // preferred modules for breadcrumbs From 415c90d9d0b5effc56b38c60aa80defd87b86b7c Mon Sep 17 00:00:00 2001 From: Saurabh Date: Thu, 27 Jun 2019 13:21:14 +0600 Subject: [PATCH 082/115] bumped to version 11.1.42 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index ce107235f50..8c70de3cc19 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.41' +__version__ = '11.1.42' def get_default_company(user=None): '''Get default company for user''' From b059c6f630f175bc2150d66ecb4b50898cc5a31a Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 28 Jun 2019 12:36:27 +0530 Subject: [PATCH 083/115] fix: Fixes related to customer/lead merging (#18075) --- erpnext/controllers/selling_controller.py | 21 +++++++++++++++---- erpnext/controllers/tests/test_mapper.py | 2 +- .../crm/doctype/opportunity/opportunity.py | 4 ++-- erpnext/demo/user/sales.py | 2 +- .../v11_1/set_missing_title_for_quotation.py | 1 + .../setup_wizard/operations/sample_data.py | 2 +- erpnext/templates/utils.py | 6 +++--- 7 files changed, 26 insertions(+), 12 deletions(-) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index a9883017cfa..f16d40c4ea8 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -55,14 +55,28 @@ class SellingController(StockController): self.set_price_list_and_item_details(for_validate=for_validate) def set_missing_lead_customer_details(self): + customer, lead = None, None if getattr(self, "customer", None): + customer = self.customer + elif self.doctype == "Opportunity" and self.party_name: + if self.opportunity_from == "Customer": + customer = self.party_name + else: + lead = self.party_name + elif self.doctype == "Quotation" and self.party_name: + if self.quotation_to == "Customer": + customer = self.party_name + else: + lead = self.party_name + + if customer: from erpnext.accounts.party import _get_party_details fetch_payment_terms_template = False if (self.get("__islocal") or self.company != frappe.db.get_value(self.doctype, self.name, 'company')): fetch_payment_terms_template = True - party_details = _get_party_details(self.customer, + party_details = _get_party_details(customer, ignore_permissions=self.flags.ignore_permissions, doctype=self.doctype, company=self.company, fetch_payment_terms_template=fetch_payment_terms_template, @@ -71,10 +85,9 @@ class SellingController(StockController): party_details.pop("sales_team") self.update_if_missing(party_details) - elif getattr(self, "lead", None): + elif lead: from erpnext.crm.doctype.lead.lead import get_lead_details - self.update_if_missing(get_lead_details( - self.lead, + self.update_if_missing(get_lead_details(lead, posting_date=self.get('transaction_date') or self.get('posting_date'), company=self.company)) diff --git a/erpnext/controllers/tests/test_mapper.py b/erpnext/controllers/tests/test_mapper.py index 14738c5ff2b..d02308d8f21 100644 --- a/erpnext/controllers/tests/test_mapper.py +++ b/erpnext/controllers/tests/test_mapper.py @@ -43,7 +43,7 @@ class TestMapper(unittest.TestCase): qtn = frappe.get_doc({ "doctype": "Quotation", "quotation_to": "Customer", - "customer": customer, + "party_name": customer, "order_type": "Sales", "transaction_date" : nowdate(), "valid_till" : add_months(nowdate(), 1) diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index dad249213c7..973b3412b8b 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -320,11 +320,11 @@ def make_opportunity_from_communication(communication, ignore_communication_link if not lead: lead = make_lead_from_communication(communication, ignore_communication_links=True) - enquiry_from = "Lead" + opportunity_from = "Lead" opportunity = frappe.get_doc({ "doctype": "Opportunity", - "enquiry_from": enquiry_from, + "opportunity_from": opportunity_from, "lead": lead }).insert(ignore_permissions=True) diff --git a/erpnext/demo/user/sales.py b/erpnext/demo/user/sales.py index 3809c1f0924..d5b0133f21b 100644 --- a/erpnext/demo/user/sales.py +++ b/erpnext/demo/user/sales.py @@ -99,7 +99,7 @@ def make_quotation(domain): "creation": frappe.flags.current_date, "doctype": "Quotation", "quotation_to": "Customer", - "customer": customer, + "party_name": customer, "currency": party_account_currency or company_currency, "conversion_rate": exchange_rate, "order_type": "Sales", diff --git a/erpnext/patches/v11_1/set_missing_title_for_quotation.py b/erpnext/patches/v11_1/set_missing_title_for_quotation.py index e86b8320c31..e2ef3433d3e 100644 --- a/erpnext/patches/v11_1/set_missing_title_for_quotation.py +++ b/erpnext/patches/v11_1/set_missing_title_for_quotation.py @@ -1,6 +1,7 @@ import frappe def execute(): + frappe.reload_doctype("Quotation") # update customer_name from Customer document if quotation_to is set to Customer frappe.db.sql(''' update tabQuotation, tabCustomer diff --git a/erpnext/setup/setup_wizard/operations/sample_data.py b/erpnext/setup/setup_wizard/operations/sample_data.py index e21c9bd1089..64c669363d3 100644 --- a/erpnext/setup/setup_wizard/operations/sample_data.py +++ b/erpnext/setup/setup_wizard/operations/sample_data.py @@ -34,7 +34,7 @@ def make_opportunity(items, customer): b = frappe.get_doc({ "doctype": "Opportunity", "opportunity_from": "Customer", - "customer": customer, + "party_name": customer, "opportunity_type": _("Sales"), "with_items": 1 }) diff --git a/erpnext/templates/utils.py b/erpnext/templates/utils.py index 97e2a7f7235..743657de322 100644 --- a/erpnext/templates/utils.py +++ b/erpnext/templates/utils.py @@ -36,11 +36,11 @@ def send_message(subject="Website Query", message="", sender="", status="Open"): )) if customer: - opportunity.customer = customer[0][0] + opportunity.party_name = customer[0][0] elif lead: - opportunity.lead = lead + opportunity.party_name = lead else: - opportunity.lead = new_lead.name + opportunity.party_name = new_lead.name opportunity.insert(ignore_permissions=True) From c82253e4794a513399522d68a2a5d10625c8339f Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 28 Jun 2019 12:41:16 +0530 Subject: [PATCH 084/115] fix: not able to make salary slip based on timesheet (#18087) --- erpnext/hr/doctype/salary_slip/salary_slip.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index c73c708b204..90391037896 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -281,7 +281,9 @@ class SalarySlip(TransactionBase): wages_row = { "salary_component": salary_component, "abbr": frappe.db.get_value("Salary Component", salary_component, "salary_component_abbr"), - "amount": self.hour_rate * self.total_working_hours + "amount": self.hour_rate * self.total_working_hours, + "default_amount": 0.0, + "additional_amount": 0.0 } doc.append('earnings', wages_row) From fdd1422d31dcfdd7170ad80b8529f5d0cde2b84c Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Fri, 28 Jun 2019 14:09:23 +0530 Subject: [PATCH 085/115] fix: Usability fixes to Serial No and batch selector (#18070) * fix: Usability fixes to Serial No and batch selector * fix: Codacy * Update sales_common.js --- .../js/utils/serial_no_batch_selector.js | 20 +++++++++++++++++-- erpnext/selling/sales_common.js | 18 ++++++++++++----- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 0202bbb872a..576ae0fbde1 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -45,6 +45,13 @@ erpnext.SerialNoBatchSelector = Class.extend({ label: __(me.warehouse_details.type), default: me.warehouse_details.name, onchange: function(e) { + + if(me.has_batch) { + fields = fields.concat(me.get_batch_fields()); + } else { + fields = fields.concat(me.get_serial_no_fields()); + } + me.warehouse_details.name = this.get_value(); var batches = this.layout.fields_dict.batches; if(batches) { @@ -232,6 +239,15 @@ erpnext.SerialNoBatchSelector = Class.extend({ get_batch_fields: function() { var me = this; + + let filters = { + item_code: me.item_code + } + + if (me.warehouse || me.warehouse_details.name) { + filters['warehouse'] = me.warehouse || me.warehouse_details.name; + } + return [ { fieldtype: 'Section Break', label: __('Batches') }, { @@ -246,8 +262,8 @@ erpnext.SerialNoBatchSelector = Class.extend({ 'in_list_view': 1, get_query: function () { return { - filters: { item: me.item_code }, - query: 'erpnext.controllers.queries.get_batch_numbers' + filters: filters, + query: 'erpnext.controllers.queries.get_batch_no' }; }, change: function () { diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index c431df403aa..b1b64a3e4ec 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -184,7 +184,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.calculate_incentive(sales_person); refresh_field(["allocated_percentage", "allocated_amount", "commission_rate","incentives"], sales_person.name, sales_person.parentfield); - } + } }, sales_person: function(doc, cdt, cdn) { @@ -215,6 +215,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ }, callback:function(r){ if (in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) { + + if (doc.doctype === 'Sales Invoice' && (!doc.update_stock)) return; + me.set_batch_number(cdt, cdn); me.batch_no(doc, cdt, cdn); } @@ -358,13 +361,18 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this._super(doc, cdt, cdn, dont_fetch_price_list_rate); if(frappe.meta.get_docfield(cdt, "stock_qty", cdn) && in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) { - this.set_batch_number(cdt, cdn); - } + if (doc.doctype === 'Sales Invoice' && (!doc.update_stock)) return; + this.set_batch_number(cdt, cdn); + } }, qty: function(doc, cdt, cdn) { this._super(doc, cdt, cdn); - this.set_batch_number(cdt, cdn); + + if(in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) { + if (doc.doctype === 'Sales Invoice' && (!doc.update_stock)) return; + this.set_batch_number(cdt, cdn); + } }, /* Determine appropriate batch number and set it in the form. @@ -396,7 +404,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ if (doc.auto_repeat) { frappe.call({ method:"frappe.desk.doctype.auto_repeat.auto_repeat.update_reference", - args:{ + args:{ docname: doc.auto_repeat, reference:doc.name }, From 5b5156356a8662819c9180a2cca6dd1f8b2847c3 Mon Sep 17 00:00:00 2001 From: Himanshu Date: Fri, 28 Jun 2019 14:12:40 +0530 Subject: [PATCH 086/115] fix(Utils): Do not add duplicate item to items (#17895) * fix: do not add duplicate item to items * fix: compare warehouses, batch and qty for an item * fix: code fixes * Update utils.js * fix: check required_date and delivery_date * Update utils.js * Update utils.js * Update utils.js * fix: mixed spaces and tabs --- erpnext/public/js/utils.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 2dd65fec170..37735646fb3 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -587,6 +587,7 @@ erpnext.utils.map_current_doc = function(opts) { if(!r.exc) { var doc = frappe.model.sync(r.message); cur_frm.dirty(); + erpnext.utils.clear_duplicates(); cur_frm.refresh(); } } @@ -617,6 +618,27 @@ erpnext.utils.map_current_doc = function(opts) { } } +erpnext.utils.clear_duplicates = function() { + const unique_items = new Map(); + /* + Create a Map of items with + item_code => [qty, warehouse, batch_no] + */ + let items = []; + + for (let item of cur_frm.doc.items) { + if (!(unique_items.has(item.item_code) && unique_items.get(item.item_code)[0] === item.qty && + unique_items.get(item.item_code)[1] === item.warehouse && unique_items.get(item.item_code)[2] === item.batch_no && + unique_items.get(item.item_code)[3] === item.delivery_date && unique_items.get(item.item_code)[4] === item.required_date && + unique_items.get(item.item_code)[5] === item.rate)) { + + unique_items.set(item.item_code, [item.qty, item.warehouse, item.batch_no, item.delivery_date, item.required_date, item.rate]); + items.push(item); + } + } + cur_frm.doc.items = items; +} + frappe.form.link_formatters['Item'] = function(value, doc) { if(doc && doc.item_name && doc.item_name !== value) { return value? value + ': ' + doc.item_name: doc.item_name; From 69051c41978afe3b8614598a58fcad0665ebbe47 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 28 Jun 2019 14:36:53 +0530 Subject: [PATCH 087/115] fix(buying): Translate label for "Supplier Addresses And Contacts" Report --- erpnext/config/buying.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/config/buying.py b/erpnext/config/buying.py index e99b1d88aa5..1db5233b026 100644 --- a/erpnext/config/buying.py +++ b/erpnext/config/buying.py @@ -199,7 +199,7 @@ def get_data(): "type": "report", "is_query_report": True, "name": "Address And Contacts", - "label": "Supplier Addresses And Contacts", + "label": _("Supplier Addresses And Contacts"), "doctype": "Address", "route_options": { "party_type": "Supplier" From dfe0a9002ac9daa42fa40a6ee77d3d39ca6c5db5 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Fri, 28 Jun 2019 19:22:51 +0530 Subject: [PATCH 088/115] fix: mapped doc --- erpnext/public/js/utils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 37735646fb3..4e589dadb66 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -619,6 +619,7 @@ erpnext.utils.map_current_doc = function(opts) { } erpnext.utils.clear_duplicates = function() { + if(!cur_frm.doc.items) return; const unique_items = new Map(); /* Create a Map of items with From 30c9c56d6cf18a5a440cc8f923ce72bb1b96971b Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Fri, 28 Jun 2019 19:35:05 +0530 Subject: [PATCH 089/115] fix: add a more descriptive message when no records are found (#18083) * fix: add a more descriptive message when no records are found * fix: translation by passing string to translation function --- .../exchange_rate_revaluation.js | 4 +- .../exchange_rate_revaluation.py | 20 +- .../exchange_rate_revaluation_account.json | 874 +++++++++--------- 3 files changed, 461 insertions(+), 437 deletions(-) diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js index 779cd6197e9..cb3aef72c32 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js @@ -39,8 +39,6 @@ frappe.ui.form.on('Exchange Rate Revaluation', { }); frm.events.get_total_gain_loss(frm); refresh_field("accounts"); - } else { - frappe.msgprint(__("No records found")); } } }); @@ -54,7 +52,7 @@ frappe.ui.form.on('Exchange Rate Revaluation', { d.gain_loss = flt(d.new_balance_in_base_currency, precision("new_balance_in_base_currency", d)) - flt(d.balance_in_base_currency, precision("balance_in_base_currency", d)); total_gain_loss += flt(d.gain_loss, precision("gain_loss", d)); }); - + frm.set_value("total_gain_loss", flt(total_gain_loss, precision("total_gain_loss"))); frm.refresh_fields(); }, diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py index cdfe34beadb..9594706d0f6 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py @@ -22,7 +22,7 @@ class ExchangeRateRevaluation(Document): - flt(d.balance_in_base_currency, d.precision("balance_in_base_currency")) total_gain_loss += flt(d.gain_loss, d.precision("gain_loss")) self.total_gain_loss = flt(total_gain_loss, self.precision("total_gain_loss")) - + def validate_mandatory(self): if not (self.company and self.posting_date): frappe.throw(_("Please select Company and Posting Date to getting entries")) @@ -33,8 +33,9 @@ class ExchangeRateRevaluation(Document): company_currency = erpnext.get_company_currency(self.company) precision = get_field_precision(frappe.get_meta("Exchange Rate Revaluation Account") .get_field("new_balance_in_base_currency"), company_currency) - for d in self.get_accounts_from_gle(): - + + account_details = self.get_accounts_from_gle() + for d in account_details: current_exchange_rate = d.balance / d.balance_in_account_currency \ if d.balance_in_account_currency else 0 new_exchange_rate = get_exchange_rate(d.account_currency, company_currency, self.posting_date) @@ -52,6 +53,10 @@ class ExchangeRateRevaluation(Document): "new_exchange_rate": new_exchange_rate, "new_balance_in_base_currency": new_balance_in_base_currency }) + + if not accounts: + self.throw_invalid_response_message(account_details) + return accounts def get_accounts_from_gle(self): @@ -83,11 +88,18 @@ class ExchangeRateRevaluation(Document): return account_details + def throw_invalid_response_message(self, account_details): + if account_details: + message = _("No outstanding invoices require exchange rate revaluation") + else: + message = _("No outstanding invoices found") + frappe.msgprint(message) + def make_jv_entry(self): if self.total_gain_loss == 0: return - unrealized_exchange_gain_loss_account = frappe.get_cached_value('Company', self.company, + unrealized_exchange_gain_loss_account = frappe.get_cached_value('Company', self.company, "unrealized_exchange_gain_loss_account") if not unrealized_exchange_gain_loss_account: frappe.throw(_("Please set Unrealized Exchange Gain/Loss Account in Company {0}") diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.json b/erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.json index 98ecd486ca5..30ff9ebed5b 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.json +++ b/erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.json @@ -1,461 +1,475 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2018-04-13 18:30:06.110433", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 0, + "creation": "2018-04-13 18:30:06.110433", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "account", - "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": "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": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 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": "account", + "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": "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": 1, + "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, - "fieldname": "party_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": "Party Type", - "length": 0, - "no_copy": 0, - "options": "DocType", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "party_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": "Party Type", + "length": 0, + "no_copy": 0, + "options": "DocType", + "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, - "fieldname": "party", - "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": "Party", - "length": 0, - "no_copy": 0, - "options": "party_type", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "party", + "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": "Party", + "length": 0, + "no_copy": 0, + "options": "party_type", + "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, - "fieldname": "column_break_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, - "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, + "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_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, + "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, - "fieldname": "account_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": "Account Currency", - "length": 0, - "no_copy": 0, - "options": "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "account_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": "Account Currency", + "length": 0, + "no_copy": 0, + "options": "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 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "balance_in_account_currency", - "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": "Balance In Account Currency", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "balance_in_account_currency", + "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": "Balance In Account Currency", + "length": 0, + "no_copy": 0, + "options": "account_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 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "balances", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "balances", + "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 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "current_exchange_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": "Current Exchange Rate", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "current_exchange_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": "Current Exchange Rate", + "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_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "balance_in_base_currency", - "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": "Balance In Base Currency", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "balance_in_base_currency", + "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": "Balance In Base Currency", + "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_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_9", - "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, + "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_9", + "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 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "new_exchange_rate", - "fieldtype": "Float", - "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": "New Exchange Rate", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "new_exchange_rate", + "fieldtype": "Float", + "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": "New Exchange Rate", + "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 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "new_balance_in_base_currency", - "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": "New Balance In Base Currency", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "new_balance_in_base_currency", + "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": "New Balance In Base Currency", + "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_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "gain_loss", - "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": "Gain/Loss", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "gain_loss", + "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": "Gain/Loss", + "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 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2019-01-07 16:52:07.327930", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Exchange Rate Revaluation Account", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "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, + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "max_attachments": 0, + "modified": "2019-06-26 18:57:51.762345", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Exchange Rate Revaluation Account", + "name_case": "", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "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 } \ No newline at end of file From 2a0be68cb37df312c55fe2c9070b8fe5077bab15 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 28 Jun 2019 17:18:03 +0530 Subject: [PATCH 090/115] fix: incorrect value booked in the accumulated depreciation account on sell of the asset --- .../doctype/sales_invoice/sales_invoice.py | 9 +- .../sales_invoice_item.json | 121 +++++++++++++++++- erpnext/assets/doctype/asset/depreciation.py | 36 ++++-- erpnext/assets/doctype/asset/test_asset.py | 9 +- 4 files changed, 155 insertions(+), 20 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index e06db8f4bc6..5b61fbfa138 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -770,7 +770,14 @@ class SalesInvoice(SellingController): if item.is_fixed_asset: asset = frappe.get_doc("Asset", item.asset) - fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset, item.base_net_amount) + if (len(asset.finance_books) > 1 and not item.finance_book + and asset.finance_books[0].finance_book): + frappe.throw(_("Select finance book for the item {0} at row {1}") + .format(item.item_code, item.idx)) + + fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset, + item.base_net_amount, item.finance_book) + for gle in fixed_asset_gl_entries: gle["against"] = self.customer gl_entries.append(self.get_gl_dict(gle)) 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 a95f3146616..5e712d1846e 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -21,6 +21,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "barcode", "fieldtype": "Data", "hidden": 0, @@ -52,6 +53,7 @@ "bold": 1, "collapsible": 0, "columns": 4, + "fetch_if_empty": 0, "fieldname": "item_code", "fieldtype": "Link", "hidden": 0, @@ -86,6 +88,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "col_break1", "fieldtype": "Column Break", "hidden": 0, @@ -116,6 +119,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "item_name", "fieldtype": "Data", "hidden": 0, @@ -149,6 +153,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "customer_item_code", "fieldtype": "Data", "hidden": 1, @@ -180,6 +185,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_6", "fieldtype": "Section Break", "hidden": 0, @@ -212,6 +218,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "description", "fieldtype": "Text Editor", "hidden": 0, @@ -247,6 +254,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_8", "fieldtype": "Column Break", "hidden": 0, @@ -278,6 +286,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "image_view", "fieldtype": "Image", "hidden": 0, @@ -311,6 +320,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -343,6 +353,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "quantity_and_rate", "fieldtype": "Section Break", "hidden": 0, @@ -374,6 +385,7 @@ "bold": 1, "collapsible": 0, "columns": 2, + "fetch_if_empty": 0, "fieldname": "qty", "fieldtype": "Float", "hidden": 0, @@ -407,6 +419,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "stock_uom", "fieldtype": "Link", "hidden": 0, @@ -439,6 +452,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "col_break2", "fieldtype": "Column Break", "hidden": 0, @@ -469,6 +483,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "uom", "fieldtype": "Link", "hidden": 0, @@ -502,6 +517,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "conversion_factor", "fieldtype": "Float", "hidden": 0, @@ -534,6 +550,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "stock_qty", "fieldtype": "Float", "hidden": 0, @@ -566,6 +583,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_17", "fieldtype": "Section Break", "hidden": 0, @@ -597,6 +615,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "price_list_rate", "fieldtype": "Currency", "hidden": 0, @@ -631,6 +650,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_price_list_rate", "fieldtype": "Currency", "hidden": 0, @@ -665,6 +685,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "discount_and_margin", "fieldtype": "Section Break", "hidden": 0, @@ -698,6 +719,7 @@ "collapsible": 0, "columns": 0, "depends_on": "price_list_rate", + "fetch_if_empty": 0, "fieldname": "margin_type", "fieldtype": "Select", "hidden": 0, @@ -732,6 +754,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.margin_type && doc.price_list_rate", + "fetch_if_empty": 0, "fieldname": "margin_rate_or_amount", "fieldtype": "Float", "hidden": 0, @@ -765,6 +788,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount", + "fetch_if_empty": 0, "fieldname": "rate_with_margin", "fieldtype": "Currency", "hidden": 0, @@ -798,6 +822,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_19", "fieldtype": "Column Break", "hidden": 0, @@ -830,6 +855,7 @@ "collapsible": 0, "columns": 0, "depends_on": "price_list_rate", + "fetch_if_empty": 0, "fieldname": "discount_percentage", "fieldtype": "Percent", "hidden": 0, @@ -865,6 +891,7 @@ "collapsible": 0, "columns": 0, "depends_on": "discount_percentage", + "fetch_if_empty": 0, "fieldname": "discount_amount", "fieldtype": "Currency", "hidden": 0, @@ -899,6 +926,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount", + "fetch_if_empty": 0, "fieldname": "base_rate_with_margin", "fieldtype": "Currency", "hidden": 0, @@ -932,6 +960,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break1", "fieldtype": "Section Break", "hidden": 0, @@ -962,6 +991,7 @@ "bold": 1, "collapsible": 0, "columns": 2, + "fetch_if_empty": 0, "fieldname": "rate", "fieldtype": "Currency", "hidden": 0, @@ -996,6 +1026,7 @@ "bold": 0, "collapsible": 0, "columns": 2, + "fetch_if_empty": 0, "fieldname": "amount", "fieldtype": "Currency", "hidden": 0, @@ -1030,6 +1061,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "col_break3", "fieldtype": "Column Break", "hidden": 0, @@ -1060,6 +1092,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_rate", "fieldtype": "Currency", "hidden": 0, @@ -1094,6 +1127,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_amount", "fieldtype": "Currency", "hidden": 0, @@ -1128,6 +1162,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "pricing_rule", "fieldtype": "Link", "hidden": 0, @@ -1160,6 +1195,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_21", "fieldtype": "Section Break", "hidden": 0, @@ -1191,6 +1227,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "net_rate", "fieldtype": "Currency", "hidden": 0, @@ -1224,6 +1261,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "net_amount", "fieldtype": "Currency", "hidden": 0, @@ -1257,6 +1295,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_24", "fieldtype": "Column Break", "hidden": 0, @@ -1288,6 +1327,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_net_rate", "fieldtype": "Currency", "hidden": 0, @@ -1321,6 +1361,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_net_amount", "fieldtype": "Currency", "hidden": 0, @@ -1355,6 +1396,7 @@ "collapsible": 1, "collapsible_depends_on": "eval:doc.delivered_by_supplier==1", "columns": 0, + "fetch_if_empty": 0, "fieldname": "drop_ship", "fieldtype": "Section Break", "hidden": 0, @@ -1387,6 +1429,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "delivered_by_supplier", "fieldtype": "Check", "hidden": 0, @@ -1419,6 +1462,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "accounting", "fieldtype": "Section Break", "hidden": 0, @@ -1450,6 +1494,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "income_account", "fieldtype": "Link", "hidden": 0, @@ -1486,6 +1531,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "expense_account", "fieldtype": "Link", "hidden": 0, @@ -1519,6 +1565,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "col_break4", "fieldtype": "Column Break", "hidden": 0, @@ -1550,6 +1597,7 @@ "collapsible": 0, "columns": 0, "default": ":Company", + "fetch_if_empty": 0, "fieldname": "cost_center", "fieldtype": "Link", "hidden": 0, @@ -1586,6 +1634,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "deferred_revenue", "fieldtype": "Section Break", "hidden": 0, @@ -1619,6 +1668,7 @@ "collapsible": 0, "columns": 0, "depends_on": "enable_deferred_revenue", + "fetch_if_empty": 0, "fieldname": "deferred_revenue_account", "fieldtype": "Link", "hidden": 0, @@ -1653,6 +1703,7 @@ "collapsible": 0, "columns": 0, "depends_on": "enable_deferred_revenue", + "fetch_if_empty": 0, "fieldname": "service_stop_date", "fieldtype": "Date", "hidden": 0, @@ -1686,6 +1737,7 @@ "collapsible": 0, "columns": 0, "default": "0", + "fetch_if_empty": 0, "fieldname": "enable_deferred_revenue", "fieldtype": "Check", "hidden": 0, @@ -1718,6 +1770,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_50", "fieldtype": "Column Break", "hidden": 0, @@ -1750,6 +1803,7 @@ "collapsible": 0, "columns": 0, "depends_on": "enable_deferred_revenue", + "fetch_if_empty": 0, "fieldname": "service_start_date", "fieldtype": "Date", "hidden": 0, @@ -1783,6 +1837,7 @@ "collapsible": 0, "columns": 0, "depends_on": "enable_deferred_revenue", + "fetch_if_empty": 0, "fieldname": "service_end_date", "fieldtype": "Date", "hidden": 0, @@ -1815,6 +1870,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_18", "fieldtype": "Section Break", "hidden": 0, @@ -1847,6 +1903,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "weight_per_unit", "fieldtype": "Float", "hidden": 0, @@ -1880,6 +1937,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_weight", "fieldtype": "Float", "hidden": 0, @@ -1912,6 +1970,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_21", "fieldtype": "Column Break", "hidden": 0, @@ -1943,6 +2002,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "weight_uom", "fieldtype": "Link", "hidden": 0, @@ -1978,6 +2038,7 @@ "collapsible_depends_on": "eval:doc.serial_no || doc.batch_no", "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "warehouse_and_reference", "fieldtype": "Section Break", "hidden": 0, @@ -2009,6 +2070,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "warehouse", "fieldtype": "Link", "hidden": 0, @@ -2043,6 +2105,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "target_warehouse", "fieldtype": "Link", "hidden": 1, @@ -2077,6 +2140,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "quality_inspection", "fieldtype": "Link", "hidden": 0, @@ -2110,6 +2174,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "batch_no", "fieldtype": "Link", "hidden": 0, @@ -2142,6 +2207,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "col_break5", "fieldtype": "Column Break", "hidden": 0, @@ -2172,6 +2238,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "allow_zero_valuation_rate", "fieldtype": "Check", "hidden": 0, @@ -2204,6 +2271,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "serial_no", "fieldtype": "Small Text", "hidden": 0, @@ -2238,6 +2306,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "item_group", "fieldtype": "Link", "hidden": 1, @@ -2272,6 +2341,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "brand", "fieldtype": "Data", "hidden": 1, @@ -2305,6 +2375,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "item_tax_rate", "fieldtype": "Small Text", "hidden": 1, @@ -2338,6 +2409,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "actual_batch_qty", "fieldtype": "Float", "hidden": 0, @@ -2372,6 +2444,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "actual_qty", "fieldtype": "Float", "hidden": 0, @@ -2405,6 +2478,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "edit_references", "fieldtype": "Section Break", "hidden": 0, @@ -2437,6 +2511,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sales_order", "fieldtype": "Link", "hidden": 0, @@ -2471,6 +2546,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "so_detail", "fieldtype": "Data", "hidden": 1, @@ -2504,6 +2580,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_74", "fieldtype": "Column Break", "hidden": 0, @@ -2535,6 +2612,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "delivery_note", "fieldtype": "Link", "hidden": 0, @@ -2569,6 +2647,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "dn_detail", "fieldtype": "Data", "hidden": 1, @@ -2602,6 +2681,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "delivered_qty", "fieldtype": "Float", "hidden": 0, @@ -2635,6 +2715,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "is_fixed_asset", "fieldtype": "Check", "hidden": 1, @@ -2667,6 +2748,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "asset", "fieldtype": "Link", "hidden": 0, @@ -2700,6 +2782,42 @@ "bold": 0, "collapsible": 0, "columns": 0, + "depends_on": "asset", + "fetch_if_empty": 0, + "fieldname": "finance_book", + "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": "Finance Book", + "length": 0, + "no_copy": 0, + "options": "Finance Book", + "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, + "fetch_if_empty": 0, "fieldname": "section_break_54", "fieldtype": "Section Break", "hidden": 0, @@ -2731,6 +2849,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "page_break", "fieldtype": "Check", "hidden": 0, @@ -2766,7 +2885,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2019-02-18 18:59:52.223628", + "modified": "2019-06-28 17:04:25.870346", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Item", diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 797075b8873..61108ec4a37 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -36,7 +36,7 @@ def make_depreciation_entry(asset_name, date=None): fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \ get_depreciation_accounts(asset) - depreciation_cost_center, depreciation_series = frappe.get_cached_value('Company', asset.company, + depreciation_cost_center, depreciation_series = frappe.get_cached_value('Company', asset.company, ["depreciation_cost_center", "series_for_depreciation_entry"]) depreciation_cost_center = asset.cost_center or depreciation_cost_center @@ -70,7 +70,7 @@ def make_depreciation_entry(asset_name, date=None): je.submit() d.db_set("journal_entry", je.name) - + idx = cint(d.finance_book_id) finance_books = asset.get('finance_books')[idx - 1] finance_books.value_after_depreciation -= d.depreciation_amount @@ -88,15 +88,15 @@ def get_depreciation_accounts(asset): fieldname = ['fixed_asset_account', 'accumulated_depreciation_account', 'depreciation_expense_account'], as_dict=1) - if accounts: + if accounts: fixed_asset_account = accounts.fixed_asset_account accumulated_depreciation_account = accounts.accumulated_depreciation_account depreciation_expense_account = accounts.depreciation_expense_account - + if not accumulated_depreciation_account or not depreciation_expense_account: - accounts = frappe.get_cached_value('Company', asset.company, + accounts = frappe.get_cached_value('Company', asset.company, ["accumulated_depreciation_account", "depreciation_expense_account"]) - + if not accumulated_depreciation_account: accumulated_depreciation_account = accounts[0] if not depreciation_expense_account: @@ -135,11 +135,11 @@ def scrap_asset(asset_name): je.flags.ignore_permissions = True je.submit() - + frappe.db.set_value("Asset", asset_name, "disposal_date", today()) frappe.db.set_value("Asset", asset_name, "journal_entry_for_scrap", je.name) asset.set_status("Scrapped") - + frappe.msgprint(_("Asset scrapped via Journal Entry {0}").format(je.name)) @frappe.whitelist() @@ -147,21 +147,29 @@ def restore_asset(asset_name): asset = frappe.get_doc("Asset", asset_name) je = asset.journal_entry_for_scrap - + asset.db_set("disposal_date", None) asset.db_set("journal_entry_for_scrap", None) - + frappe.get_doc("Journal Entry", je).cancel() asset.set_status() @frappe.whitelist() -def get_gl_entries_on_asset_disposal(asset, selling_amount=0): +def get_gl_entries_on_asset_disposal(asset, selling_amount=0, finance_book=None): fixed_asset_account, accumulated_depr_account, depr_expense_account = get_depreciation_accounts(asset) disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(asset.company) depreciation_cost_center = asset.cost_center or depreciation_cost_center - accumulated_depr_amount = flt(asset.gross_purchase_amount) - flt(asset.value_after_depreciation) + idx = 1 + if finance_book: + for d in asset.finance_books: + if d.finance_book == finance_book: + idx = d.idx + break + + value_after_depreciation = asset.finance_books[idx - 1].value_after_depreciation + accumulated_depr_amount = flt(asset.gross_purchase_amount) - flt(value_after_depreciation) gl_entries = [ { @@ -176,7 +184,7 @@ def get_gl_entries_on_asset_disposal(asset, selling_amount=0): } ] - profit_amount = flt(selling_amount) - flt(asset.value_after_depreciation) + profit_amount = flt(selling_amount) - flt(value_after_depreciation) if profit_amount: debit_or_credit = "debit" if profit_amount < 0 else "credit" gl_entries.append({ @@ -190,7 +198,7 @@ def get_gl_entries_on_asset_disposal(asset, selling_amount=0): @frappe.whitelist() def get_disposal_account_and_cost_center(company): - disposal_account, depreciation_cost_center = frappe.get_cached_value('Company', company, + disposal_account, depreciation_cost_center = frappe.get_cached_value('Company', company, ["disposal_account", "depreciation_cost_center"]) if not disposal_account: diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index ef85ffa1cb8..fceccfbd1c9 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -366,8 +366,9 @@ class TestAsset(unittest.TestCase): self.assertTrue(asset.journal_entry_for_scrap) expected_gle = ( - ("_Test Accumulated Depreciations - _TC", 100000.0, 0.0), - ("_Test Fixed Asset - _TC", 0.0, 100000.0) + ("_Test Accumulated Depreciations - _TC", 147.54, 0.0), + ("_Test Fixed Asset - _TC", 0.0, 100000.0), + ("_Test Gain/Loss on Asset Disposal - _TC", 99852.46, 0.0) ) gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` @@ -411,9 +412,9 @@ class TestAsset(unittest.TestCase): self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold") expected_gle = ( - ("_Test Accumulated Depreciations - _TC", 100000.0, 0.0), + ("_Test Accumulated Depreciations - _TC", 23051.47, 0.0), ("_Test Fixed Asset - _TC", 0.0, 100000.0), - ("_Test Gain/Loss on Asset Disposal - _TC", 0, 25000.0), + ("_Test Gain/Loss on Asset Disposal - _TC", 51948.53, 0.0), ("Debtors - _TC", 25000.0, 0.0) ) From ad99934b4c8b384e69499ae713842b4e5de7036f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 1 Jul 2019 15:16:10 +0530 Subject: [PATCH 091/115] Update accounts_controller.py --- erpnext/controllers/accounts_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 79695732683..b98fbf42cdd 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -374,7 +374,7 @@ class AccountsController(TransactionBase): def validate_qty_is_not_zero(self): for item in self.items: if not item.qty: - frappe.throw("Item quantity can not be zero") + frappe.throw(_("Item quantity can not be zero")) def validate_account_currency(self, account, account_currency=None): valid_currency = [self.company_currency] From fb59d770bad3a3e37faea12b1ab811e37b2e6659 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 1 Jul 2019 16:31:36 +0530 Subject: [PATCH 092/115] fix: translated title (#18121) --- erpnext/stock/page/stock_balance/stock_balance.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/page/stock_balance/stock_balance.js b/erpnext/stock/page/stock_balance/stock_balance.js index 85ea5b19be7..10ea3b7e228 100644 --- a/erpnext/stock/page/stock_balance/stock_balance.js +++ b/erpnext/stock/page/stock_balance/stock_balance.js @@ -1,7 +1,7 @@ frappe.pages['stock-balance'].on_page_load = function(wrapper) { var page = frappe.ui.make_app_page({ parent: wrapper, - title: 'Stock Summary', + title: __('Stock Summary'), single_column: true }); page.start = 0; From 47bca7f651db89b90932d8d30e34adbdea365dc7 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 1 Jul 2019 20:38:27 +0530 Subject: [PATCH 093/115] fix: multiple minor issues in delayed order report --- .../delayed_item_report/delayed_item_report.js | 2 +- .../delayed_item_report/delayed_item_report.py | 15 ++++++++++++--- .../delayed_order_report/delayed_order_report.js | 2 +- .../delayed_order_report/delayed_order_report.py | 13 ++++++++++--- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/erpnext/stock/report/delayed_item_report/delayed_item_report.js b/erpnext/stock/report/delayed_item_report/delayed_item_report.js index f1ead2c9fbb..40e6abefeb0 100644 --- a/erpnext/stock/report/delayed_item_report/delayed_item_report.js +++ b/erpnext/stock/report/delayed_item_report/delayed_item_report.js @@ -55,7 +55,7 @@ frappe.query_reports["Delayed Item Report"] = { label: __("Based On"), fieldtype: "Select", options: ["Delivery Note", "Sales Invoice"], - default: "Delivery Note", + default: "Sales Invoice", reqd: 1 }, ] diff --git a/erpnext/stock/report/delayed_item_report/delayed_item_report.py b/erpnext/stock/report/delayed_item_report/delayed_item_report.py index f8aa98886c1..a3d1faf9d3f 100644 --- a/erpnext/stock/report/delayed_item_report/delayed_item_report.py +++ b/erpnext/stock/report/delayed_item_report/delayed_item_report.py @@ -46,7 +46,8 @@ class DelayedItemReport(object): self.transactions = frappe.db.sql(""" SELECT `tab{child_doc}`.item_code, `tab{child_doc}`.item_name, `tab{child_doc}`.item_group, `tab{child_doc}`.qty, `tab{child_doc}`.rate, `tab{child_doc}`.amount, `tab{child_doc}`.so_detail, `tab{child_doc}`.{so_field} as sales_order, - `tab{doctype}`.customer, `tab{doctype}`.posting_date, `tab{doctype}`.name, `tab{doctype}`.grand_total + `tab{doctype}`.shipping_address_name, `tab{doctype}`.po_no, `tab{doctype}`.customer, + `tab{doctype}`.posting_date, `tab{doctype}`.name, `tab{doctype}`.grand_total FROM `tab{child_doc}`, `tab{doctype}` WHERE `tab{child_doc}`.parent = `tab{doctype}`.name and `tab{doctype}`.docstatus = 1 and @@ -97,12 +98,20 @@ class DelayedItemReport(object): "fieldtype": "Link", "options": based_on, "width": 100 - },{ + }, + { "label": _("Customer"), "fieldname": "customer", "fieldtype": "Link", "options": "Customer", - "width": 100 + "width": 200 + }, + { + "label": _("Shipping Address"), + "fieldname": "shipping_address_name", + "fieldtype": "Link", + "options": "Address", + "width": 120 }, { "label": _("Expected Delivery Date"), diff --git a/erpnext/stock/report/delayed_order_report/delayed_order_report.js b/erpnext/stock/report/delayed_order_report/delayed_order_report.js index 5b02a58fafc..aab0f3d0d1f 100644 --- a/erpnext/stock/report/delayed_order_report/delayed_order_report.js +++ b/erpnext/stock/report/delayed_order_report/delayed_order_report.js @@ -55,7 +55,7 @@ frappe.query_reports["Delayed Order Report"] = { label: __("Based On"), fieldtype: "Select", options: ["Delivery Note", "Sales Invoice"], - default: "Delivery Note", + default: "Sales Invoice", reqd: 1 }, ] diff --git a/erpnext/stock/report/delayed_order_report/delayed_order_report.py b/erpnext/stock/report/delayed_order_report/delayed_order_report.py index d2a1a30d9e2..79dc5d88219 100644 --- a/erpnext/stock/report/delayed_order_report/delayed_order_report.py +++ b/erpnext/stock/report/delayed_order_report/delayed_order_report.py @@ -42,7 +42,14 @@ class DelayedOrderReport(DelayedItemReport): "fieldname": "customer", "fieldtype": "Link", "options": "Customer", - "width": 100 + "width": 200 + }, + { + "label": _("Shipping Address"), + "fieldname": "shipping_address_name", + "fieldtype": "Link", + "options": "Address", + "width": 140 }, { "label": _("Expected Delivery Date"), @@ -73,11 +80,11 @@ class DelayedOrderReport(DelayedItemReport): "fieldname": "sales_order", "fieldtype": "Link", "options": "Sales Order", - "width": 100 + "width": 150 }, { "label": _("Customer PO"), "fieldname": "po_no", "fieldtype": "Data", - "width": 100 + "width": 110 }] \ No newline at end of file From 48474a2d4e15e4489e4af68f5d9117675d3981ef Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Tue, 2 Jul 2019 10:11:02 +0530 Subject: [PATCH 094/115] fix: Fiter passing fix in get batch query (#18130) --- erpnext/controllers/queries.py | 1 - erpnext/public/js/utils/serial_no_batch_selector.js | 13 ++++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index a40f0eff43b..e7f8c27d6df 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -297,7 +297,6 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters): order by batch.expiry_date, sle.batch_no desc limit %(start)s, %(page_len)s""".format(cond, match_conditions=get_match_cond(doctype)), args) - if batch_nos: return batch_nos else: return frappe.db.sql("""select name, concat('MFG-', manufacturing_date), concat('EXP-',expiry_date) from `tabBatch` batch diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 576ae0fbde1..c6086b9962b 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -240,14 +240,6 @@ erpnext.SerialNoBatchSelector = Class.extend({ get_batch_fields: function() { var me = this; - let filters = { - item_code: me.item_code - } - - if (me.warehouse || me.warehouse_details.name) { - filters['warehouse'] = me.warehouse || me.warehouse_details.name; - } - return [ { fieldtype: 'Section Break', label: __('Batches') }, { @@ -262,7 +254,10 @@ erpnext.SerialNoBatchSelector = Class.extend({ 'in_list_view': 1, get_query: function () { return { - filters: filters, + filters: { + item_code: me.item_code, + warehouse: me.warehouse || me.warehouse_details.name + }, query: 'erpnext.controllers.queries.get_batch_no' }; }, From 53e367492474cb6a651d480a1ae34b8a556fb66f Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Tue, 2 Jul 2019 19:06:20 +0550 Subject: [PATCH 095/115] bumped to version 11.1.43 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 8c70de3cc19..6b1ce9e669c 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.42' +__version__ = '11.1.43' def get_default_company(user=None): '''Get default company for user''' From 29433f2b1b131b4af15eb85a0b8e14b479013998 Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Wed, 3 Jul 2019 11:42:33 +0530 Subject: [PATCH 096/115] fix: translating Error (#18140) --- .../doctype/accounting_period/accounting_period.py | 5 +++-- .../bank_statement_transaction_entry.py | 8 ++++---- .../accounts/doctype/bank_transaction/bank_transaction.py | 2 +- .../accounts/doctype/purchase_invoice/purchase_invoice.js | 2 +- .../doctype/subscription_plan/subscription_plan.py | 5 +++-- .../student_report_generation_tool.py | 5 +++-- .../erpnext_integrations/connectors/shopify_connection.py | 4 ++-- .../clinical_procedure_template.py | 2 +- .../doctype/patient_encounter/patient_encounter.js | 2 +- .../employee_benefit_claim/employee_benefit_claim.py | 2 +- erpnext/hub_node/api.py | 7 ++++--- 11 files changed, 24 insertions(+), 20 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py index f7190b75e2c..1a366d2f7fb 100644 --- a/erpnext/accounts/doctype/accounting_period/accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe +from frappe import _ from frappe.model.document import Document class AccountingPeriod(Document): @@ -16,7 +17,7 @@ class AccountingPeriod(Document): def autoname(self): company_abbr = frappe.get_cached_value('Company', self.company, "abbr") self.name = " - ".join([self.period_name, company_abbr]) - + def validate_overlap(self): existing_accounting_period = frappe.db.sql("""select name from `tabAccounting Period` where ( @@ -33,7 +34,7 @@ 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")))) def get_doctypes_for_closing(self): docs_for_closing = [] diff --git a/erpnext/accounts/doctype/bank_statement_transaction_entry/bank_statement_transaction_entry.py b/erpnext/accounts/doctype/bank_statement_transaction_entry/bank_statement_transaction_entry.py index f5581941ba2..7bfab873b5a 100644 --- a/erpnext/accounts/doctype/bank_statement_transaction_entry/bank_statement_transaction_entry.py +++ b/erpnext/accounts/doctype/bank_statement_transaction_entry/bank_statement_transaction_entry.py @@ -48,7 +48,7 @@ class BankStatementTransactionEntry(Document): def get_statement_headers(self): if not self.bank_settings: - frappe.throw("Bank Data mapper doesn't exist") + frappe.throw(_("Bank Data mapper doesn't exist")) mapper_doc = frappe.get_doc("Bank Statement Settings", self.bank_settings) headers = {entry.mapped_header:entry.stmt_header for entry in mapper_doc.header_items} return headers @@ -57,7 +57,7 @@ class BankStatementTransactionEntry(Document): if self.bank_statement is None: return filename = self.bank_statement.split("/")[-1] if (len(self.new_transaction_items + self.reconciled_transaction_items) > 0): - frappe.throw("Transactions already retreived from the statement") + frappe.throw(_("Transactions already retreived from the statement")) date_format = frappe.get_value("Bank Statement Settings", self.bank_settings, "date_format") if (date_format is None): @@ -314,7 +314,7 @@ class BankStatementTransactionEntry(Document): try: reconcile_against_document(lst) except: - frappe.throw("Exception occurred while reconciling {0}".format(payment.reference_name)) + frappe.throw(_("Exception occurred while reconciling {0}".format(payment.reference_name))) def submit_payment_entries(self): for payment in self.new_transaction_items: @@ -414,7 +414,7 @@ def get_transaction_entries(filename, headers): elif (filename.lower().endswith("xls")): rows = get_rows_from_xls_file(filename) else: - frappe.throw("Only .csv and .xlsx files are supported currently") + frappe.throw(_("Only .csv and .xlsx files are supported currently")) stmt_headers = headers.values() for row in rows: diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index f943b345810..4899e6ecf0f 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -91,7 +91,7 @@ def get_paid_amount(payment_entry): return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_amount_reimbursed") else: - frappe.throw("Please reconcile {0}: {1} manually".format(payment_entry.payment_document, payment_entry.payment_entry)) + frappe.throw(_("Please reconcile {0}: {1} manually".format(payment_entry.payment_document, payment_entry.payment_entry))) @frappe.whitelist() def unclear_reference_payment(doctype, docname): diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index 2d415bb5b17..87835dcdb83 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -157,7 +157,7 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ can_change_release_date: function(date) { const diff = frappe.datetime.get_diff(date, frappe.datetime.nowdate()); if (diff < 0) { - frappe.throw('New release date should be in the future'); + frappe.throw(__('New release date should be in the future')); return false; } else { return true; diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py index d3fef6023ba..625979bee1f 100644 --- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py +++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe +from frappe import _ from frappe.model.document import Document from erpnext.utilities.product import get_price @@ -13,7 +14,7 @@ class SubscriptionPlan(Document): def validate_interval_count(self): if self.billing_interval_count < 1: - frappe.throw('Billing Interval Count cannot be less than 1') + frappe.throw(_('Billing Interval Count cannot be less than 1')) @frappe.whitelist() def get_plan_rate(plan, quantity=1, customer=None): @@ -26,7 +27,7 @@ def get_plan_rate(plan, quantity=1, customer=None): customer_group = frappe.db.get_value("Customer", customer, "customer_group") else: customer_group = None - + price = get_price(item_code=plan.item, price_list=plan.price_list, customer_group=customer_group, company=None, qty=quantity) if not price: return 0 diff --git a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py index f9979752f78..16933dcfe09 100644 --- a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py +++ b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe, json +from frappe import _ from frappe.model.document import Document from erpnext.education.api import get_grade from frappe.utils.pdf import get_pdf @@ -79,7 +80,7 @@ def get_attendance_count(student, academic_year, academic_term=None): from_date, to_date = frappe.db.get_value("Academic Term", academic_term, ["term_start_date", "term_end_date"]) if from_date and to_date: attendance = dict(frappe.db.sql('''select status, count(student) as no_of_days - from `tabStudent Attendance` where student = %s + from `tabStudent Attendance` where student = %s and date between %s and %s group by status''', (student, from_date, to_date))) if "Absent" not in attendance.keys(): @@ -88,4 +89,4 @@ def get_attendance_count(student, academic_year, academic_term=None): attendance["Present"] = 0 return attendance else: - frappe.throw("Provide the academic year and set the starting and ending date.") \ No newline at end of file + frappe.throw(_("Provide the academic year and set the starting and ending date.")) \ No newline at end of file diff --git a/erpnext/erpnext_integrations/connectors/shopify_connection.py b/erpnext/erpnext_integrations/connectors/shopify_connection.py index 88078ab74f6..1d6e8917f50 100644 --- a/erpnext/erpnext_integrations/connectors/shopify_connection.py +++ b/erpnext/erpnext_integrations/connectors/shopify_connection.py @@ -124,7 +124,7 @@ def create_sales_order(shopify_order, shopify_settings, company=None): else: so = frappe.get_doc("Sales Order", so) - + frappe.db.commit() return so @@ -252,6 +252,6 @@ def get_tax_account_head(tax): {"parent": "Shopify Settings", "shopify_tax": tax_title}, "tax_account") if not tax_account: - frappe.throw("Tax Account not specified for Shopify Tax {0}".format(tax.get("title"))) + frappe.throw(_("Tax Account not specified for Shopify Tax {0}".format(tax.get("title")))) return tax_account diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py index 90bf95770fb..141329b3db1 100644 --- a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py +++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py @@ -30,7 +30,7 @@ class ClinicalProcedureTemplate(Document): try: frappe.delete_doc("Item",self.item) except Exception: - frappe.throw("""Not permitted. Please disable the Procedure Template""") + frappe.throw(_("""Not permitted. Please disable the Procedure Template""")) def get_item_details(self, args=None): item = frappe.db.sql("""select stock_uom, item_name diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js index c7df5b7cd94..7ea45688fd9 100644 --- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js +++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js @@ -160,7 +160,7 @@ var btn_create_vital_signs = function (frm) { var btn_create_procedure = function (frm) { if(!frm.doc.patient){ - frappe.throw("Please select patient"); + frappe.throw(__("Please select patient")); } frappe.route_options = { "patient": frm.doc.patient, diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py index 3a80b303659..abb82f2cdd1 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py @@ -84,7 +84,7 @@ def get_benefit_pro_rata_ratio_amount(employee, on_date, sal_struct): pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"]) except TypeError: # show the error in tests? - frappe.throw("Unable to find Salary Component {0}".format(sal_struct_row.salary_component)) + frappe.throw(_("Unable to find Salary Component {0}".format(sal_struct_row.salary_component))) if sal_struct_row.is_flexible_benefit == 1 and pay_against_benefit_claim != 1: total_pro_rata_max += max_benefit_amount if total_pro_rata_max > 0: diff --git a/erpnext/hub_node/api.py b/erpnext/hub_node/api.py index 0c94df31596..75f2c9323aa 100644 --- a/erpnext/hub_node/api.py +++ b/erpnext/hub_node/api.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import frappe import json +from frappe import _ from frappe import _ from frappe.frappeclient import FrappeClient @@ -120,7 +121,7 @@ def get_valid_items(search_value=''): def publish_selected_items(items_to_publish): items_to_publish = json.loads(items_to_publish) if not len(items_to_publish): - frappe.throw('No items to publish') + frappe.throw(_('No items to publish')) for item in items_to_publish: item_code = item.get('item_code') @@ -165,7 +166,7 @@ def item_sync_preprocess(intended_item_publish_count): frappe.db.set_value("Marketplace Settings", "Marketplace Settings", "sync_in_progress", 1) return response else: - frappe.throw('Unable to update remote activity') + frappe.throw(_('Unable to update remote activity')) def item_sync_postprocess(): @@ -173,7 +174,7 @@ def item_sync_postprocess(): if response: frappe.db.set_value('Marketplace Settings', 'Marketplace Settings', 'last_sync_datetime', frappe.utils.now()) else: - frappe.throw('Unable to update remote activity') + frappe.throw(_('Unable to update remote activity')) frappe.db.set_value('Marketplace Settings', 'Marketplace Settings', 'sync_in_progress', 0) From cc80be449d74faf555265a2aae1469600ae12602 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 3 Jul 2019 17:27:40 +0530 Subject: [PATCH 097/115] fix: Salary slip amount calculation (#18146) --- erpnext/hr/doctype/salary_slip/salary_slip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 90391037896..652a1860396 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -618,7 +618,7 @@ class SalarySlip(TransactionBase): elif not self.payment_days and not self.salary_slip_based_on_timesheet and cint(row.depends_on_payment_days): amount, additional_amount = 0, 0 elif not row.amount: - amount = row.default_amount + row.additional_amount + amount = cint(row.default_amount) + cint(row.additional_amount) # apply rounding if frappe.get_cached_value("Salary Component", row.salary_component, "round_to_the_nearest_integer"): From e59836e3da25715de21e00b42e9bb48e947ded5c Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 3 Jul 2019 19:22:49 +0530 Subject: [PATCH 098/115] fix: Honor price list in Shopping Cart Settings --- erpnext/shopping_cart/cart.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py index efc128aa0c5..3dd8729eb54 100644 --- a/erpnext/shopping_cart/cart.py +++ b/erpnext/shopping_cart/cart.py @@ -202,11 +202,13 @@ 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"]) qdoc = frappe.get_doc({ "doctype": "Quotation", "naming_series": get_shopping_cart_settings().quotation_series or "QTN-CART-", "quotation_to": party.doctype, - "company": frappe.db.get_value("Shopping Cart Settings", None, "company"), + "company": company, + "selling_price_list": price_list, "order_type": "Shopping Cart", "status": "Draft", "docstatus": 0, From 4dd48f46f3eda6aafc78d4bd29f051e6e8d44e8f Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 4 Jul 2019 11:37:45 +0530 Subject: [PATCH 099/115] fix: invoice cancellation (#18151) --- erpnext/regional/italy/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py index 730a80b547b..cb6b736320e 100644 --- a/erpnext/regional/italy/utils.py +++ b/erpnext/regional/italy/utils.py @@ -316,6 +316,9 @@ def get_company_country(company): return frappe.get_cached_value('Company', company, 'country') def get_e_invoice_attachments(invoice): + if not invoice.company_tax_id: + return [] + out = [] attachments = get_attachments(invoice.doctype, invoice.name) company_tax_id = invoice.company_tax_id if invoice.company_tax_id.startswith("IT") else "IT" + invoice.company_tax_id From 709f21692ca4ea7648267a12701be7b1383e32e2 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 4 Jul 2019 13:09:06 +0530 Subject: [PATCH 100/115] fix(salary-slip): amount calculation (#18158) --- erpnext/hr/doctype/salary_slip/salary_slip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 652a1860396..0ce75d1b954 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -618,7 +618,7 @@ class SalarySlip(TransactionBase): elif not self.payment_days and not self.salary_slip_based_on_timesheet and cint(row.depends_on_payment_days): amount, additional_amount = 0, 0 elif not row.amount: - amount = cint(row.default_amount) + cint(row.additional_amount) + amount = flt(row.default_amount) + flt(row.additional_amount) # apply rounding if frappe.get_cached_value("Salary Component", row.salary_component, "round_to_the_nearest_integer"): From ba6217356195a8561dfb5fcc5ffc27ba14fb8d56 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 4 Jul 2019 15:00:04 +0530 Subject: [PATCH 101/115] fix: default supplier was not set from the patch in item defaults for multi company instance --- erpnext/patches.txt | 3 ++- ...pdate_default_supplier_in_item_defaults.py | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/v11_1/update_default_supplier_in_item_defaults.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 962ef8a8a8d..9827814f07e 100755 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -602,4 +602,5 @@ erpnext.patches.v11_1.delete_scheduling_tool erpnext.patches.v11_1.update_bank_transaction_status erpnext.patches.v11_1.renamed_delayed_item_report erpnext.patches.v11_1.set_missing_opportunity_from -erpnext.patches.v11_1.set_quotation_status \ No newline at end of file +erpnext.patches.v11_1.set_quotation_status +erpnext.patches.v11_1.update_default_supplier_in_item_defaults \ No newline at end of file diff --git a/erpnext/patches/v11_1/update_default_supplier_in_item_defaults.py b/erpnext/patches/v11_1/update_default_supplier_in_item_defaults.py new file mode 100644 index 00000000000..347dec1f74d --- /dev/null +++ b/erpnext/patches/v11_1/update_default_supplier_in_item_defaults.py @@ -0,0 +1,25 @@ +# Copyright (c) 2018, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + ''' + default supplier was not set in the item defaults for multi company instance, + this patch will set the default supplier + + ''' + if not frappe.db.has_column('Item', 'default_supplier'): + return + + frappe.reload_doc('stock', 'doctype', 'item_default') + frappe.reload_doc('stock', 'doctype', 'item') + + companies = frappe.get_all("Company") + if len(companies) > 1: + frappe.db.sql(""" UPDATE `tabItem Default`, `tabItem` + SET `tabItem Default`.default_supplier = `tabItem`.default_supplier + WHERE + `tabItem Default`.parent = `tabItem`.name and `tabItem Default`.default_supplier is null + and `tabItem`.default_supplier is not null and `tabItem`.default_supplier != '' """) \ No newline at end of file From 6fc6f385fee7311a2a2c6d8a8b96855890d0a35f Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Thu, 4 Jul 2019 16:10:39 +0550 Subject: [PATCH 102/115] bumped to version 11.1.44 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 6b1ce9e669c..27629c11c17 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.43' +__version__ = '11.1.44' def get_default_company(user=None): '''Get default company for user''' From 11d02c028fe9901aa69ee2c97009273b89261d47 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 5 Jul 2019 14:19:40 +0530 Subject: [PATCH 103/115] fix: on credit note / debit note deferred reversed instead of income (#18171) --- .../accounts/doctype/purchase_invoice/purchase_invoice.py | 6 +++++- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index a33e3f760d0..7edd1eb1bc6 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -484,9 +484,13 @@ class PurchaseInvoice(BuyingController): "credit": flt(item.rm_supp_cost) }, warehouse_account[self.supplier_warehouse]["account_currency"])) elif not item.is_fixed_asset or (item.is_fixed_asset and is_cwip_accounting_disabled()): + + expense_account = (item.expense_account + if (not item.enable_deferred_expense or self.is_return) else item.deferred_expense_account) + gl_entries.append( self.get_gl_dict({ - "account": item.expense_account if not item.enable_deferred_expense else item.deferred_expense_account, + "account": expense_account, "against": self.supplier, "debit": flt(item.base_net_amount, item.precision("base_net_amount")), "debit_in_account_currency": (flt(item.base_net_amount, diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 5b61fbfa138..124b6d34a36 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -785,10 +785,13 @@ class SalesInvoice(SellingController): asset.db_set("disposal_date", self.posting_date) asset.set_status("Sold" if self.docstatus==1 else None) else: - account_currency = get_account_currency(item.income_account) + income_account = (item.income_account + if (not item.enable_deferred_revenue or self.is_return) else item.deferred_revenue_account) + + account_currency = get_account_currency(income_account) gl_entries.append( self.get_gl_dict({ - "account": item.income_account if not item.enable_deferred_revenue else item.deferred_revenue_account, + "account": income_account, "against": self.customer, "credit": flt(item.base_net_amount, item.precision("base_net_amount")), "credit_in_account_currency": (flt(item.base_net_amount, item.precision("base_net_amount")) From 34867ced92d7082a62999f769bb4457e0468eea1 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 7 Jul 2019 21:49:17 +0530 Subject: [PATCH 104/115] fix: Cess amount calculation fix in GSTR-1(hotfix) --- erpnext/regional/report/gstr_1/gstr_1.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index b1cb7867daa..696dc73ef32 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -85,7 +85,7 @@ class Gstr1Report(object): "rate": "", "taxable_value": 0, "cess_amount": 0, - "type": 0 + "type": "" }) row = b2cs_output.get((rate, place_of_supply, ecommerce_gstin)) @@ -94,6 +94,7 @@ class Gstr1Report(object): row["rate"] = rate row["taxable_value"] += sum([abs(net_amount) for item_code, net_amount in self.invoice_items.get(inv).items() if item_code in items]) + row["cess_amount"] += flt(self.invoice_cess.get(inv), 2) row["type"] = "E" if ecommerce_gstin else "OE" for key, value in iteritems(b2cs_output): @@ -118,6 +119,10 @@ class Gstr1Report(object): for item_code, net_amount in self.invoice_items.get(invoice).items() if item_code in items]) row += [tax_rate or 0, taxable_value] + for column in self.other_columns: + if column.get('fieldname') == 'cess_amount': + row.append(flt(self.invoice_cess.get(invoice), 2)) + return row, taxable_value def get_invoice_data(self): From 37d0c75f04852916c639bc355941924a2bc32a56 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 8 Jul 2019 10:26:12 +0530 Subject: [PATCH 105/115] fix: not able to make credit note for the sales invoice in which item code is not set (#18185) --- erpnext/controllers/sales_and_purchase_return.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index 8cf11f785be..2fddcdf24c5 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -75,7 +75,7 @@ def validate_returned_items(doc): items_returned = False for d in doc.get("items"): - if flt(d.qty) < 0 or d.get('received_qty') < 0: + if d.item_code and (flt(d.qty) < 0 or d.get('received_qty') < 0): if d.item_code not in valid_items: frappe.throw(_("Row # {0}: Returned Item {1} does not exists in {2} {3}") .format(d.idx, d.item_code, doc.doctype, doc.return_against)) @@ -107,6 +107,9 @@ def validate_returned_items(doc): items_returned = True + elif d.item_name: + items_returned = True + if not items_returned: frappe.throw(_("Atleast one item should be entered with negative quantity in return document")) From 683d98743219e3e43ba90fd55656547794deffa5 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 8 Jul 2019 10:40:24 +0530 Subject: [PATCH 106/115] fix(bom): escape name with wildcard character (#18163) --- erpnext/controllers/queries.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index e7f8c27d6df..99fafa73056 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -206,11 +206,11 @@ def bom(doctype, txt, searchfield, start, page_len, filters): if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999), idx desc, name limit %(start)s, %(page_len)s """.format( - fcond=get_filters_cond(doctype, filters, conditions), + fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'), mcond=get_match_cond(doctype), key=frappe.db.escape(searchfield)), { - 'txt': "%%%s%%" % frappe.db.escape(txt), + 'txt': "%"+frappe.db.escape(txt)+"%", '_txt': txt.replace("%", ""), 'start': start or 0, 'page_len': page_len or 20 From d287fe4daee92f56d60a2c4269500548980644ff Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Tue, 9 Jul 2019 15:40:08 +0550 Subject: [PATCH 107/115] bumped to version 11.1.45 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 27629c11c17..ce61994edd4 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.44' +__version__ = '11.1.45' def get_default_company(user=None): '''Get default company for user''' From e6ab86e18543f265f7f8c626a7a421b1a9d78633 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 10 Jul 2019 16:41:39 +0530 Subject: [PATCH 108/115] fix: error report for item price (#18213) --- erpnext/stock/doctype/item_price/item_price.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/doctype/item_price/item_price.py b/erpnext/stock/doctype/item_price/item_price.py index d1822904278..30675b54b3e 100644 --- a/erpnext/stock/doctype/item_price/item_price.py +++ b/erpnext/stock/doctype/item_price/item_price.py @@ -31,13 +31,16 @@ class ItemPrice(Document): frappe.throw(_("Valid From Date must be lesser than Valid Upto Date.")) def update_price_list_details(self): - self.buying, self.selling, self.currency = \ - frappe.db.get_value("Price List", - {"name": self.price_list, "enabled": 1}, - ["buying", "selling", "currency"]) + if self.price_list: + self.buying, self.selling, self.currency = \ + frappe.db.get_value("Price List", + {"name": self.price_list, "enabled": 1}, + ["buying", "selling", "currency"]) def update_item_details(self): - self.item_name, self.item_description = frappe.db.get_value("Item",self.item_code,["item_name", "description"]) + if self.item_code: + self.item_name, self.item_description = frappe.db.get_value("Item", + self.item_code,["item_name", "description"]) def check_duplicates(self): conditions = "where item_code=%(item_code)s and price_list=%(price_list)s and name != %(name)s" From 49fadcbaf2f322e55ead1e6392c6a4b3dc645f6b Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 10 Jul 2019 17:03:08 +0530 Subject: [PATCH 109/115] fix(exchange-rate-revaluation): change create to view button on creation of journal entry (#18202) --- .../exchange_rate_revaluation.js | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js index cb3aef72c32..0d5456ece6c 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js @@ -21,9 +21,29 @@ frappe.ui.form.on('Exchange Rate Revaluation', { refresh: function(frm) { if(frm.doc.docstatus==1) { - frm.add_custom_button(__('Make Journal Entry'), function() { - return frm.events.make_jv(frm); - }); + frappe.db.get_value("Journal Entry Account", { + 'reference_type': 'Exchange Rate Revaluation', + 'reference_name': frm.doc.name, + 'docstatus': 1 + }, "sum(debit) as sum", (r) =>{ + let total_amt = 0; + frm.doc.accounts.forEach(d=> { + total_amt = total_amt + d['new_balance_in_base_currency']; + }); + if(total_amt === r.sum) { + frm.add_custom_button(__("Journal Entry"), function(){ + frappe.route_options = { + 'reference_type': 'Exchange Rate Revaluation', + 'reference_name': frm.doc.name + }; + frappe.set_route("List", "Journal Entry"); + }, __("View")); + } else { + frm.add_custom_button(__('Create Journal Entry'), function() { + return frm.events.make_jv(frm); + }); + } + }, 'Journal Entry'); } }, From 7ee97b612852a2801784816fd49e4c3d94024b7a Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 10 Jul 2019 17:05:57 +0530 Subject: [PATCH 110/115] fix: Make material request against SO only for pending qty (#18217) --- .../selling/doctype/sales_order/sales_order.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index a490082c42c..e1ddd2c7dac 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -486,13 +486,27 @@ def close_or_unclose_sales_orders(names, status): frappe.local.message_log = [] +def get_requested_item_qty(sales_order): + return frappe._dict(frappe.db.sql(""" + select sales_order_item, sum(stock_qty) + from `tabMaterial Request Item` + where docstatus = 1 + and sales_order = %s + group by sales_order_item + """, sales_order)) + @frappe.whitelist() def make_material_request(source_name, target_doc=None): + requested_item_qty = get_requested_item_qty(source_name) + def postprocess(source, doc): doc.material_request_type = "Purchase" def update_item(source, target, source_parent): target.project = source_parent.project + target.qty = source.stock_qty - requested_item_qty.get(source.name, 0) + target.conversion_factor = 1 + target.stock_qty = source.stock_qty - requested_item_qty.get(source.name, 0) doc = get_mapped_doc("Sales Order", source_name, { "Sales Order": { @@ -517,7 +531,7 @@ def make_material_request(source_name, target_doc=None): "stock_uom": "uom", "stock_qty": "qty" }, - "condition": lambda doc: not frappe.db.exists('Product Bundle', doc.item_code), + "condition": lambda doc: not frappe.db.exists('Product Bundle', doc.item_code) and doc.stock_qty > requested_item_qty.get(doc.name, 0), "postprocess": update_item } }, target_doc, postprocess) From 68d7d6e2231eaecbbc5c38758b18e41ac73f7009 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Wed, 10 Jul 2019 17:16:48 +0530 Subject: [PATCH 111/115] fix: Return fieldtype so that the client-side can format chart values (#18221) --- .../profit_and_loss_statement/profit_and_loss_statement.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py index 48d7361fe0a..ac11868cabb 100644 --- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py +++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py @@ -93,4 +93,6 @@ def get_chart_data(filters, columns, income, expense, net_profit_loss): else: chart["type"] = "line" + chart["fieldtype"] = "Currency" + return chart \ No newline at end of file From 6fa4697efb35ebad58a5e70ebe5da2a7a25f0316 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 11 Jul 2019 10:05:04 +0530 Subject: [PATCH 112/115] fix(sales-invoice): get items from quotation (#18236) --- .../accounts/doctype/sales_invoice/sales_invoice.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 5393f5d37fb..df1dae34f35 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -174,9 +174,13 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte method: "erpnext.selling.doctype.quotation.quotation.make_sales_invoice", source_doctype: "Quotation", target: me.frm, - setters: { - customer: me.frm.doc.customer || undefined, - }, + setters: [{ + fieldtype: 'Link', + label: __('Customer'), + options: 'Customer', + fieldname: 'party_name', + default: me.frm.doc.customer, + }], get_query_filters: { docstatus: 1, status: ["!=", "Lost"], From 75310637da9f269e7630d34f406ba25fdfd7a648 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 11 Jul 2019 14:39:38 +0530 Subject: [PATCH 113/115] fix: Revert #frappe/erpnext/17896 (#18250) --- erpnext/public/js/utils.js | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 4e589dadb66..2dd65fec170 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -587,7 +587,6 @@ erpnext.utils.map_current_doc = function(opts) { if(!r.exc) { var doc = frappe.model.sync(r.message); cur_frm.dirty(); - erpnext.utils.clear_duplicates(); cur_frm.refresh(); } } @@ -618,28 +617,6 @@ erpnext.utils.map_current_doc = function(opts) { } } -erpnext.utils.clear_duplicates = function() { - if(!cur_frm.doc.items) return; - const unique_items = new Map(); - /* - Create a Map of items with - item_code => [qty, warehouse, batch_no] - */ - let items = []; - - for (let item of cur_frm.doc.items) { - if (!(unique_items.has(item.item_code) && unique_items.get(item.item_code)[0] === item.qty && - unique_items.get(item.item_code)[1] === item.warehouse && unique_items.get(item.item_code)[2] === item.batch_no && - unique_items.get(item.item_code)[3] === item.delivery_date && unique_items.get(item.item_code)[4] === item.required_date && - unique_items.get(item.item_code)[5] === item.rate)) { - - unique_items.set(item.item_code, [item.qty, item.warehouse, item.batch_no, item.delivery_date, item.required_date, item.rate]); - items.push(item); - } - } - cur_frm.doc.items = items; -} - frappe.form.link_formatters['Item'] = function(value, doc) { if(doc && doc.item_name && doc.item_name !== value) { return value? value + ': ' + doc.item_name: doc.item_name; From 5792d6037c03dcadb8bbc6529bbeeed8945df11d Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Thu, 11 Jul 2019 15:35:56 +0550 Subject: [PATCH 114/115] bumped to version 11.1.46 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index ce61994edd4..4577c3d39ce 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.45' +__version__ = '11.1.46' def get_default_company(user=None): '''Get default company for user''' From 7d3d99a9b8df31dfcc2dedfe84ba5d9b2b6b0150 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 11 Jul 2019 17:17:49 +0530 Subject: [PATCH 115/115] fix: UX fixes in loan (#18219) * fix: UX fixes in loan * Update loan.py --- .../employee_loan_application.py | 69 ------------------- erpnext/hr/doctype/loan/loan.js | 32 +++------ erpnext/hr/doctype/loan/loan.json | 44 ++++++++++-- erpnext/hr/doctype/loan/loan.py | 59 ++++++++++------ .../loan_application/loan_application.js | 5 +- .../loan_application/loan_application.py | 12 ++-- 6 files changed, 94 insertions(+), 127 deletions(-) delete mode 100644 erpnext/hr/doctype/employee_loan_application/employee_loan_application.py diff --git a/erpnext/hr/doctype/employee_loan_application/employee_loan_application.py b/erpnext/hr/doctype/employee_loan_application/employee_loan_application.py deleted file mode 100644 index b6c650207f0..00000000000 --- a/erpnext/hr/doctype/employee_loan_application/employee_loan_application.py +++ /dev/null @@ -1,69 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - -from __future__ import unicode_literals -import frappe, math -from frappe import _ -from frappe.utils import flt, rounded -from frappe.model.mapper import get_mapped_doc -from frappe.model.document import Document - -from erpnext.hr.doctype.employee_loan.employee_loan import get_monthly_repayment_amount, check_repayment_method - -class EmployeeLoanApplication(Document): - def validate(self): - check_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, self.repayment_periods) - self.validate_loan_amount() - self.get_repayment_details() - - def validate_loan_amount(self): - maximum_loan_limit = frappe.db.get_value('Loan Type', self.loan_type, 'maximum_loan_amount') - if maximum_loan_limit and self.loan_amount > maximum_loan_limit: - frappe.throw(_("Loan Amount cannot exceed Maximum Loan Amount of {0}").format(maximum_loan_limit)) - - def get_repayment_details(self): - if self.repayment_method == "Repay Over Number of Periods": - self.repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods) - - if self.repayment_method == "Repay Fixed Amount per Period": - monthly_interest_rate = flt(self.rate_of_interest) / (12 *100) - if monthly_interest_rate: - monthly_interest_amount = self.loan_amount * monthly_interest_rate - if monthly_interest_amount >= self.repayment_amount: - frappe.throw(_("Repayment amount {} should be greater than monthly interest amount {}"). - format(self.repayment_amount, monthly_interest_amount)) - - self.repayment_periods = math.ceil((math.log(self.repayment_amount) - - math.log(self.repayment_amount - (monthly_interest_amount))) / - (math.log(1 + monthly_interest_rate))) - else: - self.repayment_periods = self.loan_amount / self.repayment_amount - - self.calculate_payable_amount() - - def calculate_payable_amount(self): - balance_amount = self.loan_amount - self.total_payable_amount = 0 - self.total_payable_interest = 0 - - while(balance_amount > 0): - interest_amount = rounded(balance_amount * flt(self.rate_of_interest) / (12*100)) - balance_amount = rounded(balance_amount + interest_amount - self.repayment_amount) - - self.total_payable_interest += interest_amount - - self.total_payable_amount = self.loan_amount + self.total_payable_interest - -@frappe.whitelist() -def make_employee_loan(source_name, target_doc = None): - doclist = get_mapped_doc("Employee Loan Application", source_name, { - "Employee Loan Application": { - "doctype": "Employee Loan", - "validation": { - "docstatus": ["=", 1] - } - } - }, target_doc) - - return doclist \ No newline at end of file diff --git a/erpnext/hr/doctype/loan/loan.js b/erpnext/hr/doctype/loan/loan.js index 3024f28207a..940e4c12daf 100644 --- a/erpnext/hr/doctype/loan/loan.js +++ b/erpnext/hr/doctype/loan/loan.js @@ -39,31 +39,19 @@ frappe.ui.form.on('Loan', { }, refresh: function (frm) { - if (frm.doc.docstatus == 1 && frm.doc.status == "Sanctioned") { - frm.add_custom_button(__('Make Disbursement Entry'), function() { - frm.trigger("make_jv"); - }) - } - if (frm.doc.repayment_schedule) { - let total_amount_paid = 0; - $.each(frm.doc.repayment_schedule || [], function(i, row) { - if (row.paid) { - total_amount_paid += row.total_payment; - } - }); - frm.set_value("total_amount_paid", total_amount_paid); -; } - if (frm.doc.docstatus == 1 && frm.doc.repayment_start_date && (frm.doc.applicant_type == 'Member' || frm.doc.repay_from_salary == 0)) { - frm.add_custom_button(__('Make Repayment Entry'), function() { - frm.trigger("make_repayment_entry"); - }) + if (frm.doc.docstatus == 1) { + if (frm.doc.status == "Sanctioned") { + frm.add_custom_button(__('Create Disbursement Entry'), function() { + frm.trigger("make_jv"); + }).addClass("btn-primary"); + } else if (frm.doc.status == "Disbursed" && frm.doc.repayment_start_date && (frm.doc.applicant_type == 'Member' || frm.doc.repay_from_salary == 0)) { + frm.add_custom_button(__('Create Repayment Entry'), function() { + frm.trigger("make_repayment_entry"); + }).addClass("btn-primary"); + } } frm.trigger("toggle_fields"); }, - status: function (frm) { - frm.toggle_reqd("disbursement_date", frm.doc.status == 'Disbursed') - frm.toggle_reqd("repayment_start_date", frm.doc.status == 'Disbursed') - }, make_jv: function (frm) { frappe.call({ diff --git a/erpnext/hr/doctype/loan/loan.json b/erpnext/hr/doctype/loan/loan.json index 587b3010ca0..505b601edd5 100644 --- a/erpnext/hr/doctype/loan/loan.json +++ b/erpnext/hr/doctype/loan/loan.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 0, @@ -20,6 +21,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "applicant_type", "fieldtype": "Select", "hidden": 0, @@ -53,6 +55,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "applicant", "fieldtype": "Dynamic Link", "hidden": 0, @@ -86,6 +89,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "applicant_name", "fieldtype": "Data", "hidden": 0, @@ -118,6 +122,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "loan_application", "fieldtype": "Link", "hidden": 0, @@ -151,6 +156,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "loan_type", "fieldtype": "Link", "hidden": 0, @@ -184,6 +190,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_3", "fieldtype": "Column Break", "hidden": 0, @@ -215,7 +222,8 @@ "bold": 0, "collapsible": 0, "columns": 0, - "default": "", + "default": "Today", + "fetch_if_empty": 0, "fieldname": "posting_date", "fieldtype": "Date", "hidden": 0, @@ -248,6 +256,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company", "fieldtype": "Link", "hidden": 0, @@ -282,6 +291,7 @@ "collapsible": 0, "columns": 0, "default": "Sanctioned", + "fetch_if_empty": 0, "fieldname": "status", "fieldtype": "Select", "hidden": 0, @@ -299,7 +309,7 @@ "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, - "read_only": 0, + "read_only": 1, "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, @@ -316,6 +326,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.applicant_type==\"Employee\"", + "fetch_if_empty": 0, "fieldname": "repay_from_salary", "fieldtype": "Check", "hidden": 0, @@ -348,6 +359,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_8", "fieldtype": "Section Break", "hidden": 0, @@ -380,6 +392,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "loan_amount", "fieldtype": "Currency", "hidden": 0, @@ -415,6 +428,7 @@ "columns": 0, "default": "", "fetch_from": "loan_type.rate_of_interest", + "fetch_if_empty": 0, "fieldname": "rate_of_interest", "fieldtype": "Percent", "hidden": 0, @@ -448,6 +462,8 @@ "bold": 0, "collapsible": 0, "columns": 0, + "depends_on": "eval:doc.status==\"Disbursed\"", + "fetch_if_empty": 0, "fieldname": "disbursement_date", "fieldtype": "Date", "hidden": 0, @@ -480,6 +496,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "repayment_start_date", "fieldtype": "Date", "hidden": 0, @@ -499,7 +516,7 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 0, + "reqd": 1, "search_index": 0, "set_only_once": 0, "translatable": 0, @@ -512,6 +529,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_11", "fieldtype": "Column Break", "hidden": 0, @@ -544,6 +562,7 @@ "collapsible": 0, "columns": 0, "default": "Repay Over Number of Periods", + "fetch_if_empty": 0, "fieldname": "repayment_method", "fieldtype": "Select", "hidden": 0, @@ -579,6 +598,7 @@ "columns": 0, "default": "", "depends_on": "", + "fetch_if_empty": 0, "fieldname": "repayment_periods", "fieldtype": "Int", "hidden": 0, @@ -613,6 +633,7 @@ "columns": 0, "default": "", "depends_on": "", + "fetch_if_empty": 0, "fieldname": "monthly_repayment_amount", "fieldtype": "Currency", "hidden": 0, @@ -646,6 +667,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "account_info", "fieldtype": "Section Break", "hidden": 0, @@ -678,6 +700,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "mode_of_payment", "fieldtype": "Link", "hidden": 0, @@ -711,6 +734,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "payment_account", "fieldtype": "Link", "hidden": 0, @@ -744,6 +768,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_9", "fieldtype": "Column Break", "hidden": 0, @@ -775,6 +800,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "loan_account", "fieldtype": "Link", "hidden": 0, @@ -808,6 +834,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "interest_income_account", "fieldtype": "Link", "hidden": 0, @@ -841,6 +868,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_15", "fieldtype": "Section Break", "hidden": 0, @@ -873,6 +901,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "repayment_schedule", "fieldtype": "Table", "hidden": 0, @@ -906,6 +935,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_17", "fieldtype": "Section Break", "hidden": 0, @@ -939,6 +969,7 @@ "collapsible": 0, "columns": 0, "default": "0", + "fetch_if_empty": 0, "fieldname": "total_payment", "fieldtype": "Currency", "hidden": 0, @@ -972,6 +1003,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_19", "fieldtype": "Column Break", "hidden": 0, @@ -1004,6 +1036,7 @@ "collapsible": 0, "columns": 0, "default": "0", + "fetch_if_empty": 0, "fieldname": "total_interest_payable", "fieldtype": "Currency", "hidden": 0, @@ -1037,6 +1070,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_amount_paid", "fieldtype": "Currency", "hidden": 0, @@ -1070,6 +1104,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "amended_from", "fieldtype": "Link", "hidden": 0, @@ -1106,7 +1141,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-08-21 16:15:53.267145", + "modified": "2019-07-10 13:04:20.953694", "modified_by": "Administrator", "module": "HR", "name": "Loan", @@ -1149,7 +1184,6 @@ "set_user_permissions": 0, "share": 0, "submit": 0, - "user_permission_doctypes": "[\"Employee\"]", "write": 0 } ], diff --git a/erpnext/hr/doctype/loan/loan.py b/erpnext/hr/doctype/loan/loan.py index 58c9b8f6676..a803863124d 100644 --- a/erpnext/hr/doctype/loan/loan.py +++ b/erpnext/hr/doctype/loan/loan.py @@ -6,29 +6,33 @@ from __future__ import unicode_literals import frappe, math, json import erpnext from frappe import _ -from frappe.utils import flt, rounded, add_months, nowdate +from frappe.utils import flt, rounded, add_months, nowdate, getdate from erpnext.controllers.accounts_controller import AccountsController class Loan(AccountsController): def validate(self): - check_repayment_method(self.repayment_method, self.loan_amount, self.monthly_repayment_amount, self.repayment_periods) + validate_repayment_method(self.repayment_method, self.loan_amount, self.monthly_repayment_amount, self.repayment_periods) + self.set_missing_fields() + self.make_repayment_schedule() + self.set_repayment_period() + self.calculate_totals() + + def set_missing_fields(self): if not self.company: self.company = erpnext.get_default_company() + if not self.posting_date: self.posting_date = nowdate() + if self.loan_type and not self.rate_of_interest: self.rate_of_interest = frappe.db.get_value("Loan Type", self.loan_type, "rate_of_interest") + if self.repayment_method == "Repay Over Number of Periods": self.monthly_repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods) + if self.status == "Repaid/Closed": self.total_amount_paid = self.total_payment - if self.status == 'Disbursed' and self.repayment_start_date < self.disbursement_date: - frappe.throw(_("Repayment Start Date cannot be before Disbursement Date.")) - if self.status == "Disbursed": - self.make_repayment_schedule() - self.set_repayment_period() - self.calculate_totals() def make_jv_entry(self): self.check_permission('write') @@ -105,20 +109,31 @@ def update_total_amount_paid(doc): frappe.db.set_value("Loan", doc.name, "total_amount_paid", total_amount_paid) def update_disbursement_status(doc): - disbursement = frappe.db.sql("""select posting_date, ifnull(sum(credit_in_account_currency), 0) as disbursed_amount - from `tabGL Entry` where account = %s and against_voucher_type = 'Loan' and against_voucher = %s""", - (doc.payment_account, doc.name), as_dict=1)[0] - if disbursement.disbursed_amount == doc.loan_amount: - frappe.db.set_value("Loan", doc.name , "status", "Disbursed") - if disbursement.disbursed_amount == 0: - frappe.db.set_value("Loan", doc.name , "status", "Sanctioned") - if disbursement.disbursed_amount > doc.loan_amount: - frappe.throw(_("Disbursed Amount cannot be greater than Loan Amount {0}").format(doc.loan_amount)) - if disbursement.disbursed_amount > 0: - frappe.db.set_value("Loan", doc.name , "disbursement_date", disbursement.posting_date) - frappe.db.set_value("Loan", doc.name , "repayment_start_date", disbursement.posting_date) + disbursement = frappe.db.sql(""" + select posting_date, ifnull(sum(credit_in_account_currency), 0) as disbursed_amount + from `tabGL Entry` + where account = %s and against_voucher_type = 'Loan' and against_voucher = %s + """, (doc.payment_account, doc.name), as_dict=1)[0] -def check_repayment_method(repayment_method, loan_amount, monthly_repayment_amount, repayment_periods): + disbursement_date = None + if not disbursement or disbursement.disbursed_amount == 0: + status = "Sanctioned" + elif disbursement.disbursed_amount == doc.loan_amount: + disbursement_date = disbursement.posting_date + status = "Disbursed" + elif disbursement.disbursed_amount > doc.loan_amount: + frappe.throw(_("Disbursed Amount cannot be greater than Loan Amount {0}").format(doc.loan_amount)) + + if status == 'Disbursed' and getdate(disbursement_date) > getdate(frappe.db.get_value("Loan", doc.name, "repayment_start_date")): + frappe.throw(_("Disbursement Date cannot be after Loan Repayment Start Date")) + + frappe.db.sql(""" + update `tabLoan` + set status = %s, disbursement_date = %s + where name = %s + """, (status, disbursement_date, doc.name)) + +def validate_repayment_method(repayment_method, loan_amount, monthly_repayment_amount, repayment_periods): if repayment_method == "Repay Over Number of Periods" and not repayment_periods: frappe.throw(_("Please enter Repayment Periods")) @@ -222,4 +237,4 @@ def make_jv_entry(loan, company, loan_account, applicant_type, applicant, loan_a "reference_name": loan, }) journal_entry.set("accounts", account_amt_list) - return journal_entry.as_dict() \ No newline at end of file + return journal_entry.as_dict() diff --git a/erpnext/hr/doctype/loan_application/loan_application.js b/erpnext/hr/doctype/loan_application/loan_application.js index febcbd88e76..a73b62a894e 100644 --- a/erpnext/hr/doctype/loan_application/loan_application.js +++ b/erpnext/hr/doctype/loan_application/loan_application.js @@ -23,9 +23,8 @@ frappe.ui.form.on('Loan Application', { }, add_toolbar_buttons: function(frm) { if (frm.doc.status == "Approved") { - frm.add_custom_button(__('Loan'), function() { + frm.add_custom_button(__('Create Loan'), function() { frappe.call({ - type: "GET", method: "erpnext.hr.doctype.loan_application.loan_application.make_loan", args: { "source_name": frm.doc.name @@ -37,7 +36,7 @@ frappe.ui.form.on('Loan Application', { } } }); - }) + }).addClass("btn-primary"); } } }); diff --git a/erpnext/hr/doctype/loan_application/loan_application.py b/erpnext/hr/doctype/loan_application/loan_application.py index 706c9646c73..5dbcf15eac1 100644 --- a/erpnext/hr/doctype/loan_application/loan_application.py +++ b/erpnext/hr/doctype/loan_application/loan_application.py @@ -9,11 +9,11 @@ from frappe.utils import flt, rounded from frappe.model.mapper import get_mapped_doc from frappe.model.document import Document -from erpnext.hr.doctype.loan.loan import get_monthly_repayment_amount, check_repayment_method +from erpnext.hr.doctype.loan.loan import get_monthly_repayment_amount, validate_repayment_method class LoanApplication(Document): def validate(self): - check_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, self.repayment_periods) + validate_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, self.repayment_periods) self.validate_loan_amount() self.get_repayment_details() @@ -29,14 +29,14 @@ class LoanApplication(Document): if self.repayment_method == "Repay Fixed Amount per Period": monthly_interest_rate = flt(self.rate_of_interest) / (12 *100) if monthly_interest_rate: - self.repayment_periods = math.ceil((math.log(self.repayment_amount) - + self.repayment_periods = math.ceil((math.log(self.repayment_amount) - math.log(self.repayment_amount - (self.loan_amount*monthly_interest_rate))) / (math.log(1 + monthly_interest_rate))) else: self.repayment_periods = self.loan_amount / self.repayment_amount self.calculate_payable_amount() - + def calculate_payable_amount(self): balance_amount = self.loan_amount self.total_payable_amount = 0 @@ -47,9 +47,9 @@ class LoanApplication(Document): balance_amount = rounded(balance_amount + interest_amount - self.repayment_amount) self.total_payable_interest += interest_amount - + self.total_payable_amount = self.loan_amount + self.total_payable_interest - + @frappe.whitelist() def make_loan(source_name, target_doc = None): doclist = get_mapped_doc("Loan Application", source_name, {