fix: conflicts
diff --git a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
index 43acded..a9b3d7c 100644
--- a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
+++ b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe, json
from frappe import _
-from frappe.utils import add_to_date, date_diff, getdate, nowdate, get_last_day, formatdate
+from frappe.utils import add_to_date, date_diff, getdate, nowdate, get_last_day, formatdate, get_link_to_form
from erpnext.accounts.report.general_ledger.general_ledger import execute
from frappe.core.page.dashboard.dashboard import cache_source, get_from_date_from_timespan
from frappe.desk.doctype.dashboard_chart.dashboard_chart import get_period_ending
@@ -30,8 +30,13 @@
account = filters.get("account")
company = filters.get("company")
- if not account and chart:
- frappe.throw(_("Account is not set for the dashboard chart {0}").format(chart))
+ if not account and chart_name:
+ frappe.throw(_("Account is not set for the dashboard chart {0}")
+ .format(get_link_to_form("Dashboard Chart", chart_name)))
+
+ if not frappe.db.exists("Account", account) and chart_name:
+ frappe.throw(_("Account {0} does not exists in the dashboard chart {1}")
+ .format(account, get_link_to_form("Dashboard Chart", chart_name)))
if not to_date:
to_date = nowdate()
diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py
index 62a8f05..3b6a588 100644
--- a/erpnext/accounts/deferred_revenue.py
+++ b/erpnext/accounts/deferred_revenue.py
@@ -30,7 +30,7 @@
frappe.throw(_("Service Stop Date cannot be after Service End Date"))
if old_stop_dates and old_stop_dates.get(item.name) and item.service_stop_date!=old_stop_dates.get(item.name):
- frappe.throw(_("Cannot change Service Stop Date for item in row {0}".format(item.idx)))
+ frappe.throw(_("Cannot change Service Stop Date for item in row {0}").format(item.idx))
def convert_deferred_expense_to_expense(start_date=None, end_date=None):
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03_gnucash.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03_gnucash.json
new file mode 100644
index 0000000..89465ee
--- /dev/null
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03_gnucash.json
@@ -0,0 +1,526 @@
+{
+ "country_code": "de",
+ "name": "SKR03 mit Kontonummern",
+ "tree": {
+ "Aktiva": {
+ "is_group": 1,
+ "root_type": "Asset",
+ "A - Anlagevermögen": {
+ "is_group": 1,
+ "EDV-Software": {
+ "account_number": "0027",
+ "account_type": "Fixed Asset"
+ },
+ "Gesch\u00e4ftsausstattung": {
+ "account_number": "0410",
+ "account_type": "Fixed Asset"
+ },
+ "B\u00fcroeinrichtung": {
+ "account_number": "0420",
+ "account_type": "Fixed Asset"
+ },
+ "Darlehen": {
+ "account_number": "0565"
+ },
+ "Maschinen": {
+ "account_number": "0210",
+ "account_type": "Fixed Asset"
+ },
+ "Betriebsausstattung": {
+ "account_number": "0400",
+ "account_type": "Fixed Asset"
+ },
+ "Ladeneinrichtung": {
+ "account_number": "0430",
+ "account_type": "Fixed Asset"
+ },
+ "Accumulated Depreciation": {
+ "account_type": "Accumulated Depreciation"
+ }
+ },
+ "B - Umlaufvermögen": {
+ "is_group": 1,
+ "I. Vorräte": {
+ "is_group": 1,
+ "Roh-, Hilfs- und Betriebsstoffe (Bestand)": {
+ "account_number": "3970",
+ "account_type": "Stock"
+ },
+ "Waren (Bestand)": {
+ "account_number": "3980",
+ "account_type": "Stock"
+ }
+ },
+ "II. Forderungen und sonstige Vermögensgegenstände": {
+ "is_group": 1,
+ "Ford. a. Lieferungen und Leistungen": {
+ "account_number": "1400",
+ "account_type": "Receivable"
+ },
+ "Durchlaufende Posten": {
+ "account_number": "1590"
+ },
+ "Gewinnermittlung \u00a74/3 nicht Ergebniswirksam": {
+ "account_number": "1371"
+ },
+ "Abziehbare VSt. 7%": {
+ "account_number": "1571"
+ },
+ "Abziehbare VSt. 19%": {
+ "account_number": "1576"
+ },
+ "Abziehbare VStr. nach \u00a713b UStG 19%": {
+ "account_number": "1577"
+ },
+ "Leistungen \u00a713b UStG 19% Vorsteuer, 19% Umsatzsteuer": {
+ "account_number": "3120"
+ }
+ },
+ "III. Wertpapiere": {
+ "is_group": 1
+ },
+ "IV. Kassenbestand, Bundesbankguthaben, Guthaben bei Kreditinstituten und Schecks.": {
+ "is_group": 1,
+ "Kasse": {
+ "account_type": "Cash",
+ "is_group": 1,
+ "Kasse": {
+ "is_group": 1,
+ "account_number": "1000",
+ "account_type": "Cash"
+ }
+ },
+ "Bank": {
+ "is_group": 1,
+ "account_type": "Bank",
+ "Postbank": {
+ "account_number": "1100",
+ "account_type": "Bank"
+ },
+ "Bankkonto": {
+ "account_number": "1200",
+ "account_type": "Bank"
+ }
+ }
+ }
+ },
+ "C - Rechnungsabgrenzungsposten": {
+ "is_group": 1,
+ "Aktive Rechnungsabgrenzung": {
+ "account_number": "0980"
+ }
+ },
+ "D - Aktive latente Steuern": {
+ "is_group": 1,
+ "Aktive latente Steuern": {
+ "account_number": "0983"
+ }
+ },
+ "E - Aktiver Unterschiedsbetrag aus der Vermögensverrechnung": {
+ "is_group": 1
+ }
+ },
+ "Passiva": {
+ "is_group": 1,
+ "root_type": "Liability",
+ "A. Eigenkapital": {
+ "is_group": 1,
+ "I. Gezeichnetes Kapital": {
+ "is_group": 1
+ },
+ "II. Kapitalrücklage": {
+ "is_group": 1
+ },
+ "III. Gewinnrücklagen": {
+ "is_group": 1
+ },
+ "IV. Gewinnvortrag/Verlustvortrag": {
+ "is_group": 1
+ },
+ "V. Jahresüberschuß/Jahresfehlbetrag": {
+ "is_group": 1
+ }
+ },
+ "B. Rückstellungen": {
+ "is_group": 1,
+ "I. Rückstellungen für Pensionen und ähnliche Verpflichtungen": {
+ "is_group": 1
+ },
+ "II. Steuerrückstellungen": {
+ "is_group": 1
+ },
+ "III. sonstige Rückstellungen": {
+ "is_group": 1
+ }
+ },
+ "C. Verbindlichkeiten": {
+ "is_group": 1,
+ "I. Anleihen": {
+ "is_group": 1
+ },
+ "II. Verbindlichkeiten gegenüber Kreditinstituten": {
+ "is_group": 1
+ },
+ "III. Erhaltene Anzahlungen auf Bestellungen": {
+ "is_group": 1
+ },
+ "IV. Verbindlichkeiten aus Lieferungen und Leistungen": {
+ "is_group": 1,
+ "Verbindlichkeiten aus Lieferungen u. Leistungen": {
+ "account_number": "1600",
+ "account_type": "Payable"
+ }
+ },
+ "V. Verbindlichkeiten aus der Annahme gezogener Wechsel und der Ausstellung eigener Wechsel": {
+ "is_group": 1
+ },
+ "VI. Verbindlichkeiten gegenüber verbundenen Unternehmen": {
+ "is_group": 1
+ },
+ "VII. Verbindlichkeiten gegenüber Unternehmen, mit denen ein Beteiligungsverhältnis besteht": {
+ "is_group": 1
+ },
+ "VIII. sonstige Verbindlichkeiten": {
+ "is_group": 1,
+ "Sonstige Verbindlichkeiten": {
+ "account_number": "1700",
+ "account_type": "Asset Received But Not Billed"
+ },
+ "Sonstige Verbindlichkeiten (1 bis 5 Jahre)": {
+ "account_number": "1702",
+ "account_type": "Stock Received But Not Billed"
+ },
+ "Verbindlichkeiten aus Lohn und Gehalt": {
+ "account_number": "1740",
+ "account_type": "Payable"
+ },
+ "Umsatzsteuer": {
+ "is_group": 1,
+ "Umsatzsteuer 7%": {
+ "account_number": "1771"
+ },
+ "Umsatzsteuer 19%": {
+ "account_number": "1776"
+ },
+ "Umsatzsteuer-Vorauszahlung": {
+ "account_number": "1780"
+ },
+ "Umsatzsteuer-Vorauszahlung 1/11": {
+ "account_number": "1781"
+ },
+ "Umsatzsteuer \u00a7 13b UStG 19%": {
+ "account_number": "1787"
+ },
+ "Umsatzsteuer Vorjahr": {
+ "account_number": "1790"
+ },
+ "Umsatzsteuer fr\u00fchere Jahre": {
+ "account_number": "1791"
+ }
+ }
+ }
+ },
+ "D. Rechnungsabgrenzungsposten": {
+ "is_group": 1,
+ "Passive Rechnungsabgrenzung": {
+ "account_number": "0990"
+ }
+ },
+ "E. Passive latente Steuern": {
+ "is_group": 1
+ }
+ },
+ "Erl\u00f6se u. Ertr\u00e4ge 2/8": {
+ "is_group": 1,
+ "root_type": "Income",
+ "Erl\u00f6skonten 8": {
+ "is_group": 1,
+ "Erl\u00f6se": {
+ "account_number": "8200",
+ "account_type": "Income Account"
+ },
+ "Erl\u00f6se USt. 19%": {
+ "account_number": "8400",
+ "account_type": "Income Account"
+ },
+ "Erl\u00f6se USt. 7%": {
+ "account_number": "8300",
+ "account_type": "Income Account"
+ }
+ },
+ "Ertragskonten 2": {
+ "is_group": 1,
+ "sonstige Zinsen und \u00e4hnliche Ertr\u00e4ge": {
+ "account_number": "2650",
+ "account_type": "Income Account"
+ },
+ "Au\u00dferordentliche Ertr\u00e4ge": {
+ "account_number": "2500",
+ "account_type": "Income Account"
+ },
+ "Sonstige Ertr\u00e4ge": {
+ "account_number": "2700",
+ "account_type": "Income Account"
+ }
+ }
+ },
+ "Aufwendungen 2/4": {
+ "is_group": 1,
+ "root_type": "Expense",
+ "Wareneingang": {
+ "account_number": "3200"
+ },
+ "Bezugsnebenkosten": {
+ "account_number": "3800",
+ "account_type": "Expenses Included In Asset Valuation"
+ },
+ "Herstellungskosten": {
+ "account_number": "4996",
+ "account_type": "Cost of Goods Sold"
+ },
+ "Verluste aus dem Abgang von Gegenständen des Anlagevermögens": {
+ "account_number": "2320",
+ "account_type": "Stock Adjustment"
+ },
+ "Verwaltungskosten": {
+ "account_number": "4997",
+ "account_type": "Expenses Included In Valuation"
+ },
+ "Vertriebskosten": {
+ "account_number": "4998",
+ "account_type": "Expenses Included In Valuation"
+ },
+ "Gegenkonto 4996-4998": {
+ "account_number": "4999"
+ },
+ "Abschreibungen": {
+ "is_group": 1,
+ "Abschreibungen auf Sachanlagen (ohne AfA auf Kfz und Gebäude)": {
+ "account_number": "4830",
+ "account_type": "Accumulated Depreciation"
+ },
+ "Abschreibungen auf Gebäude": {
+ "account_number": "4831",
+ "account_type": "Depreciation"
+ },
+ "Abschreibungen auf Kfz": {
+ "account_number": "4832",
+ "account_type": "Depreciation"
+ },
+ "Sofortabschreibung GWG": {
+ "account_number": "4855",
+ "account_type": "Expense Account"
+ }
+ },
+ "Kfz-Kosten": {
+ "is_group": 1,
+ "Kfz-Steuer": {
+ "account_number": "4510",
+ "account_type": "Expense Account"
+ },
+ "Kfz-Versicherungen": {
+ "account_number": "4520",
+ "account_type": "Expense Account"
+ },
+ "laufende Kfz-Betriebskosten": {
+ "account_number": "4530",
+ "account_type": "Expense Account"
+ },
+ "Kfz-Reparaturen": {
+ "account_number": "4540",
+ "account_type": "Expense Account"
+ },
+ "Fremdfahrzeuge": {
+ "account_number": "4570",
+ "account_type": "Expense Account"
+ },
+ "sonstige Kfz-Kosten": {
+ "account_number": "4580",
+ "account_type": "Expense Account"
+ }
+ },
+ "Personalkosten": {
+ "is_group": 1,
+ "Geh\u00e4lter": {
+ "account_number": "4120",
+ "account_type": "Expense Account"
+ },
+ "gesetzliche soziale Aufwendungen": {
+ "account_number": "4130",
+ "account_type": "Expense Account"
+ },
+ "Aufwendungen f\u00fcr Altersvorsorge": {
+ "account_number": "4165",
+ "account_type": "Expense Account"
+ },
+ "Verm\u00f6genswirksame Leistungen": {
+ "account_number": "4170",
+ "account_type": "Expense Account"
+ },
+ "Aushilfsl\u00f6hne": {
+ "account_number": "4190",
+ "account_type": "Expense Account"
+ }
+ },
+ "Raumkosten": {
+ "is_group": 1,
+ "Miete und Nebenkosten": {
+ "account_number": "4210",
+ "account_type": "Expense Account"
+ },
+ "Gas, Wasser, Strom (Verwaltung, Vertrieb)": {
+ "account_number": "4240",
+ "account_type": "Expense Account"
+ },
+ "Reinigung": {
+ "account_number": "4250",
+ "account_type": "Expense Account"
+ }
+ },
+ "Reparatur/Instandhaltung": {
+ "is_group": 1,
+ "Reparatur u. Instandh. von Anlagen/Maschinen u. Betriebs- u. Gesch\u00e4ftsausst.": {
+ "account_number": "4805",
+ "account_type": "Expense Account"
+ }
+ },
+ "Versicherungsbeitr\u00e4ge": {
+ "is_group": 1,
+ "Versicherungen": {
+ "account_number": "4360",
+ "account_type": "Expense Account"
+ },
+ "Beitr\u00e4ge": {
+ "account_number": "4380",
+ "account_type": "Expense Account"
+ },
+ "sonstige Ausgaben": {
+ "account_number": "4390",
+ "account_type": "Expense Account"
+ },
+ "steuerlich abzugsf\u00e4hige Versp\u00e4tungszuschl\u00e4ge und Zwangsgelder": {
+ "account_number": "4396",
+ "account_type": "Expense Account"
+ }
+ },
+ "Werbe-/Reisekosten": {
+ "is_group": 1,
+ "Werbekosten": {
+ "account_number": "4610",
+ "account_type": "Expense Account"
+ },
+ "Aufmerksamkeiten": {
+ "account_number": "4653",
+ "account_type": "Expense Account"
+ },
+ "nicht abzugsf\u00e4hige Betriebsausg. aus Werbe-, Repr\u00e4s.- u. Reisekosten": {
+ "account_number": "4665",
+ "account_type": "Expense Account"
+ },
+ "Reisekosten Unternehmer": {
+ "account_number": "4670",
+ "account_type": "Expense Account"
+ }
+ },
+ "verschiedene Kosten": {
+ "is_group": 1,
+ "Porto": {
+ "account_number": "4910",
+ "account_type": "Expense Account"
+ },
+ "Telekom": {
+ "account_number": "4920",
+ "account_type": "Expense Account"
+ },
+ "Mobilfunk D2": {
+ "account_number": "4921",
+ "account_type": "Expense Account"
+ },
+ "Internet": {
+ "account_number": "4922",
+ "account_type": "Expense Account"
+ },
+ "B\u00fcrobedarf": {
+ "account_number": "4930",
+ "account_type": "Expense Account"
+ },
+ "Zeitschriften, B\u00fccher": {
+ "account_number": "4940",
+ "account_type": "Expense Account"
+ },
+ "Fortbildungskosten": {
+ "account_number": "4945",
+ "account_type": "Expense Account"
+ },
+ "Buchf\u00fchrungskosten": {
+ "account_number": "4955",
+ "account_type": "Expense Account"
+ },
+ "Abschlu\u00df- u. Pr\u00fcfungskosten": {
+ "account_number": "4957",
+ "account_type": "Expense Account"
+ },
+ "Nebenkosten des Geldverkehrs": {
+ "account_number": "4970",
+ "account_type": "Expense Account"
+ },
+ "Werkzeuge und Kleinger\u00e4te": {
+ "account_number": "4985",
+ "account_type": "Expense Account"
+ }
+ },
+ "Zinsaufwendungen": {
+ "is_group": 1,
+ "Zinsaufwendungen f\u00fcr kurzfristige Verbindlichkeiten": {
+ "account_number": "2110",
+ "account_type": "Expense Account"
+ },
+ "Zinsaufwendungen f\u00fcr KFZ Finanzierung": {
+ "account_number": "2121",
+ "account_type": "Expense Account"
+ }
+ }
+ },
+ "Anfangsbestand 9": {
+ "is_group": 1,
+ "root_type": "Equity",
+ "Saldenvortragskonten": {
+ "is_group": 1,
+ "Saldenvortrag Sachkonten": {
+ "account_number": "9000"
+ },
+ "Saldenvortr\u00e4ge Debitoren": {
+ "account_number": "9008"
+ },
+ "Saldenvortr\u00e4ge Kreditoren": {
+ "account_number": "9009"
+ }
+ }
+ },
+ "Privatkonten 1": {
+ "is_group": 1,
+ "root_type": "Equity",
+ "Privatentnahmen/-einlagen": {
+ "is_group": 1,
+ "Privatentnahme allgemein": {
+ "account_number": "1800"
+ },
+ "Privatsteuern": {
+ "account_number": "1810"
+ },
+ "Sonderausgaben beschr\u00e4nkt abzugsf\u00e4hig": {
+ "account_number": "1820"
+ },
+ "Sonderausgaben unbeschr\u00e4nkt abzugsf\u00e4hig": {
+ "account_number": "1830"
+ },
+ "Au\u00dfergew\u00f6hnliche Belastungen": {
+ "account_number": "1850"
+ },
+ "Privateinlagen": {
+ "account_number": "1890"
+ }
+ }
+ }
+ }
+}
diff --git a/erpnext/accounts/doctype/bank_account/bank_account.json b/erpnext/accounts/doctype/bank_account/bank_account.json
index 8e30b85..c8ae26d 100644
--- a/erpnext/accounts/doctype/bank_account/bank_account.json
+++ b/erpnext/accounts/doctype/bank_account/bank_account.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"allow_import": 1,
"allow_rename": 1,
"creation": "2017-05-29 21:35:13.136357",
@@ -82,7 +83,7 @@
"default": "0",
"fieldname": "is_default",
"fieldtype": "Check",
- "label": "Is the Default Account"
+ "label": "Is Default Account"
},
{
"default": "0",
@@ -211,7 +212,8 @@
"read_only": 1
}
],
- "modified": "2019-10-02 01:34:12.417601",
+ "links": [],
+ "modified": "2020-01-29 20:42:26.458316",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account",
diff --git a/erpnext/accounts/doctype/bank_account/test_bank_account.py b/erpnext/accounts/doctype/bank_account/test_bank_account.py
index f3bb086..ed34d17 100644
--- a/erpnext/accounts/doctype/bank_account/test_bank_account.py
+++ b/erpnext/accounts/doctype/bank_account/test_bank_account.py
@@ -31,7 +31,7 @@
try:
bank_account.validate_iban()
except AttributeError:
- msg = _('BankAccount.validate_iban() failed for empty IBAN')
+ msg = 'BankAccount.validate_iban() failed for empty IBAN'
self.fail(msg=msg)
for iban in valid_ibans:
@@ -39,11 +39,11 @@
try:
bank_account.validate_iban()
except ValidationError:
- msg = _('BankAccount.validate_iban() failed for valid IBAN {}'.format(iban))
+ msg = 'BankAccount.validate_iban() failed for valid IBAN {}'.format(iban)
self.fail(msg=msg)
for not_iban in invalid_ibans:
bank_account.iban = not_iban
- msg = _('BankAccount.validate_iban() accepted invalid IBAN {}'.format(not_iban))
+ msg = 'BankAccount.validate_iban() accepted invalid IBAN {}'.format(not_iban)
with self.assertRaises(ValidationError, msg=msg):
bank_account.validate_iban()
diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.js b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.js
index 7c94455..19fadbf 100644
--- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.js
+++ b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.js
@@ -3,16 +3,16 @@
frappe.ui.form.on("Bank Reconciliation", {
setup: function(frm) {
- frm.add_fetch("bank_account", "account_currency", "account_currency");
+ frm.add_fetch("account", "account_currency", "account_currency");
},
onload: function(frm) {
let default_bank_account = frappe.defaults.get_user_default("Company")?
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "";
- frm.set_value("bank_account", default_bank_account);
+ frm.set_value("account", default_bank_account);
- frm.set_query("bank_account", function() {
+ frm.set_query("account", function() {
return {
"filters": {
"account_type": ["in",["Bank","Cash"]],
diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json
index e2f967d..b85ef3e 100644
--- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json
+++ b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json
@@ -19,10 +19,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "description": "Select account head of the bank where cheque was deposited.",
- "fetch_from": "bank_account_no.account",
+ "fetch_from": "bank_account.account",
"fetch_if_empty": 1,
- "fieldname": "bank_account",
+ "fieldname": "account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -31,7 +30,7 @@
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
- "label": "Bank Account",
+ "label": "Account",
"length": 0,
"no_copy": 0,
"options": "Account",
@@ -164,7 +163,6 @@
"length": 0,
"no_copy": 0,
"permlevel": 0,
- "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -183,8 +181,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "description": "Select the Bank Account to reconcile.",
"fetch_if_empty": 0,
- "fieldname": "bank_account_no",
+ "fieldname": "bank_account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -193,12 +192,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Bank Account No",
+ "label": "Bank Account",
"length": 0,
"no_copy": 0,
"options": "Bank Account",
"permlevel": 0,
- "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -450,7 +448,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2019-04-09 18:41:06.110453",
+ "modified": "2020-01-22 00:00:00.000000",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Reconciliation",
@@ -483,4 +481,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
-}
\ No newline at end of file
+}
diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py
index 90cdf83..2436b15 100644
--- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py
+++ b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py
@@ -13,18 +13,16 @@
class BankReconciliation(Document):
def get_payment_entries(self):
- if not (self.bank_account and self.from_date and self.to_date):
- msgprint(_("Bank Account, From Date and To Date are Mandatory"))
- return
+ if not (self.from_date and self.to_date):
+ frappe.throw(_("From Date and To Date are Mandatory"))
+
+ if not self.account:
+ frappe.throw(_("Account is mandatory to get payment entries"))
condition = ""
if not self.include_reconciled_entries:
condition = " and (clearance_date is null or clearance_date='0000-00-00')"
- account_cond = ""
- if self.bank_account_no:
- account_cond = " and t2.bank_account_no = {0}".format(frappe.db.escape(self.bank_account_no))
-
journal_entries = frappe.db.sql("""
select
"Journal Entry" as payment_document, t1.name as payment_entry,
@@ -34,15 +32,17 @@
from
`tabJournal Entry` t1, `tabJournal Entry Account` t2
where
- t2.parent = t1.name and t2.account = %s and t1.docstatus=1
- and t1.posting_date >= %s and t1.posting_date <= %s
- and ifnull(t1.is_opening, 'No') = 'No' {0} {1}
+ t2.parent = t1.name and t2.account = %(account)s and t1.docstatus=1
+ and t1.posting_date >= %(from)s and t1.posting_date <= %(to)s
+ and ifnull(t1.is_opening, 'No') = 'No' %(condition)s
group by t2.account, t1.name
order by t1.posting_date ASC, t1.name DESC
- """.format(condition, account_cond), (self.bank_account, self.from_date, self.to_date), as_dict=1)
+ """, {"condition":condition, "account": self.account, "from": self.from_date, "to": self.to_date}, as_dict=1)
- if self.bank_account_no:
- condition = " and bank_account = %(bank_account_no)s"
+ condition = ''
+
+ if self.bank_account:
+ condition += 'and bank_account = %(bank_account)s'
payment_entries = frappe.db.sql("""
select
@@ -55,12 +55,12 @@
from `tabPayment Entry`
where
(paid_from=%(account)s or paid_to=%(account)s) and docstatus=1
- and posting_date >= %(from)s and posting_date <= %(to)s {0}
+ and posting_date >= %(from)s and posting_date <= %(to)s
+ {condition}
order by
posting_date ASC, name DESC
- """.format(condition),
- {"account":self.bank_account, "from":self.from_date,
- "to":self.to_date, "bank_account_no": self.bank_account_no}, as_dict=1)
+ """.format(condition=condition), {"account": self.account, "from":self.from_date,
+ "to": self.to_date, "bank_account": self.bank_account}, as_dict=1)
pos_entries = []
if self.include_pos_transactions:
@@ -72,11 +72,10 @@
from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account
where
sip.account=%(account)s and si.docstatus=1 and sip.parent = si.name
- and account.name = sip.account and si.posting_date >= %(from)s and si.posting_date <= %(to)s {0}
+ and account.name = sip.account and si.posting_date >= %(from)s and si.posting_date <= %(to)s
order by
si.posting_date ASC, si.name DESC
- """.format(condition),
- {"account":self.bank_account, "from":self.from_date, "to":self.to_date}, as_dict=1)
+ """, {"account":self.account, "from":self.from_date, "to":self.to_date}, as_dict=1)
entries = sorted(list(payment_entries)+list(journal_entries+list(pos_entries)),
key=lambda k: k['posting_date'] or getdate(nowdate()))
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 1318cf1..5b6eb9d 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
@@ -314,7 +314,7 @@
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:
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index b8ebeba..0e45db3 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -49,7 +49,7 @@
if paid_amount and allocated_amount:
if flt(allocated_amount[0]["allocated_amount"]) > flt(paid_amount):
- frappe.throw(_("The total allocated amount ({0}) is greated than the paid amount ({1}).".format(flt(allocated_amount[0]["allocated_amount"]), flt(paid_amount))))
+ frappe.throw(_("The total allocated amount ({0}) is greated than the paid amount ({1}).").format(flt(allocated_amount[0]["allocated_amount"]), flt(paid_amount)))
else:
if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]:
self.clear_simple_entry(payment_entry)
diff --git a/erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.json b/erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.json
index a75e866..ab3f60d 100644
--- a/erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.json
+++ b/erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.json
@@ -110,6 +110,15 @@
"set_only_once": 0,
"translatable": 0,
"unique": 0
+ },
+ {
+ "depends_on": "eval:doc.docstatus==1",
+ "fieldname": "clearance_date",
+ "fieldtype": "Date",
+ "label": "Clearance Date",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
}
],
"has_web_view": 0,
@@ -122,7 +131,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2018-12-06 10:57:02.635141",
+ "modified": "2020-01-22 00:00:00.000000",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Transaction Payments",
@@ -138,4 +147,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
-}
\ No newline at end of file
+}
diff --git a/erpnext/accounts/doctype/budget/budget.py b/erpnext/accounts/doctype/budget/budget.py
index b76cdf3..084514c 100644
--- a/erpnext/accounts/doctype/budget/budget.py
+++ b/erpnext/accounts/doctype/budget/budget.py
@@ -210,10 +210,10 @@
item_code = args.get('item_code')
condition = get_other_condition(args, budget, 'Material Request')
- data = frappe.db.sql(""" select ifnull((sum(mri.stock_qty - mri.ordered_qty) * rate), 0) as amount
- from `tabMaterial Request Item` mri, `tabMaterial Request` mr where mr.name = mri.parent and
- mri.item_code = %s and mr.docstatus = 1 and mri.stock_qty > mri.ordered_qty and {0} and
- mr.material_request_type = 'Purchase' and mr.status != 'Stopped'""".format(condition), item_code, as_list=1)
+ data = frappe.db.sql(""" select ifnull((sum(child.stock_qty - child.ordered_qty) * rate), 0) as amount
+ from `tabMaterial Request Item` child, `tabMaterial Request` parent where parent.name = child.parent and
+ child.item_code = %s and parent.docstatus = 1 and child.stock_qty > child.ordered_qty and {0} and
+ parent.material_request_type = 'Purchase' and parent.status != 'Stopped'""".format(condition), item_code, as_list=1)
return data[0][0] if data else 0
@@ -221,10 +221,10 @@
item_code = args.get('item_code')
condition = get_other_condition(args, budget, 'Purchase Order')
- data = frappe.db.sql(""" select ifnull(sum(poi.amount - poi.billed_amt), 0) as amount
- from `tabPurchase Order Item` poi, `tabPurchase Order` po where
- po.name = poi.parent and poi.item_code = %s and po.docstatus = 1 and poi.amount > poi.billed_amt
- and po.status != 'Closed' and {0}""".format(condition), item_code, as_list=1)
+ data = frappe.db.sql(""" select ifnull(sum(child.amount - child.billed_amt), 0) as amount
+ from `tabPurchase Order Item` child, `tabPurchase Order` parent where
+ parent.name = child.parent and child.item_code = %s and parent.docstatus = 1 and child.amount > child.billed_amt
+ and parent.status != 'Closed' and {0}""".format(condition), item_code, as_list=1)
return data[0][0] if data else 0
@@ -233,16 +233,15 @@
budget_against_field = frappe.scrub(args.get("budget_against_field"))
if budget_against_field and args.get(budget_against_field):
- condition += " and %s = '%s'" %(budget_against_field, args.get(budget_against_field))
+ condition += " and child.%s = '%s'" %(budget_against_field, args.get(budget_against_field))
if args.get('fiscal_year'):
date_field = 'schedule_date' if for_doc == 'Material Request' else 'transaction_date'
start_date, end_date = frappe.db.get_value('Fiscal Year', args.get('fiscal_year'),
['year_start_date', 'year_end_date'])
- alias = 'mr' if for_doc == 'Material Request' else 'po'
- condition += """ and %s.%s
- between '%s' and '%s' """ %(alias, date_field, start_date, end_date)
+ condition += """ and parent.%s
+ between '%s' and '%s' """ %(date_field, start_date, end_date)
return condition
diff --git a/erpnext/accounts/doctype/c_form/c_form.py b/erpnext/accounts/doctype/c_form/c_form.py
index 2dcf958..9b64f81 100644
--- a/erpnext/accounts/doctype/c_form/c_form.py
+++ b/erpnext/accounts/doctype/c_form/c_form.py
@@ -18,7 +18,7 @@
`tabSales Invoice` where name = %s and docstatus = 1""", d.invoice_no)
if inv and inv[0][0] != 'Yes':
- frappe.throw(_("C-form is not applicable for Invoice: {0}".format(d.invoice_no)))
+ frappe.throw(_("C-form is not applicable for Invoice: {0}").format(d.invoice_no))
elif inv and inv[0][1] and inv[0][1] != self.name:
frappe.throw(_("""Invoice {0} is tagged in another C-form: {1}.
diff --git a/erpnext/accounts/doctype/cost_center/cost_center.json b/erpnext/accounts/doctype/cost_center/cost_center.json
index 5149be2..976f05a 100644
--- a/erpnext/accounts/doctype/cost_center/cost_center.json
+++ b/erpnext/accounts/doctype/cost_center/cost_center.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"allow_copy": 1,
"allow_import": 1,
"allow_rename": 1,
@@ -123,7 +124,8 @@
],
"icon": "fa fa-money",
"idx": 1,
- "modified": "2019-09-16 14:44:17.103548",
+ "links": [],
+ "modified": "2020-01-28 13:50:23.430434",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cost Center",
@@ -162,7 +164,6 @@
"role": "Purchase User"
}
],
- "quick_entry": 1,
"search_fields": "parent_cost_center, is_group",
"show_name_in_global_search": 1,
"sort_field": "modified",
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json
index a232a95..e64bc9e 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.json
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json
@@ -1,971 +1,286 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
"autoname": "ACC-GLE-.YYYY.-.#####",
- "beta": 0,
"creation": "2013-01-10 16:34:06",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
- "editable_grid": 0,
+ "engine": "InnoDB",
+ "field_order": [
+ "posting_date",
+ "transaction_date",
+ "account",
+ "party_type",
+ "party",
+ "cost_center",
+ "debit",
+ "credit",
+ "account_currency",
+ "debit_in_account_currency",
+ "credit_in_account_currency",
+ "against",
+ "against_voucher_type",
+ "against_voucher",
+ "voucher_type",
+ "voucher_no",
+ "voucher_detail_no",
+ "project",
+ "remarks",
+ "is_opening",
+ "is_advance",
+ "fiscal_year",
+ "company",
+ "finance_book",
+ "to_rename",
+ "due_date"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "posting_date",
"fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Posting Date",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "posting_date",
"oldfieldtype": "Date",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "transaction_date",
"fieldtype": "Date",
- "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": "Transaction Date",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "transaction_date",
- "oldfieldtype": "Date",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "oldfieldtype": "Date"
},
{
- "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": 1,
- "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Account",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "account",
"oldfieldtype": "Link",
"options": "Account",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "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,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "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": 1,
"label": "Party",
- "length": 0,
- "no_copy": 0,
"options": "party_type",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "cost_center",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Cost Center",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "cost_center",
"oldfieldtype": "Link",
- "options": "Cost Center",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Cost Center"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "debit",
"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": "Debit Amount",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "debit",
"oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Company:company:default_currency"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "credit",
"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": "Credit Amount",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "credit",
"oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Company:company:default_currency"
},
{
- "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": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Currency"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "debit_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": "Debit Amount in Account Currency",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "currency"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "credit_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": "Credit Amount in Account Currency",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "currency"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "against",
"fieldtype": "Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Against",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "against",
- "oldfieldtype": "Text",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "oldfieldtype": "Text"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "against_voucher_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": "Against Voucher Type",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "against_voucher_type",
"oldfieldtype": "Data",
"options": "DocType",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "against_voucher",
"fieldtype": "Dynamic Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Against Voucher",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "against_voucher",
"oldfieldtype": "Data",
"options": "against_voucher_type",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "voucher_type",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Voucher Type",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "voucher_type",
"oldfieldtype": "Select",
"options": "DocType",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "voucher_no",
"fieldtype": "Dynamic Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
"in_standard_filter": 1,
"label": "Voucher No",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "voucher_no",
"oldfieldtype": "Data",
"options": "voucher_type",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "voucher_detail_no",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Voucher Detail No",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "project",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Project",
- "length": 0,
- "no_copy": 0,
- "options": "Project",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Project"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "remarks",
"fieldtype": "Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Remarks",
- "length": 0,
"no_copy": 1,
"oldfieldname": "remarks",
- "oldfieldtype": "Text",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "oldfieldtype": "Text"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "is_opening",
"fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Is Opening",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "is_opening",
"oldfieldtype": "Select",
- "options": "No\nYes",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "No\nYes"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "is_advance",
"fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Is Advance",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "is_advance",
"oldfieldtype": "Select",
- "options": "No\nYes",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "No\nYes"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "fiscal_year",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Fiscal Year",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "fiscal_year",
"oldfieldtype": "Select",
- "options": "Fiscal Year",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Fiscal Year"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "company",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Company",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "company",
"oldfieldtype": "Link",
"options": "Company",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "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
+ "options": "Finance Book"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "1",
"fieldname": "to_rename",
"fieldtype": "Check",
"hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "To Rename",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "due_date",
"fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Due Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Due Date"
}
],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
"icon": "fa fa-list",
"idx": 1,
- "image_view": 0,
"in_create": 1,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-05-01 07:05:00.366399",
+ "modified": "2020-02-10 04:54:57.777905",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",
"owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 1,
"export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
- "role": "Accounts User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Accounts User"
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 1,
"export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
- "role": "Accounts Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Accounts Manager"
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
"export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 0,
"read": 1,
"report": 1,
- "role": "Auditor",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Auditor"
}
],
"quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
"search_fields": "voucher_no,account,posting_date,against_voucher",
- "show_name_in_global_search": 0,
"sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ "sort_order": "DESC"
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 8897337..4491f7a 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -9,7 +9,6 @@
from erpnext.accounts.utils import get_balance_on, get_account_currency
from erpnext.accounts.party import get_party_account
from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount
-from erpnext.hr.doctype.loan.loan import update_disbursement_status, update_total_amount_paid
from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get_party_account_based_on_invoice_discounting
from six import string_types, iteritems
@@ -50,7 +49,6 @@
self.make_gl_entries()
self.update_advance_paid()
self.update_expense_claim()
- self.update_loan()
self.update_inter_company_jv()
self.update_invoice_discounting()
@@ -62,7 +60,6 @@
self.make_gl_entries(1)
self.update_advance_paid()
self.update_expense_claim()
- self.update_loan()
self.unlink_advance_entry_reference()
self.unlink_asset_reference()
self.unlink_inter_company_jv()
@@ -597,17 +594,6 @@
doc = frappe.get_doc("Expense Claim", d.reference_name)
update_reimbursed_amount(doc)
- def update_loan(self):
- if self.paid_loan:
- paid_loan = json.loads(self.paid_loan)
- value = 1 if self.docstatus < 2 else 0
- for name in paid_loan:
- frappe.db.set_value("Repayment Schedule", name, "paid", value)
- for d in self.accounts:
- if d.reference_type=="Loan" and flt(d.debit) > 0:
- doc = frappe.get_doc("Loan", d.reference_name)
- update_disbursement_status(doc)
- update_total_amount_paid(doc)
def validate_expense_claim(self):
for d in self.accounts:
@@ -616,7 +602,7 @@
d.reference_name, ("total_sanctioned_amount", "total_amount_reimbursed"))
pending_amount = flt(sanctioned_amount) - flt(reimbursed_amount)
if d.debit > pending_amount:
- frappe.throw(_("Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. Pending Amount is {2}".format(d.idx, d.reference_name, pending_amount)))
+ frappe.throw(_("Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. Pending Amount is {2}").format(d.idx, d.reference_name, pending_amount))
def validate_credit_debit_note(self):
if self.stock_entry:
@@ -624,7 +610,7 @@
frappe.throw(_("Stock Entry {0} is not submitted").format(self.stock_entry))
if frappe.db.exists({"doctype": "Journal Entry", "stock_entry": self.stock_entry, "docstatus":1}):
- frappe.msgprint(_("Warning: Another {0} # {1} exists against stock entry {2}".format(self.voucher_type, self.name, self.stock_entry)))
+ frappe.msgprint(_("Warning: Another {0} # {1} exists against stock entry {2}").format(self.voucher_type, self.name, self.stock_entry))
def validate_empty_accounts_table(self):
if not self.get('accounts'):
diff --git a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py
index fcf94ce..d54a47e 100644
--- a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py
+++ b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py
@@ -11,6 +11,7 @@
def validate(self):
self.validate_accounts()
self.validate_repeating_companies()
+ self.validate_pos_mode_of_payment()
def validate_repeating_companies(self):
"""Error when Same Company is entered multiple times in accounts"""
@@ -27,3 +28,15 @@
if frappe.db.get_value("Account", entry.default_account, "company") != entry.company:
frappe.throw(_("Account {0} does not match with Company {1} in Mode of Account: {2}")
.format(entry.default_account, entry.company, self.name))
+
+ def validate_pos_mode_of_payment(self):
+ if not self.enabled:
+ pos_profiles = frappe.db.sql("""SELECT sip.parent FROM `tabSales Invoice Payment` sip
+ WHERE sip.parenttype = 'POS Profile' and sip.mode_of_payment = %s""", (self.name))
+ pos_profiles = list(map(lambda x: x[0], pos_profiles))
+
+ if pos_profiles:
+ message = "POS Profile " + frappe.bold(", ".join(pos_profiles)) + " contains \
+ Mode of Payment " + frappe.bold(str(self.name)) + ". Please remove them to disable this mode."
+ frappe.throw(_(message), title="Not Allowed")
+
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 2192b7b..968fb60 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -253,6 +253,19 @@
frappe.throw(__("Party can only be one of "+ party_types.join(", ")));
}
+ frm.set_query("party", function() {
+ if(frm.doc.party_type == 'Employee'){
+ return {
+ query: "erpnext.controllers.queries.employee_query"
+ }
+ }
+ else if(frm.doc.party_type == 'Customer'){
+ return {
+ query: "erpnext.controllers.queries.customer_query"
+ }
+ }
+ });
+
if(frm.doc.party) {
$.each(["party", "party_balance", "paid_from", "paid_to",
"paid_from_account_currency", "paid_from_account_balance",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 214d608..55d2758 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -102,7 +102,9 @@
self.bank = bank_data.bank
self.bank_account_no = bank_data.bank_account_no
- self.set(field, bank_data.account)
+
+ if not self.get(field):
+ self.set(field, bank_data.account)
def validate_allocated_amount(self):
for d in self.get("references"):
@@ -1003,7 +1005,7 @@
# only Purchase Invoice can be blocked individually
if doc.doctype == "Purchase Invoice" and doc.invoice_is_blocked():
- frappe.msgprint(_('{0} is on hold till {1}'.format(doc.name, doc.release_date)))
+ frappe.msgprint(_('{0} is on hold till {1}').format(doc.name, doc.release_date))
else:
pe.append("references", {
'reference_doctype': dt,
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
index 2c04a27..3080496 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
@@ -92,6 +92,7 @@
FROM `tab{doc}`, `tabGL Entry`
WHERE
(`tab{doc}`.name = `tabGL Entry`.against_voucher or `tab{doc}`.name = `tabGL Entry`.voucher_no)
+ and `tab{doc}`.{party_type_field} = %(party)s
and `tab{doc}`.is_return = 1 and `tab{doc}`.return_against IS NULL
and `tabGL Entry`.against_voucher_type = %(voucher_type)s
and `tab{doc}`.docstatus = 1 and `tabGL Entry`.party = %(party)s
@@ -99,12 +100,17 @@
GROUP BY `tab{doc}`.name
Having
amount > 0
- """.format(doc=voucher_type, dr_or_cr=dr_or_cr, reconciled_dr_or_cr=reconciled_dr_or_cr), {
- 'party': self.party,
- 'party_type': self.party_type,
- 'voucher_type': voucher_type,
- 'account': self.receivable_payable_account
- }, as_dict=1)
+ """.format(
+ doc=voucher_type,
+ dr_or_cr=dr_or_cr,
+ reconciled_dr_or_cr=reconciled_dr_or_cr,
+ party_type_field=frappe.scrub(self.party_type)),
+ {
+ 'party': self.party,
+ 'party_type': self.party_type,
+ 'voucher_type': voucher_type,
+ 'account': self.receivable_payable_account
+ }, as_dict=1)
def add_payment_entries(self, entries):
self.set('payments', [])
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 1aff43c..0fade8c 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -39,8 +39,8 @@
ref_amount = get_amount(ref_doc)
if existing_payment_request_amount + flt(self.grand_total)> ref_amount:
- frappe.throw(_("Total Payment Request amount cannot be greater than {0} amount"
- .format(self.reference_doctype)))
+ frappe.throw(_("Total Payment Request amount cannot be greater than {0} amount")
+ .format(self.reference_doctype))
def validate_currency(self):
ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
@@ -53,14 +53,14 @@
for subscription_plan in self.subscription_plans:
payment_gateway = frappe.db.get_value("Subscription Plan", subscription_plan.plan, "payment_gateway")
if payment_gateway != self.payment_gateway_account:
- frappe.throw(_('The payment gateway account in plan {0} is different from the payment gateway account in this payment request'.format(subscription_plan.name)))
+ frappe.throw(_('The payment gateway account in plan {0} is different from the payment gateway account in this payment request').format(subscription_plan.name))
rate = get_plan_rate(subscription_plan.plan, quantity=subscription_plan.qty)
amount += rate
if amount != self.grand_total:
- frappe.msgprint(_("The amount of {0} set in this payment request is different from the calculated amount of all payment plans: {1}. Make sure this is correct before submitting the document.".format(self.grand_total, amount)))
+ frappe.msgprint(_("The amount of {0} set in this payment request is different from the calculated amount of all payment plans: {1}. Make sure this is correct before submitting the document.").format(self.grand_total, amount))
def on_submit(self):
if self.payment_request_type == 'Outward':
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json
index aa9f85a..fba1bed 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.json
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json
@@ -3,6 +3,7 @@
"autoname": "Prompt",
"creation": "2013-05-24 12:15:51",
"doctype": "DocType",
+ "engine": "InnoDB",
"field_order": [
"disabled",
"section_break_2",
@@ -50,6 +51,7 @@
"income_account",
"expense_account",
"taxes_and_charges",
+ "tax_category",
"apply_discount_on",
"accounting_dimensions_section",
"cost_center",
@@ -381,11 +383,17 @@
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "tax_category",
+ "fieldtype": "Link",
+ "label": "Tax Category",
+ "options": "Tax Category"
}
],
"icon": "icon-cog",
"idx": 1,
- "modified": "2019-05-25 22:56:30.352693",
+ "modified": "2020-01-24 15:52:03.797701",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Profile",
diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
index 58f1216..64d347d 100644
--- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
@@ -29,27 +29,29 @@
frappe.db.sql("delete from `tabPOS Profile`")
-def make_pos_profile():
+def make_pos_profile(**args):
frappe.db.sql("delete from `tabPOS Profile`")
+ args = frappe._dict(args)
+
pos_profile = frappe.get_doc({
- "company": "_Test Company",
- "cost_center": "_Test Cost Center - _TC",
- "currency": "INR",
+ "company": args.company or "_Test Company",
+ "cost_center": args.cost_center or "_Test Cost Center - _TC",
+ "currency": args.currency or "INR",
"doctype": "POS Profile",
- "expense_account": "_Test Account Cost for Goods Sold - _TC",
- "income_account": "Sales - _TC",
- "name": "_Test POS Profile",
+ "expense_account": args.expense_account or "_Test Account Cost for Goods Sold - _TC",
+ "income_account": args.income_account or "Sales - _TC",
+ "name": args.name or "_Test POS Profile",
"naming_series": "_T-POS Profile-",
- "selling_price_list": "_Test Price List",
- "territory": "_Test Territory",
+ "selling_price_list": args.selling_price_list or "_Test Price List",
+ "territory": args.territory or "_Test Territory",
"customer_group": frappe.db.get_value('Customer Group', {'is_group': 0}, 'name'),
- "warehouse": "_Test Warehouse - _TC",
- "write_off_account": "_Test Write Off - _TC",
- "write_off_cost_center": "_Test Write Off Cost Center - _TC"
+ "warehouse": args.warehouse or "_Test Warehouse - _TC",
+ "write_off_account": args.write_off_account or "_Test Write Off - _TC",
+ "write_off_cost_center": args.write_off_cost_center or "_Test Write Off Cost Center - _TC"
})
- if not frappe.db.exists("POS Profile", "_Test POS Profile"):
+ if not frappe.db.exists("POS Profile", args.name or "_Test POS Profile"):
pos_profile.insert()
return pos_profile
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index 3c14819..e13fcb9 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -56,12 +56,12 @@
if not self.selling and self.applicable_for in ["Customer", "Customer Group",
"Territory", "Sales Partner", "Campaign"]:
- throw(_("Selling must be checked, if Applicable For is selected as {0}"
- .format(self.applicable_for)))
+ throw(_("Selling must be checked, if Applicable For is selected as {0}")
+ .format(self.applicable_for))
if not self.buying and self.applicable_for in ["Supplier", "Supplier Group"]:
- throw(_("Buying must be checked, if Applicable For is selected as {0}"
- .format(self.applicable_for)))
+ throw(_("Buying must be checked, if Applicable For is selected as {0}")
+ .format(self.applicable_for))
def validate_min_max_qty(self):
if self.min_qty and self.max_qty and flt(self.min_qty) > flt(self.max_qty):
@@ -243,12 +243,12 @@
if pricing_rule.coupon_code_based==1 and args.coupon_code==None:
return item_details
-
+
if not pricing_rule.validate_applied_rule:
if pricing_rule.price_or_product_discount == "Price":
apply_price_discount_rule(pricing_rule, item_details, args)
else:
- get_product_discount_rule(pricing_rule, item_details, doc)
+ get_product_discount_rule(pricing_rule, item_details, args, doc)
item_details.has_pricing_rule = 1
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index 332a900..2da71df 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -9,6 +9,8 @@
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
+from erpnext.stock.doctype.item.test_item import make_item
+from erpnext.healthcare.doctype.lab_test_template.lab_test_template import make_item_price
class TestPricingRule(unittest.TestCase):
def setUp(self):
@@ -145,6 +147,52 @@
self.assertEquals(details.get("margin_type"), "Percentage")
self.assertEquals(details.get("margin_rate_or_amount"), 10)
+ def test_mixed_conditions_for_item_group(self):
+ for item in ["Mixed Cond Item 1", "Mixed Cond Item 2"]:
+ make_item(item, {"item_group": "Products"})
+ make_item_price(item, "_Test Price List", 100)
+
+ test_record = {
+ "doctype": "Pricing Rule",
+ "title": "_Test Pricing Rule for Item Group",
+ "apply_on": "Item Group",
+ "item_groups": [
+ {
+ "item_group": "Products",
+ },
+ {
+ "item_group": "Seed",
+ },
+ ],
+ "selling": 1,
+ "mixed_conditions": 1,
+ "currency": "USD",
+ "rate_or_discount": "Discount Percentage",
+ "discount_percentage": 10,
+ "applicable_for": "Customer Group",
+ "customer_group": "All Customer Groups",
+ "company": "_Test Company"
+ }
+ frappe.get_doc(test_record.copy()).insert()
+
+ args = frappe._dict({
+ "item_code": "Mixed Cond Item 1",
+ "item_group": "Products",
+ "company": "_Test Company",
+ "price_list": "_Test Price List",
+ "currency": "_Test Currency",
+ "doctype": "Sales Order",
+ "conversion_rate": 1,
+ "price_list_currency": "_Test Currency",
+ "plc_conversion_rate": 1,
+ "order_type": "Sales",
+ "customer": "_Test Customer",
+ "customer_group": "_Test Customer Group",
+ "name": None
+ })
+ details = get_item_details(args)
+ self.assertEquals(details.get("discount_percentage"), 10)
+
def test_pricing_rule_for_variants(self):
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
@@ -278,6 +326,66 @@
self.assertEquals(item.discount_amount, 110)
self.assertEquals(item.rate, 990)
+ def test_pricing_rule_for_product_discount_on_same_item(self):
+ frappe.delete_doc_if_exists('Pricing Rule', '_Test Pricing Rule')
+ test_record = {
+ "doctype": "Pricing Rule",
+ "title": "_Test Pricing Rule",
+ "apply_on": "Item Code",
+ "currency": "USD",
+ "items": [{
+ "item_code": "_Test Item",
+ }],
+ "selling": 1,
+ "rate_or_discount": "Discount Percentage",
+ "rate": 0,
+ "min_qty": 0,
+ "max_qty": 7,
+ "discount_percentage": 17.5,
+ "price_or_product_discount": "Product",
+ "same_item": 1,
+ "free_qty": 1,
+ "company": "_Test Company"
+ }
+ frappe.get_doc(test_record.copy()).insert()
+
+ # With pricing rule
+ so = make_sales_order(item_code="_Test Item", qty=1)
+ so.load_from_db()
+ self.assertEqual(so.items[1].is_free_item, 1)
+ self.assertEqual(so.items[1].item_code, "_Test Item")
+
+
+ def test_pricing_rule_for_product_discount_on_different_item(self):
+ frappe.delete_doc_if_exists('Pricing Rule', '_Test Pricing Rule')
+ test_record = {
+ "doctype": "Pricing Rule",
+ "title": "_Test Pricing Rule",
+ "apply_on": "Item Code",
+ "currency": "USD",
+ "items": [{
+ "item_code": "_Test Item",
+ }],
+ "selling": 1,
+ "rate_or_discount": "Discount Percentage",
+ "rate": 0,
+ "min_qty": 0,
+ "max_qty": 7,
+ "discount_percentage": 17.5,
+ "price_or_product_discount": "Product",
+ "same_item": 0,
+ "free_item": "_Test Item 2",
+ "free_qty": 1,
+ "company": "_Test Company"
+ }
+ frappe.get_doc(test_record.copy()).insert()
+
+ # With pricing rule
+ so = make_sales_order(item_code="_Test Item", qty=1)
+ so.load_from_db()
+ self.assertEqual(so.items[1].is_free_item, 1)
+ self.assertEqual(so.items[1].item_code, "_Test Item 2")
+
def make_pricing_rule(**args):
args = frappe._dict(args)
diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py
index fe68fdb..a2bb2ee 100644
--- a/erpnext/accounts/doctype/pricing_rule/utils.py
+++ b/erpnext/accounts/doctype/pricing_rule/utils.py
@@ -435,7 +435,7 @@
doc.calculate_taxes_and_totals()
elif d.price_or_product_discount == 'Product':
item_details = frappe._dict({'parenttype': doc.doctype})
- get_product_discount_rule(d, item_details, doc)
+ get_product_discount_rule(d, item_details, doc=doc)
apply_pricing_rule_for_free_items(doc, item_details.free_item_data)
doc.set_missing_values()
@@ -443,9 +443,10 @@
return (item_row.get("pricing_rules").split(',')
if item_row.get("pricing_rules") else [])
-def get_product_discount_rule(pricing_rule, item_details, doc=None):
- free_item = (pricing_rule.free_item
- if not pricing_rule.same_item or pricing_rule.apply_on == 'Transaction' else item_details.item_code)
+def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None):
+ free_item = pricing_rule.free_item
+ if pricing_rule.same_item:
+ free_item = item_details.item_code or args.item_code
if not free_item:
frappe.throw(_("Free item not set in the pricing rule {0}")
@@ -489,7 +490,7 @@
for d in pr_doc.get(pricing_rule_apply_on):
if apply_on == 'item_group':
- get_child_item_groups(d.get(apply_on))
+ apply_on_data.extend(get_child_item_groups(d.get(apply_on)))
else:
apply_on_data.append(d.get(apply_on))
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 7725994..3cd988c 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -149,6 +149,7 @@
"column_break_63",
"status",
"inter_company_invoice_reference",
+ "is_internal_supplier",
"remarks",
"subscription_section",
"from_date",
@@ -418,7 +419,6 @@
"fieldname": "contact_email",
"fieldtype": "Small Text",
"label": "Contact Email",
- "options": "Email",
"print_hide": 1,
"read_only": 1
},
@@ -1284,6 +1284,14 @@
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
+ },
+ {
+ "default": "0",
+ "fetch_from": "supplier.is_internal_supplier",
+ "fieldname": "is_internal_supplier",
+ "fieldtype": "Check",
+ "label": "Is Internal Supplier",
+ "read_only": 1
}
],
"icon": "fa fa-file-text",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index d4676ff..a68c368 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -224,7 +224,7 @@
for item in self.get("items"):
# in case of auto inventory accounting,
# expense account is always "Stock Received But Not Billed" for a stock item
- # except epening entry, drop-ship entry and fixed asset items
+ # except opening entry, drop-ship entry and fixed asset items
if item.item_code:
asset_category = frappe.get_cached_value("Item", item.item_code, "asset_category")
@@ -233,10 +233,22 @@
and (not item.po_detail or
not frappe.db.get_value("Purchase Order Item", item.po_detail, "delivered_by_supplier")):
- if self.update_stock:
+ if self.update_stock and (not item.from_warehouse):
item.expense_account = warehouse_account[item.warehouse]["account"]
else:
- item.expense_account = stock_not_billed_account
+ # check if 'Stock Received But Not Billed' account is credited in Purchase receipt or not
+ if item.purchase_receipt:
+ negative_expense_booked_in_pr = frappe.db.sql("""select name from `tabGL Entry`
+ where voucher_type='Purchase Receipt' and voucher_no=%s and account = %s""",
+ (item.purchase_receipt, stock_not_billed_account))
+
+ if negative_expense_booked_in_pr:
+ item.expense_account = stock_not_billed_account
+ else:
+ # If no purchase receipt present then book expense in 'Stock Received But Not Billed'
+ # This is done in cases when Purchase Invoice is created before Purchase Receipt
+ item.expense_account = stock_not_billed_account
+
elif item.is_fixed_asset and not is_cwip_accounting_enabled(asset_category):
item.expense_account = get_asset_category_account('fixed_asset_account', item=item.item_code,
company = self.company)
@@ -467,16 +479,47 @@
warehouse_debit_amount = self.make_stock_adjustment_entry(gl_entries,
item, voucher_wise_stock_value, account_currency)
- gl_entries.append(
- self.get_gl_dict({
- "account": item.expense_account,
- "against": self.supplier,
- "debit": warehouse_debit_amount,
- "remarks": self.get("remarks") or _("Accounting Entry for Stock"),
+ if item.from_warehouse:
+
+ gl_entries.append(self.get_gl_dict({
+ "account": warehouse_account[item.warehouse]['account'],
+ "against": warehouse_account[item.from_warehouse]["account"],
"cost_center": item.cost_center,
- "project": item.project
- }, account_currency, item=item)
- )
+ "remarks": self.get("remarks") or _("Accounting Entry for Stock"),
+ "debit": warehouse_debit_amount,
+ }, warehouse_account[item.warehouse]["account_currency"], item=item))
+
+ # Intentionally passed negative debit amount to avoid incorrect GL Entry validation
+ gl_entries.append(self.get_gl_dict({
+ "account": warehouse_account[item.from_warehouse]['account'],
+ "against": warehouse_account[item.warehouse]["account"],
+ "cost_center": item.cost_center,
+ "remarks": self.get("remarks") or _("Accounting Entry for Stock"),
+ "debit": -1 * flt(item.base_net_amount, item.precision("base_net_amount")),
+ }, warehouse_account[item.from_warehouse]["account_currency"], item=item))
+
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": item.expense_account,
+ "against": self.supplier,
+ "debit": flt(item.base_net_amount, item.precision("base_net_amount")),
+ "remarks": self.get("remarks") or _("Accounting Entry for Stock"),
+ "cost_center": item.cost_center,
+ "project": item.project
+ }, account_currency, item=item)
+ )
+
+ else:
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": item.expense_account,
+ "against": self.supplier,
+ "debit": warehouse_debit_amount,
+ "remarks": self.get("remarks") or _("Accounting Entry for Stock"),
+ "cost_center": item.cost_center,
+ "project": item.project
+ }, account_currency, item=item)
+ )
# Amount added through landed-cost-voucher
if landed_cost_entries:
@@ -908,7 +951,7 @@
if pi:
pi = pi[0][0]
- frappe.throw(_("Supplier Invoice No exists in Purchase Invoice {0}".format(pi)))
+ frappe.throw(_("Supplier Invoice No exists in Purchase Invoice {0}").format(pi))
def update_billing_status_in_pr(self, update_modified=True):
updated_pr = []
@@ -1015,7 +1058,7 @@
@frappe.whitelist()
-def block_invoice(name, hold_comment, release_date):
+def block_invoice(name, release_date, hold_comment=None):
if frappe.db.exists('Purchase Invoice', name):
pi = frappe.get_doc('Purchase Invoice', name)
pi.block_invoice(hold_comment, release_date)
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index acb0398..28208ce 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -63,6 +63,7 @@
"warehouse_section",
"warehouse",
"rejected_warehouse",
+ "from_warehouse",
"quality_inspection",
"batch_no",
"col_br_wh",
@@ -762,16 +763,22 @@
"fetch_from": "item_code.asset_category",
"fieldname": "asset_category",
"fieldtype": "Data",
- "in_preview": 1,
"label": "Asset Category",
"options": "Asset Category",
"read_only": 1
+ },
+ {
+ "fieldname": "from_warehouse",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Supplier Warehouse",
+ "options": "Warehouse"
}
],
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2019-12-04 12:23:17.046413",
+ "modified": "2020-01-13 16:04:14.200462",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index a48d224..749816f 100755
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -152,8 +152,11 @@
def get_mode_of_payment(doc):
- return frappe.db.sql(""" select mpa.default_account, mpa.parent, mp.type as type from `tabMode of Payment Account` mpa, \
- `tabMode of Payment` mp where mpa.parent = mp.name and mpa.company = %(company)s""", {'company': doc.company}, as_dict=1)
+ return frappe.db.sql("""
+ select mpa.default_account, mpa.parent, mp.type as type
+ from `tabMode of Payment Account` mpa,`tabMode of Payment` mp
+ where mpa.parent = mp.name and mpa.company = %(company)s and mp.enabled = 1""",
+ {'company': doc.company}, as_dict=1)
def update_tax_table(doc):
diff --git a/erpnext/accounts/doctype/sales_invoice/regional/india.js b/erpnext/accounts/doctype/sales_invoice/regional/india.js
index 48fa364..ba6c03b 100644
--- a/erpnext/accounts/doctype/sales_invoice/regional/india.js
+++ b/erpnext/accounts/doctype/sales_invoice/regional/india.js
@@ -25,7 +25,7 @@
if(frm.doc.docstatus == 1 && !frm.is_dirty()
&& !frm.doc.is_return && !frm.doc.ewaybill) {
- frm.add_custom_button('e-Way Bill JSON', () => {
+ frm.add_custom_button('E-Way Bill JSON', () => {
var w = window.open(
frappe.urllib.get_full_url(
"/api/method/erpnext.regional.india.utils.generate_ewb_json?"
@@ -36,7 +36,7 @@
if (!w) {
frappe.msgprint(__("Please enable pop-ups")); return;
}
- }, __("Make"));
+ }, __("Create"));
}
}
diff --git a/erpnext/accounts/doctype/sales_invoice/regional/india_list.js b/erpnext/accounts/doctype/sales_invoice/regional/india_list.js
index 66d74b4..d175827 100644
--- a/erpnext/accounts/doctype/sales_invoice/regional/india_list.js
+++ b/erpnext/accounts/doctype/sales_invoice/regional/india_list.js
@@ -12,7 +12,7 @@
for (let doc of selected_docs) {
if (doc.docstatus !== 1) {
- frappe.throw(__("e-Way Bill JSON can only be generated from a submitted document"));
+ frappe.throw(__("E-Way Bill JSON can only be generated from a submitted document"));
}
}
@@ -29,5 +29,5 @@
};
- doclist.page.add_actions_menu_item(__('Generate e-Way Bill JSON'), action, false);
+ doclist.page.add_actions_menu_item(__('Generate E-Way Bill JSON'), action, false);
};
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 33ee7a2..e239f91 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -1,5 +1,4 @@
{
- "actions": [],
"allow_import": 1,
"autoname": "naming_series:",
"creation": "2013-05-24 19:29:05",
@@ -154,6 +153,7 @@
"select_print_heading",
"more_information",
"inter_company_invoice_reference",
+ "is_internal_customer",
"customer_group",
"campaign",
"is_discounted",
@@ -373,7 +373,8 @@
"no_copy": 1,
"options": "Sales Invoice",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "search_index": 1
},
{
"fieldname": "column_break_21",
@@ -1563,13 +1564,20 @@
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
+ },
+ {
+ "default": "0",
+ "fetch_from": "customer.is_internal_customer",
+ "fieldname": "is_internal_customer",
+ "fieldtype": "Check",
+ "label": "Is Internal Customer",
+ "read_only": 1
}
],
"icon": "fa fa-file-text",
"idx": 181,
"is_submittable": 1,
- "links": [],
- "modified": "2019-12-30 19:15:59.580414",
+ "modified": "2020-02-10 04:57:11.221180",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 6e3e43e..658e703 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -225,7 +225,7 @@
total_amount_in_payments += payment.amount
invoice_total = self.rounded_total or self.grand_total
if total_amount_in_payments < invoice_total:
- frappe.throw(_("Total payments amount can't be greater than {}".format(-invoice_total)))
+ frappe.throw(_("Total payments amount can't be greater than {}").format(-invoice_total))
def validate_pos_paid_amount(self):
if len(self.payments) == 0 and self.is_pos:
@@ -421,6 +421,9 @@
if pos:
self.allow_print_before_pay = pos.allow_print_before_pay
+ if not for_validate:
+ self.tax_category = pos.get("tax_category")
+
if not for_validate and not self.customer:
self.customer = pos.customer
@@ -1041,11 +1044,11 @@
si_serial_nos = set(get_serial_nos(serial_nos))
if si_serial_nos - dn_serial_nos:
- frappe.throw(_("Serial Numbers in row {0} does not match with Delivery Note".format(item.idx)))
+ frappe.throw(_("Serial Numbers in row {0} does not match with Delivery Note").format(item.idx))
if item.serial_no and cint(item.qty) != len(si_serial_nos):
- frappe.throw(_("Row {0}: {1} Serial numbers required for Item {2}. You have provided {3}.".format(
- item.idx, item.qty, item.item_code, len(si_serial_nos))))
+ frappe.throw(_("Row {0}: {1} Serial numbers required for Item {2}. You have provided {3}.").format(
+ item.idx, item.qty, item.item_code, len(si_serial_nos)))
def validate_serial_against_sales_invoice(self):
""" check if serial number is already used in other sales invoice """
@@ -1064,8 +1067,8 @@
and self.name != serial_no_details.sales_invoice:
sales_invoice_company = frappe.db.get_value("Sales Invoice", serial_no_details.sales_invoice, "company")
if sales_invoice_company == self.company:
- frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}"
- .format(serial_no, serial_no_details.sales_invoice)))
+ frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}")
+ .format(serial_no, serial_no_details.sales_invoice))
def update_project(self):
if self.project:
@@ -1240,25 +1243,28 @@
precision = self.precision("outstanding_amount")
outstanding_amount = flt(self.outstanding_amount, precision)
+ due_date = getdate(self.due_date)
+ nowdate = getdate()
+ discountng_status = self.get_discounting_status()
if not status:
if self.docstatus == 2:
status = "Cancelled"
elif self.docstatus == 1:
- if outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
+ if outstanding_amount > 0 and due_date < nowdate and self.is_discounted and discountng_status=='Disbursed':
self.status = "Overdue and Discounted"
- elif outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()):
+ elif outstanding_amount > 0 and due_date < nowdate:
self.status = "Overdue"
- elif outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
+ elif outstanding_amount > 0 and due_date >= nowdate and self.is_discounted and discountng_status=='Disbursed':
self.status = "Unpaid and Discounted"
- elif outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()):
+ elif outstanding_amount > 0 and due_date >= nowdate:
self.status = "Unpaid"
#Check if outstanding amount is 0 due to credit note issued against invoice
elif outstanding_amount <= 0 and self.is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}):
self.status = "Credit Note Issued"
elif self.is_return == 1:
self.status = "Return"
- elif outstanding_amount <=0:
+ elif outstanding_amount<=0:
self.status = "Paid"
else:
self.status = "Submitted"
@@ -1423,23 +1429,42 @@
data.account = get_bank_cash_account(data.mode_of_payment, self.company).get("account")
def get_inter_company_details(doc, doctype):
- if doctype in ["Sales Invoice", "Sales Order"]:
- party = frappe.db.get_value("Supplier", {"disabled": 0, "is_internal_supplier": 1, "represents_company": doc.company}, "name")
+ if doctype in ["Sales Invoice", "Sales Order", "Delivery Note"]:
+ parties = frappe.db.get_all("Supplier", fields=["name"], filters={"disabled": 0, "is_internal_supplier": 1, "represents_company": doc.company})
company = frappe.get_cached_value("Customer", doc.customer, "represents_company")
+
+ party = get_internal_party(parties, "Supplier", doc)
else:
- party = frappe.db.get_value("Customer", {"disabled": 0, "is_internal_customer": 1, "represents_company": doc.company}, "name")
+ parties = frappe.db.get_all("Customer", fields=["name"], filters={"disabled": 0, "is_internal_customer": 1, "represents_company": doc.company})
company = frappe.get_cached_value("Supplier", doc.supplier, "represents_company")
+ party = get_internal_party(parties, "Customer", doc)
+
return {
"party": party,
"company": company
}
+def get_internal_party(parties, link_doctype, doc):
+ if len(parties) == 1:
+ party = parties[0].name
+ else:
+ # If more than one Internal Supplier/Customer, get supplier/customer on basis of address
+ if doc.get('company_address') or doc.get('shipping_address'):
+ party = frappe.db.get_value("Dynamic Link", {"parent": doc.get('company_address') or doc.get('shipping_address'),
+ "parenttype": "Address", "link_doctype": link_doctype}, "link_name")
+
+ if not party:
+ party = parties[0].name
+ else:
+ party = parties[0].name
+
+ return party
def validate_inter_company_transaction(doc, doctype):
details = get_inter_company_details(doc, doctype)
- price_list = doc.selling_price_list if doctype in ["Sales Invoice", "Sales Order"] else doc.buying_price_list
+ price_list = doc.selling_price_list if doctype in ["Sales Invoice", "Sales Order", "Delivery Note"] else doc.buying_price_list
valid_price_list = frappe.db.get_value("Price List", {"name": price_list, "buying": 1, "selling": 1})
if not valid_price_list:
frappe.throw(_("Selected Price List should have buying and selling fields checked."))
@@ -1523,6 +1548,9 @@
else:
return lp_details
+def on_doctype_update():
+ frappe.db.add_index("Sales Invoice", ["customer", "is_return", "return_against"])
+
@frappe.whitelist()
def create_invoice_discounting(source_name, target_doc=None):
invoice = frappe.get_doc("Sales Invoice", source_name)
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index a2a47b3..e48e6c9 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -705,6 +705,64 @@
self.pos_gl_entry(si, pos, 50)
+ def test_pos_returns_without_repayment(self):
+ pos_profile = make_pos_profile()
+
+ pos = create_sales_invoice(qty = 10, do_not_save=True)
+ pos.is_pos = 1
+ pos.pos_profile = pos_profile.name
+
+ pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 500})
+ pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 500})
+ pos.insert()
+ pos.submit()
+
+ pos_return = create_sales_invoice(is_return=1,
+ return_against=pos.name, qty=-5, do_not_save=True)
+
+ pos_return.is_pos = 1
+ pos_return.pos_profile = pos_profile.name
+
+ pos_return.insert()
+ pos_return.submit()
+
+ self.assertFalse(pos_return.is_pos)
+ self.assertFalse(pos_return.get('payments'))
+
+ def test_pos_returns_with_repayment(self):
+ pos_profile = make_pos_profile()
+
+ pos_profile.append('payments', {
+ 'default': 1,
+ 'mode_of_payment': 'Cash',
+ 'amount': 0.0
+ })
+
+ pos_profile.save()
+
+ pos = create_sales_invoice(qty = 10, do_not_save=True)
+
+ pos.is_pos = 1
+ pos.pos_profile = pos_profile.name
+
+ pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 500})
+ pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 500})
+ pos.insert()
+ pos.submit()
+
+ pos_return = create_sales_invoice(is_return=1,
+ return_against=pos.name, qty=-5, do_not_save=True)
+
+ pos_return.is_pos = 1
+ pos_return.pos_profile = pos_profile.name
+ pos_return.insert()
+ pos_return.submit()
+
+ self.assertEqual(pos_return.get('payments')[0].amount, -500)
+ pos_profile.payments = []
+ pos_profile.save()
+
+
def test_pos_change_amount(self):
make_pos_profile()
diff --git a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py
index 8c4efbe..1fd340c 100644
--- a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py
+++ b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py
@@ -82,7 +82,7 @@
if not shipping_country:
frappe.throw(_('Shipping Address does not have country, which is required for this Shipping Rule'))
if shipping_country not in [d.country for d in self.countries]:
- frappe.throw(_('Shipping rule not applicable for country {0}'.format(shipping_country)))
+ frappe.throw(_('Shipping rule not applicable for country {0}').format(shipping_country))
def add_shipping_rule_to_tax_table(self, doc, shipping_amount):
shipping_charge = {
diff --git a/erpnext/accounts/doctype/subscription/subscription.json b/erpnext/accounts/doctype/subscription/subscription.json
index 29cb62a..32b97ba 100644
--- a/erpnext/accounts/doctype/subscription/subscription.json
+++ b/erpnext/accounts/doctype/subscription/subscription.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"autoname": "ACC-SUB-.YYYY.-.#####",
"creation": "2017-07-18 17:50:43.967266",
"doctype": "DocType",
@@ -155,7 +156,7 @@
"fieldname": "apply_additional_discount",
"fieldtype": "Select",
"label": "Apply Additional Discount On",
- "options": "\nGrand Total\nNet total"
+ "options": "\nGrand Total\nNet Total"
},
{
"fieldname": "cb_2",
@@ -196,7 +197,8 @@
"fieldtype": "Column Break"
}
],
- "modified": "2019-07-25 18:45:38.579579",
+ "links": [],
+ "modified": "2020-01-27 14:37:32.845173",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Subscription",
diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py
index 5482750..0933c7e 100644
--- a/erpnext/accounts/doctype/subscription/subscription.py
+++ b/erpnext/accounts/doctype/subscription/subscription.py
@@ -195,7 +195,7 @@
doc = frappe.get_doc('Sales Invoice', current.invoice)
return doc
else:
- frappe.throw(_('Invoice {0} no longer exists'.format(current.invoice)))
+ frappe.throw(_('Invoice {0} no longer exists').format(current.invoice))
def is_new_subscription(self):
"""
@@ -280,7 +280,7 @@
if self.additional_discount_percentage or self.additional_discount_amount:
discount_on = self.apply_additional_discount
- invoice.apply_additional_discount = discount_on if discount_on else 'Grand Total'
+ invoice.apply_discount_on = discount_on if discount_on else 'Grand Total'
# Subscription period
invoice.from_date = self.current_invoice_start
@@ -338,7 +338,7 @@
# Check invoice dates and make sure it doesn't have outstanding invoices
return getdate(nowdate()) >= getdate(self.current_invoice_start) and not self.has_outstanding_invoice()
-
+
def is_current_invoice_paid(self):
if self.is_new_subscription():
return False
@@ -346,7 +346,7 @@
last_invoice = frappe.get_doc('Sales Invoice', self.invoices[-1].invoice)
if getdate(last_invoice.posting_date) == getdate(self.current_invoice_start) and last_invoice.status == 'Paid':
return True
-
+
return False
def process_for_active(self):
@@ -388,7 +388,7 @@
"""
current_invoice = self.get_current_invoice()
if not current_invoice:
- frappe.throw(_('Current invoice {0} is missing'.format(current_invoice.invoice)))
+ frappe.throw(_('Current invoice {0} is missing').format(current_invoice.invoice))
else:
if self.is_not_outstanding(current_invoice):
self.status = 'Active'
diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py
index ff87ba3..e4ebc6d 100644
--- a/erpnext/accounts/doctype/tax_rule/tax_rule.py
+++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py
@@ -95,7 +95,7 @@
if tax_rule:
if tax_rule[0].priority == self.priority:
- frappe.throw(_("Tax Rule Conflicts with {0}".format(tax_rule[0].name)), ConflictingTaxRule)
+ frappe.throw(_("Tax Rule Conflicts with {0}").format(tax_rule[0].name), ConflictingTaxRule)
def validate_use_for_shopping_cart(self):
'''If shopping cart is enabled and no tax rule exists for shopping cart, enable this one'''
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 156f218..422ace6 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -35,8 +35,7 @@
def _get_party_details(party=None, account=None, party_type="Customer", company=None, posting_date=None,
bill_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False,
- fetch_payment_terms_template=True, party_address=None, company_address=None,shipping_address=None, pos_profile=None):
-
+ fetch_payment_terms_template=True, party_address=None, company_address=None, shipping_address=None, pos_profile=None):
party_details = frappe._dict(set_account_and_due_date(party, account, party_type, company, posting_date, bill_date, doctype))
party = party_details[party_type.lower()]
diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js
index b1f427c..df700ec 100644
--- a/erpnext/accounts/report/accounts_payable/accounts_payable.js
+++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js
@@ -101,6 +101,11 @@
"options": "Supplier Group"
},
{
+ "fieldname": "group_by_party",
+ "label": __("Group By Supplier"),
+ "fieldtype": "Check"
+ },
+ {
"fieldname":"based_on_payment_terms",
"label": __("Based On Payment Terms"),
"fieldtype": "Check",
@@ -112,6 +117,16 @@
"hidden": 1
}
],
+
+ "formatter": function(value, row, column, data, default_formatter) {
+ value = default_formatter(value, row, column, data);
+ if (data && data.bold) {
+ value = value.bold();
+
+ }
+ return value;
+ },
+
onload: function(report) {
report.page.add_inner_button(__("Accounts Payable Summary"), function() {
var filters = report.get_values();
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
index 9b4dda2..5d0154f 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
@@ -87,7 +87,7 @@
frappe.query_report.set_filter_value('payment_terms', value["payment_terms"]);
});
- frappe.db.get_value('Customer Credit Limit', {'parent': customer, 'company': company},
+ frappe.db.get_value('Customer Credit Limit', {'parent': customer, 'company': company},
["credit_limit"], function(value) {
if (value) {
frappe.query_report.set_filter_value('credit_limit', value["credit_limit"]);
@@ -132,6 +132,11 @@
"options": "Sales Person"
},
{
+ "fieldname": "group_by_party",
+ "label": __("Group By Customer"),
+ "fieldtype": "Check"
+ },
+ {
"fieldname":"based_on_payment_terms",
"label": __("Based On Payment Terms"),
"fieldtype": "Check",
@@ -177,6 +182,15 @@
}
],
+ "formatter": function(value, row, column, data, default_formatter) {
+ value = default_formatter(value, row, column, data);
+ if (data && data.bold) {
+ value = value.bold();
+
+ }
+ return value;
+ },
+
onload: function(report) {
report.page.add_inner_button(__("Accounts Receivable Summary"), function() {
var filters = report.get_values();
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index f82146a..0438f6d 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -46,7 +46,7 @@
self.get_columns()
self.get_data()
self.get_chart_data()
- return self.columns, self.data, None, self.chart
+ return self.columns, self.data, None, self.chart, None, self.skip_total_row
def set_defaults(self):
if not self.filters.get("company"):
@@ -57,6 +57,12 @@
self.party_type = self.filters.party_type
self.party_details = {}
self.invoices = set()
+ self.skip_total_row = 0
+
+ if self.filters.get('group_by_party'):
+ self.previous_party=''
+ self.total_row_map = {}
+ self.skip_total_row = 1
def get_data(self):
self.get_gl_entries()
@@ -102,6 +108,12 @@
)
self.get_invoices(gle)
+ if self.filters.get('group_by_party'):
+ self.init_subtotal_row(gle.party)
+
+ if self.filters.get('group_by_party'):
+ self.init_subtotal_row('Total')
+
def get_invoices(self, gle):
if gle.voucher_type in ('Sales Invoice', 'Purchase Invoice'):
if self.filters.get("sales_person"):
@@ -111,6 +123,20 @@
else:
self.invoices.add(gle.voucher_no)
+ def init_subtotal_row(self, party):
+ if not self.total_row_map.get(party):
+ self.total_row_map.setdefault(party, {
+ 'party': party,
+ 'bold': 1
+ })
+
+ for field in self.get_currency_fields():
+ self.total_row_map[party][field] = 0.0
+
+ def get_currency_fields(self):
+ return ['invoiced', 'paid', 'credit_note', 'outstanding', 'range1',
+ 'range2', 'range3', 'range4', 'range5']
+
def update_voucher_balance(self, gle):
# get the row where this balance needs to be updated
# if its a payment, it will return the linked invoice or will be considered as advance
@@ -135,6 +161,18 @@
# advance / unlinked payment or other adjustment
row.paid -= gle_balance
+ def update_sub_total_row(self, row, party):
+ total_row = self.total_row_map.get(party)
+
+ for field in self.get_currency_fields():
+ total_row[field] += row.get(field, 0.0)
+
+ def append_subtotal_row(self, party):
+ sub_total_row = self.total_row_map.get(party)
+ self.data.append(sub_total_row)
+ self.data.append({})
+ self.update_sub_total_row(sub_total_row, 'Total')
+
def get_voucher_balance(self, gle):
if self.filters.get("sales_person"):
against_voucher = gle.against_voucher or gle.voucher_no
@@ -192,11 +230,22 @@
else:
self.append_row(row)
+ if self.filters.get('group_by_party'):
+ self.append_subtotal_row(self.previous_party)
+ self.data.append(self.total_row_map.get('Total'))
+
def append_row(self, row):
self.allocate_future_payments(row)
self.set_invoice_details(row)
self.set_party_details(row)
self.set_ageing(row)
+
+ if self.filters.get('group_by_party'):
+ self.update_sub_total_row(row, row.party)
+ if self.previous_party and (self.previous_party != row.party):
+ self.append_subtotal_row(self.previous_party)
+ self.previous_party = row.party
+
self.data.append(row)
def set_invoice_details(self, row):
@@ -503,6 +552,7 @@
# get all the GL entries filtered by the given filters
conditions, values = self.prepare_conditions()
+ order_by = self.get_order_by_condition()
if self.filters.get(scrub(self.party_type)):
select_fields = "debit_in_account_currency as debit, credit_in_account_currency as credit"
@@ -520,9 +570,8 @@
and party_type=%s
and (party is not null and party != '')
and posting_date <= %s
- {1}
- order by posting_date, party"""
- .format(select_fields, conditions), values, as_dict=True)
+ {1} {2}"""
+ .format(select_fields, conditions, order_by), values, as_dict=True)
def get_sales_invoices_or_customers_based_on_sales_person(self):
if self.filters.get("sales_person"):
@@ -557,6 +606,12 @@
return " and ".join(conditions), values
+ def get_order_by_condition(self):
+ if self.filters.get('group_by_party'):
+ return "order by party, posting_date"
+ else:
+ return "order by posting_date, party"
+
def add_common_filters(self, conditions, values, party_type_field):
if self.filters.company:
conditions.append("company=%s")
@@ -736,11 +791,13 @@
def get_chart_data(self):
rows = []
for row in self.data:
- values = [row.range1, row.range2, row.range3, row.range4, row.range5]
- precision = cint(frappe.db.get_default("float_precision")) or 2
- rows.append({
- 'values': [flt(val, precision) for val in values]
- })
+ row = frappe._dict(row)
+ if not cint(row.bold):
+ values = [row.range1, row.range2, row.range3, row.range4, row.range5]
+ precision = cint(frappe.db.get_default("float_precision")) or 2
+ rows.append({
+ 'values': [flt(val, precision) for val in values]
+ })
self.chart = {
"data": {
diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py
index 0b12477..e349a6a 100644
--- a/erpnext/accounts/report/cash_flow/cash_flow.py
+++ b/erpnext/accounts/report/cash_flow/cash_flow.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
-from frappe.utils import cint
+from frappe.utils import cint, cstr
from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data)
from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import get_net_profit_loss
from erpnext.accounts.utils import get_fiscal_year
@@ -129,13 +129,13 @@
cond = ""
filters = frappe._dict(filters)
- if filters.finance_book:
- cond = " AND (finance_book in (%s, '') OR finance_book IS NULL)" %(frappe.db.escape(filters.finance_book))
- if filters.include_default_book_entries:
- company_fb = frappe.db.get_value("Company", company, 'default_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, '') OR finance_book IS NULL)
+ """ %(frappe.db.escape(filters.finance_book), frappe.db.escape(company_fb))
+ else:
+ cond = " AND (finance_book in (%s, '') OR finance_book IS NULL)" %(frappe.db.escape(cstr(filters.finance_book)))
- cond = """ AND (finance_book in (%s, %s, '') OR finance_book IS NULL)
- """ %(frappe.db.escape(filters.finance_book), frappe.db.escape(company_fb))
gl_sum = frappe.db.sql_list("""
select sum(credit) - sum(debit)
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 e9eb819..4a79b6a 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
@@ -387,11 +387,10 @@
if from_date:
additional_conditions.append("gl.posting_date >= %(from_date)s")
- if filters.get("finance_book"):
- if filters.get("include_default_book_entries"):
- additional_conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)")
- else:
- additional_conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)")
+ if filters.get("include_default_book_entries"):
+ additional_conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)")
+ else:
+ additional_conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)")
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 32d9075..35915d0 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -13,7 +13,7 @@
from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
from erpnext.accounts.utils import get_fiscal_year
from frappe import _
-from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate)
+from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate, cstr)
from six import itervalues
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
@@ -175,7 +175,7 @@
d = accounts_by_name.get(entry.account)
if not d:
frappe.msgprint(
- _("Could not retrieve information for {0}.".format(entry.account)), title="Error",
+ _("Could not retrieve information for {0}.").format(entry.account), title="Error",
raise_exception=1
)
for period in period_list:
@@ -348,40 +348,42 @@
additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters)
accounts = frappe.db.sql_list("""select name from `tabAccount`
- where lft >= %s and rgt <= %s""", (root_lft, root_rgt))
- additional_conditions += " and account in ({})"\
- .format(", ".join([frappe.db.escape(d) for d in accounts]))
+ where lft >= %s and rgt <= %s and company = %s""", (root_lft, root_rgt, company))
- gl_filters = {
- "company": company,
- "from_date": from_date,
- "to_date": to_date,
- "finance_book": filters.get("finance_book")
- }
+ if accounts:
+ additional_conditions += " and account in ({})"\
+ .format(", ".join([frappe.db.escape(d) for d in accounts]))
- if filters.get("include_default_book_entries"):
- gl_filters["company_fb"] = frappe.db.get_value("Company",
- company, 'default_finance_book')
+ gl_filters = {
+ "company": company,
+ "from_date": from_date,
+ "to_date": to_date,
+ "finance_book": cstr(filters.get("finance_book"))
+ }
- for key, value in filters.items():
- if value:
- gl_filters.update({
- key: value
- })
+ if filters.get("include_default_book_entries"):
+ gl_filters["company_fb"] = frappe.db.get_value("Company",
+ company, 'default_finance_book')
- gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year, debit_in_account_currency, credit_in_account_currency, account_currency from `tabGL Entry`
- where company=%(company)s
- {additional_conditions}
- and posting_date <= %(to_date)s
- order by account, posting_date""".format(additional_conditions=additional_conditions), gl_filters, as_dict=True) #nosec
+ for key, value in filters.items():
+ if value:
+ gl_filters.update({
+ key: value
+ })
- if filters and filters.get('presentation_currency'):
- convert_to_presentation_currency(gl_entries, get_currency(filters))
+ gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year, debit_in_account_currency, credit_in_account_currency, account_currency from `tabGL Entry`
+ where company=%(company)s
+ {additional_conditions}
+ and posting_date <= %(to_date)s
+ order by account, posting_date""".format(additional_conditions=additional_conditions), gl_filters, as_dict=True) #nosec
- for entry in gl_entries:
- gl_entries_by_account.setdefault(entry.account, []).append(entry)
+ if filters and filters.get('presentation_currency'):
+ convert_to_presentation_currency(gl_entries, get_currency(filters))
- return gl_entries_by_account
+ for entry in gl_entries:
+ gl_entries_by_account.setdefault(entry.account, []).append(entry)
+
+ return gl_entries_by_account
def get_additional_conditions(from_date, ignore_closing_entries, filters):
@@ -406,12 +408,11 @@
filters.cost_center = get_cost_centers_with_children(filters.cost_center)
additional_conditions.append("cost_center in %(cost_center)s")
- if filters.get("finance_book"):
- if filters.get("include_default_book_entries"):
- additional_conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)")
- else:
- additional_conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)")
-
+ if filters.get("include_default_book_entries"):
+ additional_conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)")
+ else:
+ additional_conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)")
+
if accounting_dimensions:
for dimension in accounting_dimensions:
if filters.get(dimension):
@@ -430,7 +431,7 @@
children = frappe.get_all("Cost Center", filters={"lft": [">=", lft], "rgt": ["<=", rgt]})
all_cost_centers += [c.name for c in children]
else:
- frappe.throw(_("Cost Center: {0} does not exist".format(d)))
+ frappe.throw(_("Cost Center: {0} does not exist").format(d))
return list(set(all_cost_centers))
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index 0939354..8bea365 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -373,19 +373,19 @@
"width": 180
},
{
- "label": _("Debit ({0})".format(currency)),
+ "label": _("Debit ({0})").format(currency),
"fieldname": "debit",
"fieldtype": "Float",
"width": 100
},
{
- "label": _("Credit ({0})".format(currency)),
+ "label": _("Credit ({0})").format(currency),
"fieldname": "credit",
"fieldtype": "Float",
"width": 100
},
{
- "label": _("Balance ({0})".format(currency)),
+ "label": _("Balance ({0})").format(currency),
"fieldname": "balance",
"fieldtype": "Float",
"width": 130
diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js
index e936a17..f88906a 100644
--- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js
+++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js
@@ -34,6 +34,20 @@
"label": __("Mode of Payment"),
"fieldtype": "Link",
"options": "Mode of Payment"
+ },
+ {
+ "label": __("Group By"),
+ "fieldname": "group_by",
+ "fieldtype": "Select",
+ "options": ["Supplier", "Item Group", "Item", "Invoice"]
}
- ]
+ ],
+ "formatter": function(value, row, column, data, default_formatter) {
+ value = default_formatter(value, row, column, data);
+ if (data && data.bold) {
+ value = value.bold();
+
+ }
+ return value;
+ }
}
diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
index 380b208..8b6359c 100644
--- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
+++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
@@ -5,7 +5,9 @@
import frappe, erpnext
from frappe import _
from frappe.utils import flt
-from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import get_tax_accounts
+from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import (get_tax_accounts,
+ get_grand_total, add_total_row, get_display_value, get_group_by_and_display_fields, add_sub_total_row,
+ get_group_by_conditions)
def execute(filters=None):
return _execute(filters)
@@ -13,7 +15,7 @@
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
if not filters: filters = {}
filters.update({"from_date": filters.get("date_range")[0], "to_date": filters.get("date_range")[1]})
- columns = get_columns(additional_table_columns)
+ columns = get_columns(additional_table_columns, filters)
company_currency = erpnext.get_company_currency(filters.company)
@@ -23,16 +25,16 @@
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency,
doctype="Purchase Invoice", tax_doctype="Purchase Taxes and Charges")
- columns.append({
- "fieldname": "currency",
- "label": _("Currency"),
- "fieldtype": "Data",
- "width": 80
- })
-
po_pr_map = get_purchase_receipts_against_purchase_order(item_list)
data = []
+ total_row_map = {}
+ skip_total_row = 0
+ prev_group_by_value = ''
+
+ if filters.get('group_by'):
+ grand_total = get_grand_total(filters, 'Purchase Invoice')
+
for d in item_list:
if not d.stock_qty:
continue
@@ -44,51 +46,243 @@
purchase_receipt = ", ".join(po_pr_map.get(d.po_detail, []))
expense_account = d.expense_account or aii_account_map.get(d.company)
- row = [d.item_code, d.item_name, d.item_group, d.description, d.parent, d.posting_date, d.supplier,
- d.supplier_name]
+
+ row = {
+ 'item_code': d.item_code,
+ 'item_name': d.item_name,
+ 'item_group': d.item_group,
+ 'description': d.description,
+ 'invoice': d.parent,
+ 'posting_date': d.posting_date,
+ 'customer': d.supplier,
+ 'customer_name': d.supplier_name
+ }
if additional_query_columns:
for col in additional_query_columns:
- row.append(d.get(col))
+ row.update({
+ col: d.get(col)
+ })
- row += [
- d.credit_to, d.mode_of_payment, d.project, d.company, d.purchase_order,
- purchase_receipt, expense_account, d.stock_qty, d.stock_uom, d.base_net_amount / d.stock_qty, d.base_net_amount
- ]
+ row.update({
+ 'credit_to': d.credit_to,
+ 'mode_of_payment': d.mode_of_payment,
+ 'project': d.project,
+ 'company': d.company,
+ 'purchase_order': d.purchase_order,
+ 'purchase_receipt': d.purchase_receipt,
+ 'expense_account': expense_account,
+ 'stock_qty': d.stock_qty,
+ 'stock_uom': d.stock_uom,
+ 'rate': d.base_net_amount / d.stock_qty,
+ 'amount': d.base_net_amount
+ })
total_tax = 0
for tax in tax_columns:
item_tax = itemised_tax.get(d.name, {}).get(tax, {})
- row += [item_tax.get("tax_rate", 0), item_tax.get("tax_amount", 0)]
+ row.update({
+ frappe.scrub(tax + ' Rate'): item_tax.get("tax_rate", 0),
+ frappe.scrub(tax + ' Amount'): item_tax.get("tax_amount", 0),
+ })
total_tax += flt(item_tax.get("tax_amount"))
- row += [total_tax, d.base_net_amount + total_tax, company_currency]
+ row.update({
+ 'total_tax': total_tax,
+ 'total': d.base_net_amount + total_tax,
+ 'currency': company_currency
+ })
+
+ if filters.get('group_by'):
+ row.update({'percent_gt': flt(row['total']/grand_total) * 100})
+ group_by_field, subtotal_display_field = get_group_by_and_display_fields(filters)
+ data, prev_group_by_value = add_total_row(data, filters, prev_group_by_value, d, total_row_map,
+ group_by_field, subtotal_display_field, grand_total, tax_columns)
+ add_sub_total_row(row, total_row_map, d.get(group_by_field, ''), tax_columns)
data.append(row)
- return columns, data
+ if filters.get('group_by'):
+ total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
+ total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
+ data.append(total_row)
+ data.append({})
+ add_sub_total_row(total_row, total_row_map, 'total_row', tax_columns)
+ data.append(total_row_map.get('total_row'))
+ skip_total_row = 1
+
+ return columns, data, None, None, None, skip_total_row
-def get_columns(additional_table_columns):
- columns = [
- _("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
- _("Item Group") + ":Link/Item Group:100", "Description::150", _("Invoice") + ":Link/Purchase Invoice:120",
- _("Posting Date") + ":Date:80", _("Supplier") + ":Link/Supplier:120",
- "Supplier Name::120"
- ]
+def get_columns(additional_table_columns, filters):
+
+ columns = []
+
+ if filters.get('group_by') != ('Item'):
+ columns.extend(
+ [
+ {
+ 'label': _('Item Code'),
+ 'fieldname': 'item_code',
+ 'fieldtype': 'Link',
+ 'options': 'Item',
+ 'width': 120
+ },
+ {
+ 'label': _('Item Name'),
+ 'fieldname': 'item_name',
+ 'fieldtype': 'Data',
+ 'width': 120
+ }
+ ]
+ )
+
+ if filters.get('group_by') not in ('Item', 'Item Group'):
+ columns.extend([
+ {
+ 'label': _('Item Group'),
+ 'fieldname': 'item_group',
+ 'fieldtype': 'Link',
+ 'options': 'Item Group',
+ 'width': 120
+ }
+ ])
+
+ columns.extend([
+ {
+ 'label': _('Description'),
+ 'fieldname': 'description',
+ 'fieldtype': 'Data',
+ 'width': 150
+ },
+ {
+ 'label': _('Invoice'),
+ 'fieldname': 'invoice',
+ 'fieldtype': 'Link',
+ 'options': 'Purchase Invoice',
+ 'width': 120
+ },
+ {
+ 'label': _('Posting Date'),
+ 'fieldname': 'posting_date',
+ 'fieldtype': 'Date',
+ 'width': 120
+ }
+ ])
+
+ if filters.get('group_by') != 'Supplier':
+ columns.extend([
+ {
+ 'label': _('Supplier'),
+ 'fieldname': 'supplier',
+ 'fieldtype': 'Link',
+ 'options': 'Supplier',
+ 'width': 120
+ },
+ {
+ 'label': _('Supplier Name'),
+ 'fieldname': 'supplier_name',
+ 'fieldtype': 'Data',
+ 'width': 120
+ }
+ ])
if additional_table_columns:
columns += additional_table_columns
columns += [
- "Payable Account:Link/Account:120",
- _("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80",
- _("Company") + ":Link/Company:100", _("Purchase Order") + ":Link/Purchase Order:100",
- _("Purchase Receipt") + ":Link/Purchase Receipt:100", _("Expense Account") + ":Link/Account:140",
- _("Stock Qty") + ":Float:120", _("Stock UOM") + "::100",
- _("Rate") + ":Currency/currency:120", _("Amount") + ":Currency/currency:120"
+ {
+ 'label': _('Payable Account'),
+ 'fieldname': 'credit_to',
+ 'fieldtype': 'Link',
+ 'options': 'Account',
+ 'width': 80
+ },
+ {
+ 'label': _('Mode Of Payment'),
+ 'fieldname': 'mode_of_payment',
+ 'fieldtype': 'Data',
+ 'width': 120
+ },
+ {
+ 'label': _('Project'),
+ 'fieldname': 'project',
+ 'fieldtype': 'Link',
+ 'options': 'Project',
+ 'width': 80
+ },
+ {
+ 'label': _('Company'),
+ 'fieldname': 'company',
+ 'fieldtype': 'Link',
+ 'options': 'Company',
+ 'width': 80
+ },
+ {
+ 'label': _('Purchase Order'),
+ 'fieldname': 'purchase_order',
+ 'fieldtype': 'Link',
+ 'options': 'Purchase Order',
+ 'width': 100
+ },
+ {
+ 'label': _("Purchase Receipt"),
+ 'fieldname': 'Purchase Receipt',
+ 'fieldtype': 'Link',
+ 'options': 'Purchase Receipt',
+ 'width': 100
+ },
+ {
+ 'label': _('Expense Account'),
+ 'fieldname': 'expense_account',
+ 'fieldtype': 'Link',
+ 'options': 'Account',
+ 'width': 100
+ },
+ {
+ 'label': _('Stock Qty'),
+ 'fieldname': 'stock_qty',
+ 'fieldtype': 'Float',
+ 'width': 100
+ },
+ {
+ 'label': _('Stock UOM'),
+ 'fieldname': 'stock_uom',
+ 'fieldtype': 'Link',
+ 'options': 'UOM',
+ 'width': 100
+ },
+ {
+ 'label': _('Rate'),
+ 'fieldname': 'rate',
+ 'fieldtype': 'Float',
+ 'options': 'currency',
+ 'width': 100
+ },
+ {
+ 'label': _('Amount'),
+ 'fieldname': 'amount',
+ 'fieldtype': 'Currency',
+ 'options': 'currency',
+ 'width': 100
+ },
+ {
+ 'fieldname': 'currency',
+ 'label': _('Currency'),
+ 'fieldtype': 'Currency',
+ 'width': 80,
+ 'hidden': 1
+ }
]
+ if filters.get('group_by'):
+ columns.append({
+ 'label': _('% Of Grand Total'),
+ 'fieldname': 'percent_gt',
+ 'fieldtype': 'Float',
+ 'width': 80
+ })
+
return columns
def get_conditions(filters):
@@ -103,6 +297,11 @@
if filters.get(opts[0]):
conditions += opts[1]
+ if not filters.get("group_by"):
+ conditions += "ORDER BY `tabPurchase Invoice`.posting_date desc, `tabPurchase Invoice Item`.item_code desc"
+ else:
+ conditions += get_group_by_conditions(filters, 'Purchase Invoice')
+
return conditions
def get_items(filters, additional_query_columns):
@@ -129,7 +328,6 @@
from `tabPurchase Invoice`, `tabPurchase Invoice Item`
where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and
`tabPurchase Invoice`.docstatus = 1 %s %s
- order by `tabPurchase Invoice`.posting_date desc, `tabPurchase Invoice Item`.item_code desc
""".format(additional_query_columns) % (conditions, match_conditions), filters, as_dict=1)
def get_aii_accounts():
diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js
index 9dd9b3f..8a9c76f 100644
--- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js
+++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js
@@ -4,48 +4,62 @@
frappe.query_reports["Item-wise Sales Register"] = {
"filters": [
{
- "fieldname":"date_range",
+ "fieldname": "date_range",
"label": __("Date Range"),
"fieldtype": "DateRange",
"default": [frappe.datetime.add_months(frappe.datetime.get_today(),-1), frappe.datetime.get_today()],
"reqd": 1
},
{
- "fieldname":"customer",
+ "fieldname": "customer",
"label": __("Customer"),
"fieldtype": "Link",
"options": "Customer"
},
{
- "fieldname":"company",
+ "fieldname": "company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_user_default("Company")
},
{
- "fieldname":"mode_of_payment",
+ "fieldname": "mode_of_payment",
"label": __("Mode of Payment"),
"fieldtype": "Link",
"options": "Mode of Payment"
},
{
- "fieldname":"warehouse",
+ "fieldname": "warehouse",
"label": __("Warehouse"),
"fieldtype": "Link",
"options": "Warehouse"
},
{
- "fieldname":"brand",
+ "fieldname": "brand",
"label": __("Brand"),
"fieldtype": "Link",
"options": "Brand"
},
{
- "fieldname":"item_group",
+ "fieldname": "item_group",
"label": __("Item Group"),
"fieldtype": "Link",
"options": "Item Group"
+ },
+ {
+ "label": __("Group By"),
+ "fieldname": "group_by",
+ "fieldtype": "Select",
+ "options": ["Customer Group", "Customer", "Item Group", "Item", "Territory", "Invoice"]
}
- ]
+ ],
+ "formatter": function(value, row, column, data, default_formatter) {
+ value = default_formatter(value, row, column, data);
+ if (data && data.bold) {
+ value = value.bold();
+
+ }
+ return value;
+ }
}
diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
index 9da89ff..2cc2db6 100644
--- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
+++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe, erpnext
from frappe import _
-from frappe.utils import flt
+from frappe.utils import flt, cstr
from frappe.model.meta import get_field_precision
from frappe.utils.xlsxutils import handle_html
from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
@@ -15,23 +15,25 @@
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
if not filters: filters = {}
filters.update({"from_date": filters.get("date_range") and filters.get("date_range")[0], "to_date": filters.get("date_range") and filters.get("date_range")[1]})
- columns = get_columns(additional_table_columns)
+ columns = get_columns(additional_table_columns, filters)
company_currency = frappe.get_cached_value('Company', filters.get("company"), "default_currency")
item_list = get_items(filters, additional_query_columns)
if item_list:
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency)
- columns.append({
- "fieldname": "currency",
- "label": _("Currency"),
- "fieldtype": "Data",
- "width": 80
- })
+
mode_of_payments = get_mode_of_payments(set([d.parent for d in item_list]))
so_dn_map = get_delivery_notes_against_sales_order(item_list)
data = []
+ total_row_map = {}
+ skip_total_row = 0
+ prev_group_by_value = ''
+
+ if filters.get('group_by'):
+ grand_total = get_grand_total(filters, 'Sales Invoice')
+
for d in item_list:
delivery_note = None
if d.delivery_note:
@@ -42,57 +44,285 @@
if not delivery_note and d.update_stock:
delivery_note = d.parent
- row = [d.item_code, d.item_name, d.item_group, d.description, d.parent, d.posting_date, d.customer, d.customer_name]
+ row = {
+ 'item_code': d.item_code,
+ 'item_name': d.item_name,
+ 'item_group': d.item_group,
+ 'description': d.description,
+ 'invoice': d.parent,
+ 'posting_date': d.posting_date,
+ 'customer': d.customer,
+ 'customer_name': d.customer_name,
+ 'customer_group': d.customer_group,
+ }
if additional_query_columns:
for col in additional_query_columns:
- row.append(d.get(col))
+ row.update({
+ col: d.get(col)
+ })
- row += [
- d.customer_group, d.debit_to, ", ".join(mode_of_payments.get(d.parent, [])),
- d.territory, d.project, d.company, d.sales_order,
- delivery_note, d.income_account, d.cost_center, d.stock_qty, d.stock_uom
- ]
+ row.update({
+ 'debit_to': d.debit_to,
+ 'mode_of_payment': ", ".join(mode_of_payments.get(d.parent, [])),
+ 'territory': d.territory,
+ 'project': d.project,
+ 'company': d.company,
+ 'sales_order': d.sales_order,
+ 'delivery_note': d.delivery_note,
+ 'income_account': d.income_account,
+ 'cost_center': d.cost_center,
+ 'stock_qty': d.stock_qty,
+ 'stock_uom': d.stock_uom
+ })
if d.stock_uom != d.uom and d.stock_qty:
- row += [(d.base_net_rate * d.qty)/d.stock_qty, d.base_net_amount]
+ row.update({
+ 'rate': (d.base_net_rate * d.qty)/d.stock_qty,
+ 'amount': d.base_net_amount
+ })
else:
- row += [d.base_net_rate, d.base_net_amount]
+ row.update({
+ 'rate': d.base_net_rate,
+ 'amount': d.base_net_amount
+ })
total_tax = 0
for tax in tax_columns:
item_tax = itemised_tax.get(d.name, {}).get(tax, {})
- row += [item_tax.get("tax_rate", 0), item_tax.get("tax_amount", 0)]
+ row.update({
+ frappe.scrub(tax + ' Rate'): item_tax.get("tax_rate", 0),
+ frappe.scrub(tax + ' Amount'): item_tax.get("tax_amount", 0),
+ })
total_tax += flt(item_tax.get("tax_amount"))
- row += [total_tax, d.base_net_amount + total_tax, company_currency]
+ row.update({
+ 'total_tax': total_tax,
+ 'total': d.base_net_amount + total_tax,
+ 'currency': company_currency
+ })
+
+ if filters.get('group_by'):
+ row.update({'percent_gt': flt(row['total']/grand_total) * 100})
+ group_by_field, subtotal_display_field = get_group_by_and_display_fields(filters)
+ data, prev_group_by_value = add_total_row(data, filters, prev_group_by_value, d, total_row_map,
+ group_by_field, subtotal_display_field, grand_total, tax_columns)
+ add_sub_total_row(row, total_row_map, d.get(group_by_field, ''), tax_columns)
data.append(row)
- return columns, data
+ if filters.get('group_by'):
+ total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
+ total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
+ data.append(total_row)
+ data.append({})
+ add_sub_total_row(total_row, total_row_map, 'total_row', tax_columns)
+ data.append(total_row_map.get('total_row'))
+ skip_total_row = 1
+
+ return columns, data, None, None, None, skip_total_row
-def get_columns(additional_table_columns):
- columns = [
- _("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
- _("Item Group") + ":Link/Item Group:100", "Description::150", _("Invoice") + ":Link/Sales Invoice:120",
- _("Posting Date") + ":Date:80", _("Customer") + ":Link/Customer:120",
- _("Customer Name") + "::120"]
+def get_columns(additional_table_columns, filters):
+ columns = []
+
+ if filters.get('group_by') != ('Item'):
+ columns.extend(
+ [
+ {
+ 'label': _('Item Code'),
+ 'fieldname': 'item_code',
+ 'fieldtype': 'Link',
+ 'options': 'Item',
+ 'width': 120
+ },
+ {
+ 'label': _('Item Name'),
+ 'fieldname': 'item_name',
+ 'fieldtype': 'Data',
+ 'width': 120
+ }
+ ]
+ )
+
+ if filters.get('group_by') not in ('Item', 'Item Group'):
+ columns.extend([
+ {
+ 'label': _('Item Group'),
+ 'fieldname': 'item_group',
+ 'fieldtype': 'Link',
+ 'options': 'Item Group',
+ 'width': 120
+ }
+ ])
+
+ columns.extend([
+ {
+ 'label': _('Description'),
+ 'fieldname': 'description',
+ 'fieldtype': 'Data',
+ 'width': 150
+ },
+ {
+ 'label': _('Invoice'),
+ 'fieldname': 'invoice',
+ 'fieldtype': 'Link',
+ 'options': 'Sales Invoice',
+ 'width': 120
+ },
+ {
+ 'label': _('Posting Date'),
+ 'fieldname': 'posting_date',
+ 'fieldtype': 'Date',
+ 'width': 120
+ }
+ ])
+
+ if filters.get('group_by') != 'Customer':
+ columns.extend([
+ {
+ 'label': _('Customer Group'),
+ 'fieldname': 'customer_group',
+ 'fieldtype': 'Link',
+ 'options': 'Customer Group',
+ 'width': 120
+ }
+ ])
+
+ if filters.get('group_by') not in ('Customer', 'Customer Group'):
+ columns.extend([
+ {
+ 'label': _('Customer'),
+ 'fieldname': 'customer',
+ 'fieldtype': 'Link',
+ 'options': 'Customer',
+ 'width': 120
+ },
+ {
+ 'label': _('Customer Name'),
+ 'fieldname': 'customer_name',
+ 'fieldtype': 'Data',
+ 'width': 120
+ }
+ ])
if additional_table_columns:
columns += additional_table_columns
columns += [
- _("Customer Group") + ":Link/Customer Group:120",
- _("Receivable Account") + ":Link/Account:120",
- _("Mode of Payment") + "::120", _("Territory") + ":Link/Territory:80",
- _("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100",
- _("Sales Order") + ":Link/Sales Order:100", _("Delivery Note") + ":Link/Delivery Note:100",
- _("Income Account") + ":Link/Account:140", _("Cost Center") + ":Link/Cost Center:140",
- _("Stock Qty") + ":Float:120", _("Stock UOM") + "::100",
- _("Rate") + ":Currency/currency:120",
- _("Amount") + ":Currency/currency:120"
+ {
+ 'label': _('Receivable Account'),
+ 'fieldname': 'debit_to',
+ 'fieldtype': 'Link',
+ 'options': 'Account',
+ 'width': 80
+ },
+ {
+ 'label': _('Mode Of Payment'),
+ 'fieldname': 'mode_of_payment',
+ 'fieldtype': 'Data',
+ 'width': 120
+ }
]
+ if filters.get('group_by') != 'Terriotory':
+ columns.extend([
+ {
+ 'label': _("Territory"),
+ 'fieldname': 'territory',
+ 'fieldtype': 'Link',
+ 'options': 'Territory',
+ 'width': 80
+ }
+ ])
+
+
+ columns += [
+ {
+ 'label': _('Project'),
+ 'fieldname': 'project',
+ 'fieldtype': 'Link',
+ 'options': 'Project',
+ 'width': 80
+ },
+ {
+ 'label': _('Company'),
+ 'fieldname': 'company',
+ 'fieldtype': 'Link',
+ 'options': 'Company',
+ 'width': 80
+ },
+ {
+ 'label': _('Sales Order'),
+ 'fieldname': 'sales_order',
+ 'fieldtype': 'Link',
+ 'options': 'Sales Order',
+ 'width': 100
+ },
+ {
+ 'label': _("Delivery Note"),
+ 'fieldname': 'delivery_note',
+ 'fieldtype': 'Link',
+ 'options': 'Delivery Note',
+ 'width': 100
+ },
+ {
+ 'label': _('Income Account'),
+ 'fieldname': 'income_account',
+ 'fieldtype': 'Link',
+ 'options': 'Account',
+ 'width': 100
+ },
+ {
+ 'label': _("Cost Center"),
+ 'fieldname': 'cost_center',
+ 'fieldtype': 'Link',
+ 'options': 'Cost Center',
+ 'width': 100
+ },
+ {
+ 'label': _('Stock Qty'),
+ 'fieldname': 'stock_qty',
+ 'fieldtype': 'Float',
+ 'width': 100
+ },
+ {
+ 'label': _('Stock UOM'),
+ 'fieldname': 'stock_uom',
+ 'fieldtype': 'Link',
+ 'options': 'UOM',
+ 'width': 100
+ },
+ {
+ 'label': _('Rate'),
+ 'fieldname': 'rate',
+ 'fieldtype': 'Float',
+ 'options': 'currency',
+ 'width': 100
+ },
+ {
+ 'label': _('Amount'),
+ 'fieldname': 'amount',
+ 'fieldtype': 'Currency',
+ 'options': 'currency',
+ 'width': 100
+ },
+ {
+ 'fieldname': 'currency',
+ 'label': _('Currency'),
+ 'fieldtype': 'Currency',
+ 'width': 80,
+ 'hidden': 1
+ }
+ ]
+
+ if filters.get('group_by'):
+ columns.append({
+ 'label': _('% Of Grand Total'),
+ 'fieldname': 'percent_gt',
+ 'fieldtype': 'Float',
+ 'width': 80
+ })
+
return columns
def get_conditions(filters):
@@ -112,24 +342,32 @@
and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)"""
if filters.get("warehouse"):
- conditions += """ and exists(select name from `tabSales Invoice Item`
- where parent=`tabSales Invoice`.name
- and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s)"""
+ conditions += """and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s"""
if filters.get("brand"):
- conditions += """ and exists(select name from `tabSales Invoice Item`
- where parent=`tabSales Invoice`.name
- and ifnull(`tabSales Invoice Item`.brand, '') = %(brand)s)"""
+ conditions += """and ifnull(`tabSales Invoice Item`.brand, '') = %(brand)s"""
if filters.get("item_group"):
- conditions += """ and exists(select name from `tabSales Invoice Item`
- where parent=`tabSales Invoice`.name
- and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s)"""
+ conditions += """and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s"""
+ if not filters.get("group_by"):
+ conditions += "ORDER BY `tabSales Invoice`.posting_date desc, `tabSales Invoice Item`.item_group desc"
+ else:
+ conditions += get_group_by_conditions(filters, 'Sales Invoice')
return conditions
+def get_group_by_conditions(filters, doctype):
+ if filters.get("group_by") == 'Invoice':
+ return "ORDER BY `tab{0} Item`.parent desc".format(doctype)
+ elif filters.get("group_by") == 'Item':
+ return "ORDER BY `tab{0} Item`.`item_code`".format(doctype)
+ elif filters.get("group_by") == 'Item Group':
+ return "ORDER BY `tab{0} Item`.{1}".format(doctype, frappe.scrub(filters.get('group_by')))
+ elif filters.get("group_by") in ('Customer', 'Customer Group', 'Territory', 'Supplier'):
+ return "ORDER BY `tab{0}`.{1}".format(doctype, frappe.scrub(filters.get('group_by')))
+
def get_items(filters, additional_query_columns):
conditions = get_conditions(filters)
match_conditions = frappe.build_match_conditions("Sales Invoice")
@@ -156,9 +394,8 @@
`tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom, `tabSales Invoice Item`.qty {0}
from `tabSales Invoice`, `tabSales Invoice Item`
where `tabSales Invoice`.name = `tabSales Invoice Item`.parent
- and `tabSales Invoice`.docstatus = 1 %s %s
- order by `tabSales Invoice`.posting_date desc, `tabSales Invoice Item`.item_code desc
- """.format(additional_query_columns or '') % (conditions, match_conditions), filters, as_dict=1)
+ and `tabSales Invoice`.docstatus = 1 {1} {2}
+ """.format(additional_query_columns or '', conditions, match_conditions), filters, as_dict=1) #nosec
def get_delivery_notes_against_sales_order(item_list):
so_dn_map = frappe._dict()
@@ -177,6 +414,15 @@
return so_dn_map
+def get_grand_total(filters, doctype):
+
+ return frappe.db.sql(""" SELECT
+ SUM(`tab{0}`.base_grand_total)
+ FROM `tab{0}`
+ WHERE `tab{0}`.docstatus = 1
+ and posting_date between %s and %s
+ """.format(doctype), (filters.get('from_date'), filters.get('to_date')))[0][0] #nosec
+
def get_deducted_taxes():
return frappe.db.sql_list("select name from `tabPurchase Taxes and Charges` where add_deduct_tax = 'Deduct'")
@@ -264,9 +510,117 @@
tax_columns.sort()
for desc in tax_columns:
- columns.append(desc + " Rate:Data:80")
- columns.append(desc + " Amount:Currency/currency:100")
+ columns.append({
+ 'label': _(desc + ' Rate'),
+ 'fieldname': frappe.scrub(desc + ' Rate'),
+ 'fieldtype': 'Float',
+ 'width': 100
+ })
- columns += ["Total Tax:Currency/currency:80", "Total:Currency/currency:100"]
+ columns.append({
+ 'label': _(desc + ' Amount'),
+ 'fieldname': frappe.scrub(desc + ' Amount'),
+ 'fieldtype': 'Currency',
+ 'options': 'currency',
+ 'width': 100
+ })
+
+ columns += [
+ {
+ 'label': _('Total Tax'),
+ 'fieldname': 'total_tax',
+ 'fieldtype': 'Currency',
+ 'options': 'currency',
+ 'width': 100
+ },
+ {
+ 'label': _('Total'),
+ 'fieldname': 'total',
+ 'fieldtype': 'Currency',
+ 'options': 'currency',
+ 'width': 100
+ }
+ ]
return itemised_tax, tax_columns
+
+def add_total_row(data, filters, prev_group_by_value, item, total_row_map,
+ group_by_field, subtotal_display_field, grand_total, tax_columns):
+ if prev_group_by_value != item.get(group_by_field, ''):
+ if prev_group_by_value:
+ total_row = total_row_map.get(prev_group_by_value)
+ data.append(total_row)
+ data.append({})
+ add_sub_total_row(total_row, total_row_map, 'total_row', tax_columns)
+
+ prev_group_by_value = item.get(group_by_field, '')
+
+ total_row_map.setdefault(item.get(group_by_field, ''), {
+ subtotal_display_field: get_display_value(filters, group_by_field, item),
+ 'stock_qty': 0.0,
+ 'amount': 0.0,
+ 'bold': 1,
+ 'total_tax': 0.0,
+ 'total': 0.0,
+ 'percent_gt': 0.0
+ })
+
+ total_row_map.setdefault('total_row', {
+ subtotal_display_field: "Total",
+ 'stock_qty': 0.0,
+ 'amount': 0.0,
+ 'bold': 1,
+ 'total_tax': 0.0,
+ 'total': 0.0,
+ 'percent_gt': 0.0
+ })
+
+ return data, prev_group_by_value
+
+def get_display_value(filters, group_by_field, item):
+ if filters.get('group_by') == 'Item':
+ if item.get('item_code') != item.get('item_name'):
+ value = cstr(item.get('item_code')) + "<br><br>" + \
+ "<span style='font-weight: normal'>" + cstr(item.get('item_name')) + "</span>"
+ else:
+ value = item.get('item_code', '')
+ elif filters.get('group_by') in ('Customer', 'Supplier'):
+ party = frappe.scrub(filters.get('group_by'))
+ if item.get(party) != item.get(party+'_name'):
+ value = item.get(party) + "<br><br>" + \
+ "<span style='font-weight: normal'>" + item.get(party+'_name') + "</span>"
+ else:
+ value = item.get(party)
+ else:
+ value = item.get(group_by_field)
+
+ return value
+
+def get_group_by_and_display_fields(filters):
+ if filters.get('group_by') == 'Item':
+ group_by_field = 'item_code'
+ subtotal_display_field = 'invoice'
+ elif filters.get('group_by') == 'Invoice':
+ group_by_field = 'parent'
+ subtotal_display_field = 'item_code'
+ else:
+ group_by_field = frappe.scrub(filters.get('group_by'))
+ subtotal_display_field = 'item_code'
+
+ return group_by_field, subtotal_display_field
+
+def add_sub_total_row(item, total_row_map, group_by_value, tax_columns):
+ total_row = total_row_map.get(group_by_value)
+ total_row['stock_qty'] += item['stock_qty']
+ total_row['amount'] += item['amount']
+ total_row['total_tax'] += item['total_tax']
+ total_row['total'] += item['total']
+ total_row['percent_gt'] += item['percent_gt']
+
+ for tax in tax_columns:
+ total_row.setdefault(frappe.scrub(tax + ' Amount'), 0.0)
+ total_row[frappe.scrub(tax + ' Amount')] += flt(item[frappe.scrub(tax + ' Amount')])
+
+
+
+
diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py
index afdd31d..2be90bc 100644
--- a/erpnext/accounts/report/sales_register/sales_register.py
+++ b/erpnext/accounts/report/sales_register/sales_register.py
@@ -139,7 +139,7 @@
columns +=[
{
- 'label': _("Custmer Group"),
+ 'label': _("Customer Group"),
'fieldname': 'customer_group',
'fieldtype': 'Link',
'options': 'Customer Group',
@@ -175,7 +175,7 @@
'label': _("Project"),
'fieldname': 'project',
'fieldtype': 'Link',
- 'options': 'project',
+ 'options': 'Project',
'width': 80
},
{
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 5ad8cb5..4789063 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -513,7 +513,7 @@
where reference_type=%s and reference_name=%s
and docstatus < 2""", (now(), frappe.session.user, ref_type, ref_no))
- frappe.msgprint(_("Journal Entries {0} are un-linked".format("\n".join(linked_jv))))
+ frappe.msgprint(_("Journal Entries {0} are un-linked").format("\n".join(linked_jv)))
def remove_ref_doc_link_from_pe(ref_type, ref_no):
linked_pe = frappe.db.sql_list("""select parent from `tabPayment Entry Reference`
@@ -536,7 +536,7 @@
where name=%s""", (pe_doc.total_allocated_amount, pe_doc.base_total_allocated_amount,
pe_doc.unallocated_amount, now(), frappe.session.user, pe))
- frappe.msgprint(_("Payment Entries {0} are un-linked".format("\n".join(linked_pe))))
+ frappe.msgprint(_("Payment Entries {0} are un-linked").format("\n".join(linked_pe)))
@frappe.whitelist()
def get_company_default(company, fieldname):