Merge branch 'develop' of https://github.com/frappe/erpnext into custom_append_to

This commit is contained in:
Himanshu Warekar 2020-04-06 11:34:27 +05:30
commit c207c457a5
220 changed files with 2413 additions and 4596 deletions

View File

@ -15,18 +15,18 @@
ERPNext as a monolith includes the following areas for managing businesses:
1. [Accounting](https://erpnext.com/docs/user/manual/en/accounts)
1. [Inventory](https://erpnext.com/docs/user/manual/en/stock)
1. [CRM](https://erpnext.com/docs/user/manual/en/CRM)
1. [Sales](https://erpnext.com/docs/user/manual/en/selling)
1. [Purchase](https://erpnext.com/docs/user/manual/en/buying)
1. [HRMS](https://erpnext.com/docs/user/manual/en/human-resources)
1. [Project Management](https://erpnext.com/docs/user/manual/en/projects)
1. [Support](https://erpnext.com/docs/user/manual/en/support)
1. [Asset Management](https://erpnext.com/docs/user/manual/en/asset)
1. [Accounting](https://erpnext.com/open-source-accounting)
1. [Inventory](https://erpnext.com/distribution/inventory-management-system)
1. [CRM](https://erpnext.com/open-source-crm)
1. [Sales](https://erpnext.com/open-source-sales-purchase)
1. [Purchase](https://erpnext.com/open-source-sales-purchase)
1. [HRMS](https://erpnext.com/open-source-hrms)
1. [Project Management](https://erpnext.com/open-source-projects)
1. [Support](https://erpnext.com/open-source-help-desk-software)
1. [Asset Management](https://erpnext.com/open-source-asset-management-software)
1. [Quality Management](https://erpnext.com/docs/user/manual/en/quality-management)
1. [Manufacturing](https://erpnext.com/docs/user/manual/en/manufacturing)
1. [Website Management](https://erpnext.com/docs/user/manual/en/website)
1. [Manufacturing](https://erpnext.com/open-source-manufacturing-erp-software)
1. [Website Management](https://erpnext.com/open-source-website-builder-software)
1. [Customize ERPNext](https://erpnext.com/docs/user/manual/en/customize-erpnext)
1. [And More](https://erpnext.com/docs/user/manual/en/)

View File

@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
__version__ = '12.2.0'
__version__ = '12.0.0-dev'
def get_default_company(user=None):
'''Get default company for user'''

View File

@ -26,7 +26,7 @@ def get(chart_name = None, chart = None, no_cache = None, filters = None, from_d
to_date = chart.to_date
timegrain = chart.time_interval
filters = frappe.parse_json(chart.filters_json)
filters = frappe.parse_json(filters) or frappe.parse_json(chart.filters_json)
account = filters.get("account")
company = filters.get("company")

View File

@ -1,4 +1,5 @@
{
"actions": [],
"allow_copy": 1,
"allow_import": 1,
"creation": "2013-01-30 12:49:46",
@ -196,10 +197,13 @@
],
"icon": "fa fa-money",
"idx": 1,
"modified": "2019-10-10 19:10:02.967554",
"is_tree": 1,
"links": [],
"modified": "2020-03-18 17:57:52.063233",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",
"nsm_parent_field": "parent_account",
"owner": "Administrator",
"permissions": [
{

View File

@ -102,7 +102,7 @@ class Account(NestedSet):
if not frappe.db.get_value("Account",
{'account_name': self.account_name, 'company': ancestors[0]}, 'name'):
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
else:
elif self.parent_account:
descendants = get_descendants_of('Company', self.company)
if not descendants: return
parent_acc_name_map = {}

View File

@ -406,11 +406,11 @@
"is_group": 1,
"Bewertungskorrektur zu Forderungen aus Lieferungen und Leistungen": {
"account_number": "9960"
},
"Debitoren": {
"is_group": 1,
"account_number": "10000"
},
},
"Debitoren": {
"is_group": 1,
"account_number": "10000"
},
"Forderungen aus Lieferungen und Leistungen": {
"account_number": "1200",
"account_type": "Receivable"
@ -663,16 +663,22 @@
"account_number": "1400"
},
"Abziehbare Vorsteuer 7 %": {
"account_number": "1401"
"account_number": "1401",
"account_type": "Tax",
"tax_rate": 7.0
},
"Abziehbare Vorsteuer aus innergem. Erwerb": {
"account_number": "1402"
},
"Abziehbare Vorsteuer aus innergem. Erwerb 19%": {
"account_number": "1404"
"account_number": "1404",
"account_type": "Tax",
"tax_rate": 19.0
},
"Abziehbare Vorsteuer 19 %": {
"account_number": "1406"
"account_number": "1406",
"account_type": "Tax",
"tax_rate": 19.0
},
"Abziehbare Vorsteuer nach \u00a7 13b UStG 19 %": {
"account_number": "1407"
@ -911,17 +917,31 @@
"is_group": 1,
"I - Gezeichnetes Kapital": {
"account_type": "Equity",
"is_group": 1
"is_group": 1,
"Gezeichnetes Kapital": {
"account_type": "Equity",
"account_number": "2900"
},
"Ausstehende Einlagen auf das gezeichnete Kapital": {
"account_number": "2910",
"is_group": 1
}
},
"II - Kapitalr\u00fccklage": {
"account_type": "Equity",
"is_group": 1
"is_group": 1,
"Kapitalr\u00fccklage": {
"account_number": "2920"
}
},
"III - Gewinnr\u00fccklagen": {
"account_type": "Equity",
"1 - gesetzliche R\u00fccklage": {
"account_type": "Equity",
"is_group": 1
"is_group": 1,
"Gesetzliche R\u00fccklage": {
"account_number": "2930"
}
},
"2 - R\u00fccklage f. Anteile an einem herrschenden oder mehrheitlich beteiligten Unternehmen": {
"account_type": "Equity",
@ -929,7 +949,10 @@
},
"3 - satzungsm\u00e4\u00dfige R\u00fccklagen": {
"account_type": "Equity",
"is_group": 1
"is_group": 1,
"Satzungsm\u00e4\u00dfige R\u00fccklagen": {
"account_number": "2950"
}
},
"4 - andere Gewinnr\u00fccklagen": {
"account_type": "Equity",
@ -963,7 +986,13 @@
},
"IV - Gewinnvortrag/Verlustvortrag": {
"account_type": "Equity",
"is_group": 1
"is_group": 1,
"Gewinnvortrag vor Verwendung": {
"account_number": "2970"
},
"Verlustvortrag vor Verwendung": {
"account_number": "2978"
}
},
"V - Jahres\u00fcberschu\u00df/Jahresfehlbetrag": {
"account_type": "Equity",
@ -1197,15 +1226,15 @@
"is_group": 1,
"Bewertungskorrektur zu Verb. aus Lieferungen und Leistungen": {
"account_number": "9964"
},
"Kreditoren": {
"account_number": "70000",
"is_group": 1,
"Wareneingangs-­Verrechnungskonto" : {
"account_number": "70001",
"account_type": "Stock Received But Not Billed"
}
},
},
"Kreditoren": {
"account_number": "70000",
"is_group": 1,
"Wareneingangs-­Verrechnungskonto" : {
"account_number": "70001",
"account_type": "Stock Received But Not Billed"
}
},
"Verb. aus Lieferungen und Leistungen": {
"account_number": "3300",
"account_type": "Payable"
@ -1488,17 +1517,21 @@
},
"Umsatzsteuer 7 %": {
"account_number": "3801",
"account_type": "Tax"
"account_type": "Tax",
"tax_rate": 7.0
},
"Umsatzsteuer aus innergem. Erwerb": {
"account_number": "3802"
},
"Umsatzsteuer aus innergem. Erwerb 19 %": {
"account_number": "3804"
"account_number": "3804",
"account_type": "Tax",
"tax_rate": 19.0
},
"Umsatzsteuer 19 %": {
"account_number": "3806",
"account_type": "Tax"
"account_type": "Tax",
"tax_rate": 19.0
},
"Umsatzsteuer aus im Inland steuerpfl. EU-Lieferungen": {
"account_number": "3807"
@ -1653,7 +1686,15 @@
"Erl\u00f6se 7 % USt": {
"account_number": "4300",
"account_type": "Income Account"
},
},
"Erl\u00f6se 16 % USt": {
"account_number": "4340",
"account_type": "Income Account"
},
"Erl\u00f6se 19 % USt": {
"account_number": "4400",
"account_type": "Income Account"
},
"Erl\u00f6se aus im Inland steuerpfl. EU-Lieferungen 7 % USt": {
"account_number": "4310"
},
@ -1681,19 +1722,6 @@
"Erl\u00f6se aus im anderen EU-Land steuerbaren Leistungen, im Inland nicht steuerbare Ums\u00e4tze": {
"account_number": "4339"
},
"Erl\u00f6se 16 % USt (Gruppe)": {
"is_group": 1,
"Erl\u00f6se 16 % USt": {
"account_number": "4340"
}
},
"Erl\u00f6se 19 % USt (Gruppe)": {
"is_group": 1,
"Erl\u00f6se 19 % USt": {
"account_number": "4400",
"account_type": "Income Account"
}
},
"Grundst\u00fccksertr\u00e4ge (Gruppe)": {
"is_group": 1,
"Grundst\u00fccksertr\u00e4ge": {
@ -1752,14 +1780,12 @@
"2 - Herstellungskosten der zur Erzielung der Umsatzerl\u00f6se erbrachten Leistungen": {
"root_type": "Expense",
"is_group": 1,
"Herstellungskosten (Gruppe)": {
"Herstellungskosten": {
"account_number": "6990",
"account_type": "Cost of Goods Sold"
},
"Herstellungskosten: Schwund": {
"account_type": "Stock Adjustment"
}
"Herstellungskosten": {
"account_number": "6990",
"account_type": "Cost of Goods Sold"
},
"Herstellungskosten: Schwund": {
"account_type": "Stock Adjustment"
},
"Aufwendungen f. Roh-, Hilfs- und Betriebsstoffe und f. bezogene Waren": {
"account_number": "5000",
@ -1809,10 +1835,10 @@
"Energiestoffe (Fertigung)": {
"account_number": "5190"
},
"Energiestoffe (Fertigung)7% Vorsteuer": {
"Energiestoffe (Fertigung) 7% Vorsteuer": {
"account_number": "5191"
},
"Energiestoffe (Fertigung)19% Vorsteuer": {
"Energiestoffe (Fertigung) 19% Vorsteuer": {
"account_number": "5192"
}
}
@ -1935,49 +1961,49 @@
},
"Nachl\u00e4sse aus innergem. Erwerb 15 % Vorsteuer und 15 % Umsatzsteuer": {
"account_number": "5727"
},
"Erhaltene Skonti (Gruppe)": {
"is_group": 1,
"Erh. Skonti": {
"account_number": "5730"
},
"Erh. Skonti 7 % Vorsteuer": {
"account_number": "5731"
},
"Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe": {
"account_number": "5733"
},
"Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe 7% Vorsteuer": {
"account_number": "5734"
},
"Erh. Skonti 19 % Vorsteuer": {
"account_number": "5736"
},
"Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe 19% Vorsteuer": {
"account_number": "5738"
},
"Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe aus steuerpfl. innergem. Erwerb 19% Vorst. u. 19% Ust.": {
"account_number": "5741"
},
"Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe aus steuerpfl. innergem. Erwerb 7% Vorst. u. 7% Ust.": {
"account_number": "5743"
},
"Erh. Skonti aus steuerpflichtigem innergem. Erwerb": {
"account_number": "5745"
},
"Erh. Skonti aus steuerpflichtigem innergem. Erwerb 7% Vorst. u. 7% Ust.": {
"account_number": "5746"
},
"Erh. Skonti aus steuerpflichtigem innergem. Erwerb 19% Vorst. u. 19% Ust.": {
"account_number": "5748"
},
"Erh. Skonti aus Erwerb Roh-,Hilfs-,Betriebsstoff letzter Abn.innerh.Dreiecksg. 19% Vorst. und 19% Ust.": {
"account_number": "5792"
},
"Erh. Skonti aus Erwerb Waren als letzter Abnehmer innerh. Dreiecksgesch. 19% Vorst. u. 19% Ust.": {
"account_number": "5793"
}
}
}
},
"Erhaltene Skonti (Gruppe)": {
"is_group": 1,
"Erh. Skonti": {
"account_number": "5730"
},
"Erh. Skonti 7 % Vorsteuer": {
"account_number": "5731"
},
"Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe": {
"account_number": "5733"
},
"Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe 7% Vorsteuer": {
"account_number": "5734"
},
"Erh. Skonti 19 % Vorsteuer": {
"account_number": "5736"
},
"Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe 19% Vorsteuer": {
"account_number": "5738"
},
"Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe aus steuerpfl. innergem. Erwerb 19% Vorst. u. 19% Ust.": {
"account_number": "5741"
},
"Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe aus steuerpfl. innergem. Erwerb 7% Vorst. u. 7% Ust.": {
"account_number": "5743"
},
"Erh. Skonti aus steuerpflichtigem innergem. Erwerb": {
"account_number": "5745"
},
"Erh. Skonti aus steuerpflichtigem innergem. Erwerb 7% Vorst. u. 7% Ust.": {
"account_number": "5746"
},
"Erh. Skonti aus steuerpflichtigem innergem. Erwerb 19% Vorst. u. 19% Ust.": {
"account_number": "5748"
},
"Erh. Skonti aus Erwerb Roh-,Hilfs-,Betriebsstoff letzter Abn.innerh.Dreiecksg. 19% Vorst. und 19% Ust.": {
"account_number": "5792"
},
"Erh. Skonti aus Erwerb Waren als letzter Abnehmer innerh. Dreiecksgesch. 19% Vorst. u. 19% Ust.": {
"account_number": "5793"
}
},
"Bezugsnebenkosten (Gruppe)": {
"is_group": 1,
@ -2295,49 +2321,49 @@
},
"6 - sonstige betriebliche Ertr\u00e4ge": {
"root_type": "Income",
"is_group": 1,
"Erhaltene Boni (Gruppe)": {
"is_group": 1,
"Erhaltene Boni 7 % Vorsteuer": {
"account_number": "5750"
},
"Erhaltene Boni aus Einkauf Roh-, Hilfs- und Betriebsstoffe": {
"account_number": "5753"
},
"Erhaltene Boni aus Einkauf Roh-, Hilfs- und Betriebsstoffe 7% Vorsteuer": {
"account_number": "5754"
},
"Erhaltene Boni aus Einkauf Roh-, Hilfs- und Betriebsstoffe 19% Vorsteuer": {
"account_number": "5755"
},
"Erhaltene Boni 19 % Vorsteuer": {
"account_number": "5760"
},
"Erhaltene Boni": {
"account_number": "5769"
}
},
"Erhaltene Rabatte (Gruppe)": {
"is_group": 1,
"Erhaltene Rabatte": {
"account_number": "5770"
},
"Erhaltene Rabatte 7 % Vorsteuer": {
"account_number": "5780"
},
"Erhaltene Rabatte aus Einkauf Roh-, Hilfs- und Betriebsstoffe": {
"account_number": "5783"
},
"Erhaltene Rabatte aus Einkauf Roh-, Hilfs- und Betriebsstoffe 7% Vorsteuer": {
"account_number": "5784"
},
"Erhaltene Rabatte aus Einkauf Roh-, Hilfs- und Betriebsstoffe 19% Vorsteuer": {
"account_number": "5785"
},
"Erhaltene Rabatte 19 % Vorsteuer": {
"account_number": "5790"
}
},
"is_group": 1,
"Erhaltene Boni (Gruppe)": {
"is_group": 1,
"Erhaltene Boni 7 % Vorsteuer": {
"account_number": "5750"
},
"Erhaltene Boni aus Einkauf Roh-, Hilfs- und Betriebsstoffe": {
"account_number": "5753"
},
"Erhaltene Boni aus Einkauf Roh-, Hilfs- und Betriebsstoffe 7% Vorsteuer": {
"account_number": "5754"
},
"Erhaltene Boni aus Einkauf Roh-, Hilfs- und Betriebsstoffe 19% Vorsteuer": {
"account_number": "5755"
},
"Erhaltene Boni 19 % Vorsteuer": {
"account_number": "5760"
},
"Erhaltene Boni": {
"account_number": "5769"
}
},
"Erhaltene Rabatte (Gruppe)": {
"is_group": 1,
"Erhaltene Rabatte": {
"account_number": "5770"
},
"Erhaltene Rabatte 7 % Vorsteuer": {
"account_number": "5780"
},
"Erhaltene Rabatte aus Einkauf Roh-, Hilfs- und Betriebsstoffe": {
"account_number": "5783"
},
"Erhaltene Rabatte aus Einkauf Roh-, Hilfs- und Betriebsstoffe 7% Vorsteuer": {
"account_number": "5784"
},
"Erhaltene Rabatte aus Einkauf Roh-, Hilfs- und Betriebsstoffe 19% Vorsteuer": {
"account_number": "5785"
},
"Erhaltene Rabatte 19 % Vorsteuer": {
"account_number": "5790"
}
},
"Andere aktivierte Eigenleistungen": {
"account_number": "4820"
},
@ -2407,29 +2433,26 @@
"Erl\u00f6se aus Verk\u00e4ufen Sachanlageverm\u00f6gen (bei Buchgewinn)": {
"account_number": "4849"
},
"Erl\u00f6se aus Verk\u00e4ufen immaterieller VG (bei Buchgewinn) (Gruppe)": {
"is_group": 1,
"Erl\u00f6se aus Verk\u00e4ufen immaterieller VG (bei Buchgewinn)": {
"account_number": "4850"
},
"Erl\u00f6se aus Verk\u00e4ufen Finanzanlagen (bei Buchgewinn)": {
"account_number": "4851"
},
"Erl\u00f6se aus Verk\u00e4ufen Finanzanlagen (inl\u00e4ndische Kap.Ges., bei Buchgewinn)": {
"account_number": "4852"
},
"Anlagenabg\u00e4nge Sachanlagen (Restbuchwert bei Buchvergewinn)": {
"account_number": "4855"
},
"Anlagenabg\u00e4nge immaterielle VG (Restbuchwert bei Buchgewinn)": {
"account_number": "4856"
},
"Anlagenabg\u00e4nge Finanzanlagen (Restbuchwert bei Buchgewinn)": {
"account_number": "4857"
},
"Anlagenabg\u00e4nge Finanzanlagen (inl\u00e4ndische Kap.Ges., Restbuchwert bei Buchgewinn)": {
"account_number": "4858"
}
"Erl\u00f6se aus Verk\u00e4ufen immaterieller VG (bei Buchgewinn)": {
"account_number": "4850"
},
"Erl\u00f6se aus Verk\u00e4ufen Finanzanlagen (bei Buchgewinn)": {
"account_number": "4851"
},
"Erl\u00f6se aus Verk\u00e4ufen Finanzanlagen (inl\u00e4ndische Kap.Ges., bei Buchgewinn)": {
"account_number": "4852"
},
"Anlagenabg\u00e4nge Sachanlagen (Restbuchwert bei Buchvergewinn)": {
"account_number": "4855"
},
"Anlagenabg\u00e4nge immaterielle VG (Restbuchwert bei Buchgewinn)": {
"account_number": "4856"
},
"Anlagenabg\u00e4nge Finanzanlagen (Restbuchwert bei Buchgewinn)": {
"account_number": "4857"
},
"Anlagenabg\u00e4nge Finanzanlagen (inl\u00e4ndische Kap.Ges., Restbuchwert bei Buchgewinn)": {
"account_number": "4858"
},
"Ertr\u00e4ge aus Zuschreibungen des Sachanlageverm\u00f6gens": {
"account_number": "4910",
@ -2552,20 +2575,17 @@
"Entnahme von Gegenst\u00e4nden ohne USt": {
"account_number": "4605"
},
"Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens 7 % USt (Gruppe)": {
"is_group": 1,
"Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens 7 % USt": {
"account_number": "4630"
},
"Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens ohne USt": {
"account_number": "4637"
},
"Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternnehmens ohne USt (Telefon-Nutzung)": {
"account_number": "4638"
},
"Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens ohne USt (Kfz-Nutzung)": {
"account_number": "4639"
}
"Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens 7 % USt": {
"account_number": "4630"
},
"Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens ohne USt": {
"account_number": "4637"
},
"Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternnehmens ohne USt (Telefon-Nutzung)": {
"account_number": "4638"
},
"Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens ohne USt (Kfz-Nutzung)": {
"account_number": "4639"
},
"Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens 19 % USt (Gruppe)": {
"is_group": 1,
@ -2603,14 +2623,11 @@
"Unentgeltliche Zuwendung von Gegenst\u00e4nden ohne USt": {
"account_number": "4689"
},
"Nicht steuerbare Ums\u00e4tze (Innenums\u00e4tze) (Gruppe)": {
"is_group": 1,
"Nicht steuerbare Ums\u00e4tze (Innenums\u00e4tze)": {
"account_number": "4690"
},
"Umsatzsteuerverg\u00fctungen, z.B. nach \u00a7 24 UStG": {
"account_number": "4695"
}
"Nicht steuerbare Ums\u00e4tze (Innenums\u00e4tze)": {
"account_number": "4690"
},
"Umsatzsteuerverg\u00fctungen, z.B. nach \u00a7 24 UStG": {
"account_number": "4695"
},
"Au\u00dferordentliche Ertr\u00e4ge (Gruppe)": {
"is_group": 1,
@ -2620,48 +2637,42 @@
"Au\u00dferordentliche Ertr\u00e4ge finanzwirksam": {
"account_number": "7401"
},
"Au\u00dferordentliche Ertr\u00e4ge nicht finanzwirksam (Gruppe)": {
"is_group": 1,
"Au\u00dferordentliche Ertr\u00e4ge nicht finanzwirksam": {
"account_number": "7450"
},
"Ertr\u00e4ge durch Verschmelzung und Umwandlung": {
"account_number": "7451"
},
"Ertr\u00e4ge durch den Verkauf von bedeutenden Beteiligungen": {
"account_number": "7452"
},
"Ert\u00e4ge durch den Verkauf von bedeutenden Grundst\u00fccken": {
"account_number": "7453"
},
"Gewinn aus der Ver\u00e4u\u00dferung oder der Aufgabe von Gesch\u00e4ftsaktivit\u00e4ten nach Steuern": {
"account_number": "7454"
}
"Au\u00dferordentliche Ertr\u00e4ge nicht finanzwirksam": {
"account_number": "7450"
},
"Au\u00dferordentliche Ertr\u00e4ge aus der Anwendung von \u00dcbergangsvorschriften (Gruppe)": {
"is_group": 1,
"Au\u00dferordentliche Ertr\u00e4ge aus der Anwendung von \u00dcbergangsvorschriften": {
"account_number": "7460"
},
"Au\u00dferordentliche Ertr\u00e4ge: Zuschreibung f. Sachanlageverm\u00f6gen": {
"account_number": "7461"
},
"Au\u00dferordentliche Ertr\u00e4ge: Zuschreibung f. Finanzanlageverm\u00f6gen": {
"account_number": "7462"
},
"Au\u00dferordentliche Ertr\u00e4ge: Wertpapiere im Umlaufverm\u00f6gen": {
"account_number": "7463"
},
"Au\u00dferordentliche Ertr\u00e4ge: latente Steuern": {
"account_number": "7464"
}
"Ertr\u00e4ge durch Verschmelzung und Umwandlung": {
"account_number": "7451"
},
"Ertr\u00e4ge durch den Verkauf von bedeutenden Beteiligungen": {
"account_number": "7452"
},
"Ert\u00e4ge durch den Verkauf von bedeutenden Grundst\u00fccken": {
"account_number": "7453"
},
"Gewinn aus der Ver\u00e4u\u00dferung oder der Aufgabe von Gesch\u00e4ftsaktivit\u00e4ten nach Steuern": {
"account_number": "7454"
},
"Au\u00dferordentliche Ertr\u00e4ge aus der Anwendung von \u00dcbergangsvorschriften": {
"account_number": "7460"
},
"Au\u00dferordentliche Ertr\u00e4ge: Zuschreibung f. Sachanlageverm\u00f6gen": {
"account_number": "7461"
},
"Au\u00dferordentliche Ertr\u00e4ge: Zuschreibung f. Finanzanlageverm\u00f6gen": {
"account_number": "7462"
},
"Au\u00dferordentliche Ertr\u00e4ge: Wertpapiere im Umlaufverm\u00f6gen": {
"account_number": "7463"
},
"Au\u00dferordentliche Ertr\u00e4ge: latente Steuern": {
"account_number": "7464"
}
}
},
"7 - sonstige betriebliche Aufwendungen": {
"root_type": "Expense",
"is_group": 1,
"Erl\u00f6sschm\u00e4lerungen (Gruppe)": {
"is_group": 1,
"Erl\u00f6sschm\u00e4lerungen (Gruppe)": {
"is_group": 1,
"Erl\u00f6sschm\u00e4lerungen": {
"account_number": "4700"
@ -2692,40 +2703,43 @@
},
"Erl\u00f6sschm\u00e4lerungen aus im Inland steuerpfl. EU-Lieferungen 16 % USt": {
"account_number": "4729"
}
},
"Gew\u00e4hrte Skonti (Gruppe)": {
"is_group": 1,
"Gew. Skonti": {
"account_number": "4730"
},
"Gew\u00e4hrte Skonti (Gruppe)": {
"is_group": 1,
"Gew. Skonti": {
"account_number": "4730"
},
"Gew. Skonti 7 % USt": {
"account_number": "4731"
},
"Gew. Skonti 19 % USt": {
"account_number": "4736"
},
"Gew. Skonti aus Lieferungen von Mobilfunkger./Schaltkr., f. die der Leistungsempf. die Ust. schuldet": {
"account_number": "4738"
},
"Gew. Skonti aus Leistungen, f. die der Leistungsempf. die Umsatzsteuer nach \u00a7 13b UStG schuldet": {
"account_number": "4741"
},
"Gew. Skonti aus Erl\u00f6sen aus im anderen EU-Land steuerpfl. Leistungen, f. die der Leistungsempf. die Ust. schuldet": {
"account_number": "4742"
},
"Gew. Skonti aus steuerfreien innergem. Lieferungen \u00a7 4 Nr. 1b UStG": {
"account_number": "4743"
},
"Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen": {
"account_number": "4745"
},
"Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen 7% USt": {
"account_number": "4746"
},
"Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen 19% USt": {
"account_number": "4748"
}
"Gew. Skonti 7 % USt": {
"account_number": "4731"
},
"Gew. Skonti 19 % USt": {
"account_number": "4736"
},
"Gew. Skonti aus Lieferungen von Mobilfunkger./Schaltkr., f. die der Leistungsempf. die Ust. schuldet": {
"account_number": "4738"
},
"Gew. Skonti aus Leistungen, f. die der Leistungsempf. die Umsatzsteuer nach \u00a7 13b UStG schuldet": {
"account_number": "4741"
},
"Gew. Skonti aus Erl\u00f6sen aus im anderen EU-Land steuerpfl. Leistungen, f. die der Leistungsempf. die Ust. schuldet": {
"account_number": "4742"
},
"Gew. Skonti aus steuerfreien innergem. Lieferungen \u00a7 4 Nr. 1b UStG": {
"account_number": "4743"
},
"Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen": {
"account_number": "4745"
},
"Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen 7% USt": {
"account_number": "4746"
},
"Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen 19% USt": {
"account_number": "4748"
}
},
"Gew\u00e4hrte Boni (Gruppe)": {
"is_group": 1,
"Gew\u00e4hrte Boni 7 % USt": {
"account_number": "4750"
},
@ -2744,7 +2758,7 @@
"Gew\u00e4hrte Rabatte 19 % USt": {
"account_number": "4790"
}
},
},
"Sonstige betriebliche Aufwendungen": {
"account_number": "6300"
},
@ -2838,103 +2852,79 @@
"account_number": "6398"
}
},
"Versicherungen (Gruppe)": {
"is_group": 1,
"Versicherungen": {
"account_number": "6400"
},
"Versicherungen f. Geb\u00e4ude, die zum Betriebsverm\u00f6gen geh\u00f6ren": {
"account_number": "6405"
},
"Netto-Pr\u00e4mie f. R\u00fcckdeckung k\u00fcnftiger Versorgungsleistungen": {
"account_number": "6410"
},
"Beitr\u00e4ge": {
"account_number": "6420"
},
"Sonstige Abgaben": {
"account_number": "6430"
},
"Steuerlich abzugsf\u00e4hige Versp\u00e4tungszuschl\u00e4ge und Zwangsgelder": {
"account_number": "6436"
},
"Steuerlich nicht abzugsf\u00e4hige Versp\u00e4tungszuschl\u00e4ge und Zwangsgelder": {
"account_number": "6437"
},
"Ausgleichsabgabe i. S. d. Schwerbehindertengesetzes": {
"account_number": "6440"
},
"Reparaturen und Instandhaltung von Bauten": {
"account_number": "6450"
},
"Reparaturen und Instandhaltung von technischenAnlagen und Maschinen": {
"account_number": "6460"
},
"Reparaturen und Instandhaltung von anderen Anlagen und Betriebs- und Gesch\u00e4ftsausstattung": {
"account_number": "6470"
},
"Zuf\u00fchrung zu Aufwandsr\u00fcckstellungen": {
"account_number": "6475"
},
"Reparaturen und Instandhaltung von anderen Anlagen": {
"account_number": "6485"
},
"Sonstige Reparaturen und Instandhaltungen": {
"account_number": "6490"
},
"Wartungskosten f. Hard- und Software": {
"account_number": "6495"
},
"Mietleasing (bewegliche Wirtschaftsg\u00fcter)": {
"account_number": "6498"
}
"Versicherungen": {
"account_number": "6400"
},
"Versicherungen f. Geb\u00e4ude, die zum Betriebsverm\u00f6gen geh\u00f6ren": {
"account_number": "6405"
},
"Netto-Pr\u00e4mie f. R\u00fcckdeckung k\u00fcnftiger Versorgungsleistungen": {
"account_number": "6410"
},
"Beitr\u00e4ge": {
"account_number": "6420"
},
"Sonstige Abgaben": {
"account_number": "6430"
},
"Steuerlich abzugsf\u00e4hige Versp\u00e4tungszuschl\u00e4ge und Zwangsgelder": {
"account_number": "6436"
},
"Steuerlich nicht abzugsf\u00e4hige Versp\u00e4tungszuschl\u00e4ge und Zwangsgelder": {
"account_number": "6437"
},
"Ausgleichsabgabe i. S. d. Schwerbehindertengesetzes": {
"account_number": "6440"
},
"Reparaturen und Instandhaltung von Bauten": {
"account_number": "6450"
},
"Reparaturen und Instandhaltung von technischenAnlagen und Maschinen": {
"account_number": "6460"
},
"Reparaturen und Instandhaltung von anderen Anlagen und Betriebs- und Gesch\u00e4ftsausstattung": {
"account_number": "6470"
},
"Zuf\u00fchrung zu Aufwandsr\u00fcckstellungen": {
"account_number": "6475"
},
"Reparaturen und Instandhaltung von anderen Anlagen": {
"account_number": "6485"
},
"Sonstige Reparaturen und Instandhaltungen": {
"account_number": "6490"
},
"Wartungskosten f. Hard- und Software": {
"account_number": "6495"
},
"Mietleasing (bewegliche Wirtschaftsg\u00fcter)": {
"account_number": "6498"
},
"Fahrzeugkosten (Gruppe)": {
"is_group": 1,
"Fahrzeugkosten": {
"account_number": "6500"
},
"Kfz-Versicherungen (Gruppe)": {
"is_group": 1,
"Kfz-Versicherungen": {
"account_number": "6520"
}
"Kfz-Versicherungen": {
"account_number": "6520"
},
"Laufende Kfz-Betriebskosten (Gruppe)": {
"is_group": 1,
"Laufende Kfz-Betriebskosten": {
"account_number": "6530"
}
"Laufende Kfz-Betriebskosten": {
"account_number": "6530"
},
"Kfz-Reparaturen (Gruppe)": {
"is_group": 1,
"Kfz-Reparaturen": {
"account_number": "6540"
}
"Kfz-Reparaturen": {
"account_number": "6540"
},
"Garagenmiete (Gruppe)": {
"is_group": 1,
"Garagenmiete": {
"account_number": "6550"
}
"Garagenmiete": {
"account_number": "6550"
},
"Mietleasing Kfz (Gruppe)": {
"is_group": 1,
"Mietleasing Kfz": {
"account_number": "6560"
}
"Mietleasing Kfz": {
"account_number": "6560"
},
"Sonstige Kfz-Kosten (Gruppe)": {
"is_group": 1,
"Sonstige Kfz-Kosten": {
"account_number": "6570"
}
"Sonstige Kfz-Kosten": {
"account_number": "6570"
},
"Mautgeb\u00fchren (Gruppe)": {
"is_group": 1,
"Mautgeb\u00fchren": {
"account_number": "6580"
}
"Mautgeb\u00fchren": {
"account_number": "6580"
},
"Kfz-Kosten f. betrieblich genutzte zum Privatverm\u00f6gen geh\u00f6rende Kraftfahrzeuge": {
"account_number": "6590"
@ -2996,20 +2986,23 @@
"Nicht abzugsf\u00e4hige Betriebsausgaben aus Werbe- und Repr\u00e4sentationskosten": {
"account_number": "6645"
},
"Reisekosten Arbeitnehmer": {
"account_number": "6650"
},
"Reisekosten Arbeitnehmer \u00dcbernachtungsaufwand": {
"account_number": "6660"
},
"Reisekosten Arbeitnehmer Fahrtkosten": {
"account_number": "6663"
},
"Reisekosten Arbeitnehmer Verpflegungsmehraufwand": {
"account_number": "6664"
},
"Kilometergelderstattung Arbeitnehmer": {
"account_number": "6668"
"Reisekosten Arbeitnehmer (Gruppe)": {
"is_group": 1,
"Reisekosten Arbeitnehmer": {
"account_number": "6650"
},
"Reisekosten Arbeitnehmer \u00dcbernachtungsaufwand": {
"account_number": "6660"
},
"Reisekosten Arbeitnehmer Fahrtkosten": {
"account_number": "6663"
},
"Reisekosten Arbeitnehmer Verpflegungsmehraufwand": {
"account_number": "6664"
},
"Kilometergelderstattung Arbeitnehmer": {
"account_number": "6668"
}
},
"Reisekosten Unternehmer (Gruppe)": {
"is_group": 1,

View File

@ -48,12 +48,6 @@ frappe.ui.form.on('Accounting Dimension', {
frm.set_value('label', frm.doc.document_type);
frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type));
if (frm.is_new()){
let row = frappe.model.add_child(frm.doc, "Accounting Dimension Detail", "dimension_defaults");
row.reference_document = frm.doc.document_type;
frm.refresh_fields("dimension_defaults");
}
frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => {
if (r && r.document_type) {
frm.set_df_property('document_type', 'description', "Document type is already set as dimension");

View File

@ -1,4 +1,5 @@
{
"actions": [],
"autoname": "field:label",
"creation": "2019-05-04 18:13:37.002352",
"doctype": "DocType",
@ -46,7 +47,8 @@
"options": "Accounting Dimension Detail"
}
],
"modified": "2019-07-17 16:49:31.134385",
"links": [],
"modified": "2020-03-22 20:34:39.805728",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting Dimension",
@ -63,9 +65,20 @@
"role": "System Manager",
"share": 1,
"write": 1
},
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "ASC",
"track_changes": 1

View File

@ -172,7 +172,7 @@ def get_doctypes_with_dimensions():
return doclist
def get_accounting_dimensions(as_list=True):
accounting_dimensions = frappe.get_all("Accounting Dimension", fields=["label", "fieldname", "disabled"])
accounting_dimensions = frappe.get_all("Accounting Dimension", fields=["label", "fieldname", "disabled", "document_type"])
if as_list:
return [d.fieldname for d in accounting_dimensions]
@ -186,6 +186,18 @@ def get_checks_for_pl_and_bs_accounts():
return dimensions
def get_dimension_with_children(doctype, dimension):
if isinstance(dimension, list):
dimension = dimension[0]
all_dimensions = []
lft, rgt = frappe.db.get_value(doctype, dimension, ["lft", "rgt"])
children = frappe.get_all(doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]})
all_dimensions += [c.name for c in children]
return all_dimensions
@frappe.whitelist()
def get_dimension_filters():
dimension_filters = frappe.db.sql("""

View File

@ -0,0 +1,8 @@
frappe.ui.form.on('Accounts Settings', {
refresh: function(frm) {
frm.set_df_property("acc_frozen_upto", "label", "Books Closed Through");
frm.set_df_property("frozen_accounts_modifier", "label", "Role Allowed to Close Books & Make Changes to Closed Periods");
frm.set_df_property("credit_controller", "label", "Credit Manager");
}
});

View File

@ -7,7 +7,20 @@ frappe.ui.form.on('Bank', {
},
refresh: function(frm) {
add_fields_to_mapping_table(frm);
}
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank' };
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
if (frm.doc.__islocal) {
frm.set_df_property('address_and_contact', 'hidden', 1);
frappe.contacts.clear_address_and_contact(frm);
}
else {
frm.set_df_property('address_and_contact', 'hidden', 0);
frappe.contacts.render_address_and_contact(frm);
}
},
});

View File

@ -1,224 +1,137 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:bank_name",
"beta": 0,
"creation": "2018-04-07 16:59:59.496668",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:bank_name",
"creation": "2018-04-07 16:59:59.496668",
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"bank_details_section",
"bank_name",
"swift_number",
"column_break_1",
"branch_code",
"website",
"address_and_contact",
"address_html",
"column_break_13",
"contact_html",
"data_import_configuration_section",
"bank_transaction_mapping",
"section_break_4",
"plaid_access_token"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "bank_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Bank Name",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"fieldname": "bank_name",
"fieldtype": "Data",
"label": "Bank Name",
"reqd": 1,
"unique": 1
},
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"columns": 0,
"fieldname": "data_import_configuration_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Data Import Configuration",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "bank_details_section",
"fieldtype": "Section Break",
"label": "Bank Details"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "bank_transaction_mapping",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Bank Transaction Mapping",
"length": 0,
"no_copy": 0,
"options": "Bank Transaction Mapping",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"allow_in_quick_entry": 1,
"fieldname": "swift_number",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "SWIFT number",
"unique": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_4",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "column_break_1",
"fieldtype": "Column Break",
"search_index": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "plaid_access_token",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Plaid Access Token",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"allow_in_quick_entry": 1,
"fieldname": "branch_code",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Branch Code",
"unique": 1
},
{
"fieldname": "address_and_contact",
"fieldtype": "Section Break",
"label": "Address and Contact",
"options": "fa fa-map-marker"
},
{
"fieldname": "address_html",
"fieldtype": "HTML",
"label": "Address HTML"
},
{
"fieldname": "website",
"fieldtype": "Data",
"label": "Website"
},
{
"fieldname": "column_break_13",
"fieldtype": "Column Break"
},
{
"fieldname": "contact_html",
"fieldtype": "HTML",
"label": "Contact HTML"
},
{
"collapsible": 1,
"fieldname": "data_import_configuration_section",
"fieldtype": "Section Break",
"label": "Data Import Configuration"
},
{
"fieldname": "bank_transaction_mapping",
"fieldtype": "Table",
"label": "Bank Transaction Mapping",
"options": "Bank Transaction Mapping"
},
{
"fieldname": "section_break_4",
"fieldtype": "Section Break"
},
{
"fieldname": "plaid_access_token",
"fieldtype": "Data",
"hidden": 1,
"label": "Plaid Access Token",
"no_copy": 1,
"read_only": 1
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-11-27 16:12:13.938776",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank",
"name_case": "",
"owner": "Administrator",
],
"links": [],
"modified": "2020-03-25 21:22:33.496264",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -5,6 +5,12 @@
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address
class Bank(Document):
pass
def onload(self):
"""Load address and contacts in `__onload`"""
load_address_and_contact(self)
def on_trash(self):
delete_contact_and_address('Bank', self.name)

View File

@ -24,8 +24,6 @@
"iban",
"column_break_12",
"bank_account_no",
"branch_code",
"swift_number",
"address_and_contact",
"address_html",
"website",
@ -145,17 +143,6 @@
"label": "Bank Account No",
"length": 30
},
{
"fieldname": "branch_code",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Branch Code"
},
{
"fieldname": "swift_number",
"fieldtype": "Data",
"label": "SWIFT number"
},
{
"fieldname": "address_and_contact",
"fieldtype": "Section Break",
@ -213,7 +200,7 @@
}
],
"links": [],
"modified": "2020-01-29 20:42:26.458316",
"modified": "2020-01-30 20:42:26.458316",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account",

View File

@ -4,8 +4,8 @@
cur_frm.add_fetch('bank_account','account','account');
cur_frm.add_fetch('bank_account','bank_account_no','bank_account_no');
cur_frm.add_fetch('bank_account','iban','iban');
cur_frm.add_fetch('bank_account','branch_code','branch_code');
cur_frm.add_fetch('bank_account','swift_number','swift_number');
cur_frm.add_fetch('bank','branch_code','branch_code');
cur_frm.add_fetch('bank','swift_number','swift_number');
frappe.ui.form.on('Bank Guarantee', {
setup: function(frm) {

View File

@ -6,6 +6,7 @@ from __future__ import unicode_literals
import frappe, json
from frappe.model.document import Document
from frappe import _
from frappe.desk.search import sanitize_searchfield
class BankGuarantee(Document):
def validate(self):
@ -22,5 +23,8 @@ class BankGuarantee(Document):
@frappe.whitelist()
def get_vouchar_detials(column_list, doctype, docname):
column_list = json.loads(column_list)
for col in column_list:
sanitize_searchfield(col)
return frappe.db.sql(''' select {columns} from `tab{doctype}` where name=%s'''
.format(columns=", ".join(json.loads(column_list)), doctype=doctype), docname, as_dict=1)[0]

View File

@ -32,10 +32,12 @@ frappe.ui.form.on('C-Form Invoice Detail', {
invoice_no(frm, cdt, cdn) {
let d = frappe.get_doc(cdt, cdn);
frm.call('get_invoice_details', {
invoice_no: d.invoice_no
}).then(r => {
frappe.model.set_value(cdt, cdn, r.message);
});
if (d.invoice_no) {
frm.call('get_invoice_details', {
invoice_no: d.invoice_no
}).then(r => {
frappe.model.set_value(cdt, cdn, r.message);
});
}
}
});

View File

@ -124,11 +124,13 @@
],
"icon": "fa fa-money",
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2020-01-28 13:50:23.430434",
"modified": "2020-03-18 17:59:04.321637",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cost Center",
"nsm_parent_field": "parent_cost_center",
"owner": "Administrator",
"permissions": [
{

View File

@ -30,18 +30,10 @@ frappe.ui.form.on('Exchange Rate Revaluation', {
frm.doc.accounts.forEach(d=> {
total_amt = total_amt + d['new_balance_in_base_currency'];
});
if(total_amt === r.sum) {
frm.add_custom_button(__("Journal Entry"), function(){
frappe.route_options = {
'reference_type': 'Exchange Rate Revaluation',
'reference_name': frm.doc.name
};
frappe.set_route("List", "Journal Entry");
}, __("View"));
} else {
frm.add_custom_button(__('Create Journal Entry'), function() {
if(total_amt !== r.sum) {
frm.add_custom_button(__('Journal Entry'), function() {
return frm.events.make_jv(frm);
});
}, __('Create'));
}
}, 'Journal Entry');
}

View File

@ -0,0 +1,11 @@
from __future__ import unicode_literals
def get_data():
return {
'fieldname': 'reference_name',
'transactions': [
{
'items': ['Journal Entry']
}
]
}

View File

@ -114,13 +114,13 @@
"fieldname": "debit_in_account_currency",
"fieldtype": "Currency",
"label": "Debit Amount in Account Currency",
"options": "currency"
"options": "account_currency"
},
{
"fieldname": "credit_in_account_currency",
"fieldtype": "Currency",
"label": "Credit Amount in Account Currency",
"options": "currency"
"options": "account_currency"
},
{
"fieldname": "against",
@ -250,7 +250,7 @@
"icon": "fa fa-list",
"idx": 1,
"in_create": 1,
"modified": "2020-02-10 04:54:57.777905",
"modified": "2020-03-28 16:22:33.766994",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",

View File

@ -233,35 +233,14 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
frappe.throw(_("Outstanding for {0} cannot be less than zero ({1})").format(against_voucher, fmt_money(bal)))
if against_voucher_type in ["Sales Invoice", "Purchase Invoice", "Fees"]:
update_outstanding_amt_in_ref(against_voucher, against_voucher_type, bal)
def update_outstanding_amt_in_ref(against_voucher, against_voucher_type, bal):
data = []
# Update outstanding amt on against voucher
if against_voucher_type == "Fees":
ref_doc = frappe.get_doc(against_voucher_type, against_voucher)
ref_doc.db_set('outstanding_amount', bal)
ref_doc.set_status(update=True)
return
elif against_voucher_type == "Purchase Invoice":
from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import get_status
data = frappe.db.get_value(against_voucher_type, against_voucher,
["name as purchase_invoice", "outstanding_amount",
"is_return", "due_date", "docstatus"])
elif against_voucher_type == "Sales Invoice":
from erpnext.accounts.doctype.sales_invoice.sales_invoice import get_status
data = frappe.db.get_value(against_voucher_type, against_voucher,
["name as sales_invoice", "outstanding_amount", "is_discounted",
"is_return", "due_date", "docstatus"])
precision = frappe.get_precision(against_voucher_type, "outstanding_amount")
data = list(data)
data.append(precision)
status = get_status(data)
frappe.db.set_value(against_voucher_type, against_voucher, {
'outstanding_amount': bal,
'status': status
})
# Didn't use db_set for optimisation purpose
ref_doc.outstanding_amount = bal
frappe.db.set_value(against_voucher_type, against_voucher, 'outstanding_amount', bal)
ref_doc.set_status(update=True)
def validate_frozen_account(account, adv_adj=None):
frozen_account = frappe.db.get_value("Account", account, "freeze_account")

View File

@ -38,6 +38,7 @@ class TestGLEntry(unittest.TestCase):
filters={"voucher_type": "Journal Entry", "voucher_no": je.name},
order_by="creation"
)
self.assertTrue(all(entry.to_rename == 1 for entry in gl_entries))
old_naming_series_current_value = frappe.db.sql("SELECT current from tabSeries where name = %s", naming_series)[0][0]

View File

@ -454,8 +454,10 @@ class JournalEntry(AccountsController):
def set_print_format_fields(self):
bank_amount = party_amount = total_amount = 0.0
currency = bank_account_currency = party_account_currency = pay_to_recd_from= None
party_type = None
for d in self.get('accounts'):
if d.party_type in ['Customer', 'Supplier'] and d.party:
party_type = d.party_type
if not pay_to_recd_from:
pay_to_recd_from = d.party
@ -467,9 +469,9 @@ class JournalEntry(AccountsController):
bank_amount += (d.debit_in_account_currency or d.credit_in_account_currency)
bank_account_currency = d.account_currency
if pay_to_recd_from:
self.pay_to_recd_from = frappe.db.get_value(d.party_type, pay_to_recd_from,
"customer_name" if d.party_type=="Customer" else "supplier_name")
if party_type and pay_to_recd_from:
self.pay_to_recd_from = frappe.db.get_value(party_type, pay_to_recd_from,
"customer_name" if party_type=="Customer" else "supplier_name")
if bank_amount:
total_amount = bank_amount
currency = bank_account_currency

View File

@ -33,7 +33,9 @@ frappe.ui.form.on('Payment Entry', {
frm.set_query("party_bank_account", function() {
return {
filters: {
"is_company_account":0
"is_company_account":0,
party_type: frm.doc.party_type,
party: frm.doc.party
}
}
});

View File

@ -161,15 +161,15 @@ class TestPaymentEntry(unittest.TestCase):
pe.insert()
pe.submit()
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
self.assertEqual(outstanding_amount, 0)
self.assertEqual(si.status, 'Paid')
outstanding_amount, status = frappe.db.get_value("Sales Invoice", si.name, ["outstanding_amount", "status"])
self.assertEqual(flt(outstanding_amount), 0)
self.assertEqual(status, 'Paid')
pe.cancel()
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
self.assertEqual(outstanding_amount, 100)
self.assertEqual(si.status, 'Unpaid')
outstanding_amount, status = frappe.db.get_value("Sales Invoice", si.name, ["outstanding_amount", "status"])
self.assertEqual(flt(outstanding_amount), 100)
self.assertEqual(status, 'Unpaid')
def test_payment_against_purchase_invoice_to_check_status(self):
pi = make_purchase_invoice(supplier="_Test Supplier USD", debit_to="_Test Payable USD - _TC",
@ -182,15 +182,15 @@ class TestPaymentEntry(unittest.TestCase):
pe.insert()
pe.submit()
outstanding_amount = flt(frappe.db.get_value("Purchase Invoice", pi.name, "outstanding_amount"))
self.assertEqual(outstanding_amount, 0)
self.assertEqual(pi.status, 'Paid')
outstanding_amount, status = frappe.db.get_value("Purchase Invoice", pi.name, ["outstanding_amount", "status"])
self.assertEqual(flt(outstanding_amount), 0)
self.assertEqual(status, 'Paid')
pe.cancel()
outstanding_amount = flt(frappe.db.get_value("Purchase Invoice", pi.name, "outstanding_amount"))
self.assertEqual(outstanding_amount, 100)
self.assertEqual(pi.status, 'Unpaid')
outstanding_amount, status = frappe.db.get_value("Purchase Invoice", pi.name, ["outstanding_amount", "status"])
self.assertEqual(flt(outstanding_amount), 250)
self.assertEqual(status, 'Unpaid')
def test_payment_entry_against_ec(self):

View File

@ -839,7 +839,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "bank_account.branch_code",
"fetch_from": "bank.branch_code",
"fieldname": "branch_code",
"fieldtype": "Read Only",
"hidden": 0,
@ -873,7 +873,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "bank_account.swift_number",
"fetch_from": "bank.swift_number",
"fieldname": "swift_number",
"fieldtype": "Read Only",
"hidden": 0,

View File

@ -317,13 +317,13 @@ def make_payment_request(**args):
"payment_request_type": args.get("payment_request_type"),
"currency": ref_doc.currency,
"grand_total": grand_total,
"email_to": args.recipient_id or "",
"email_to": args.recipient_id or ref_doc.owner,
"subject": _("Payment Request for {0}").format(args.dn),
"message": gateway_account.get("message") or get_dummy_message(ref_doc),
"reference_doctype": args.dt,
"reference_name": args.dn,
"party_type": args.get("party_type"),
"party": args.get("party"),
"party_type": args.get("party_type") or "Customer",
"party": args.get("party") or ref_doc.customer,
"bank_account": bank_account
})

View File

@ -125,27 +125,6 @@ class PurchaseInvoice(BuyingController):
else:
self.remarks = _("No Remarks")
def set_status(self, update=False, status=None, update_modified=True):
if self.is_new():
if self.get('amended_from'):
self.status = 'Draft'
return
if not status:
precision = self.precision("outstanding_amount")
args = [
self.name,
self.outstanding_amount,
self.is_return,
self.due_date,
self.docstatus,
precision
]
self.status = get_status(args)
if update:
self.db_set('status', self.status, update_modified = update_modified)
def set_missing_values(self, for_validate=False):
if not self.credit_to:
self.credit_to = get_party_account("Supplier", self.supplier, self.company)
@ -167,10 +146,14 @@ class PurchaseInvoice(BuyingController):
["account_type", "report_type", "account_currency"], as_dict=True)
if account.report_type != "Balance Sheet":
frappe.throw(_("Credit To account must be a Balance Sheet account"))
frappe.throw(_("Please ensure {} account is a Balance Sheet account. \
You can change the parent account to a Balance Sheet account or select a different account.")
.format(frappe.bold("Credit To")), title=_("Invalid Account"))
if self.supplier and account.account_type != "Payable":
frappe.throw(_("Credit To account must be a Payable account"))
frappe.throw(_("Please ensure {} account is a Payable account. \
Change the account type to Payable or select a different account.")
.format(frappe.bold("Credit To")), title=_("Invalid Account"))
self.party_account_currency = account.account_currency
@ -1028,34 +1011,6 @@ class PurchaseInvoice(BuyingController):
# calculate totals again after applying TDS
self.calculate_taxes_and_totals()
def get_status(*args):
purchase_invoice, outstanding_amount, is_return, due_date, docstatus, precision = args[0]
outstanding_amount = flt(outstanding_amount, precision)
due_date = getdate(due_date)
now_date = getdate()
if docstatus == 2:
status = "Cancelled"
elif docstatus == 1:
if outstanding_amount > 0 and due_date < now_date:
status = "Overdue"
elif outstanding_amount > 0 and due_date >= now_date:
status = "Unpaid"
#Check if outstanding amount is 0 due to debit note issued against invoice
elif outstanding_amount <= 0 and is_return == 0 and frappe.db.get_value('Purchase Invoice', {'is_return': 1, 'return_against': purchase_invoice, 'docstatus': 1}):
status = "Debit Note Issued"
elif is_return == 1:
status = "Return"
elif outstanding_amount <=0:
status = "Paid"
else:
status = "Submitted"
else:
status = "Draft"
return status
def get_list_context(context=None):
from erpnext.controllers.website_list_for_contact import get_list_context
list_context = get_list_context(context)
@ -1116,3 +1071,6 @@ def block_invoice(name, release_date, hold_comment=None):
def make_inter_company_sales_invoice(source_name, target_doc=None):
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_company_transaction
return make_inter_company_transaction("Purchase Invoice", source_name, target_doc)
def on_doctype_update():
frappe.db.add_index("Purchase Invoice", ["supplier", "is_return", "return_against"])

View File

@ -761,7 +761,7 @@
"depends_on": "is_fixed_asset",
"fetch_from": "item_code.asset_category",
"fieldname": "asset_category",
"fieldtype": "Data",
"fieldtype": "Link",
"label": "Asset Category",
"options": "Asset Category",
"read_only": 1
@ -777,7 +777,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2020-03-05 14:20:17.297284",
"modified": "2020-04-01 14:20:17.297284",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@ -423,7 +423,10 @@ def make_invoice(pos_profile, doc_list={}, email_queue_list={}, customers_list={
name_list.append(name)
email_queue = make_email_queue(email_queue_list)
pos_profile = json.loads(pos_profile)
if isinstance(pos_profile, string_types):
pos_profile = json.loads(pos_profile)
customers = get_customers_list(pos_profile)
return {
'invoice': name_list,

View File

@ -437,13 +437,17 @@ class SalesInvoice(SellingController):
if (not for_validate) or (for_validate and not self.get(fieldname)):
self.set(fieldname, pos.get(fieldname))
customer_price_list = frappe.get_value("Customer", self.customer, 'default_price_list')
if pos.get("company_address"):
self.company_address = pos.get("company_address")
if not customer_price_list:
self.set('selling_price_list', pos.get('selling_price_list'))
customer_price_list, customer_group = frappe.get_value("Customer", self.customer, ['default_price_list', 'customer_group'])
customer_group_price_list = frappe.get_value("Customer Group", customer_group, 'default_price_list')
selling_price_list = customer_price_list or customer_group_price_list or pos.get('selling_price_list')
if selling_price_list:
self.set('selling_price_list', selling_price_list)
if not for_validate:
self.update_stock = cint(pos.get("update_stock"))
@ -474,13 +478,17 @@ class SalesInvoice(SellingController):
["account_type", "report_type", "account_currency"], as_dict=True)
if not account:
frappe.throw(_("Debit To is required"))
frappe.throw(_("Debit To is required"), title=_("Account Missing"))
if account.report_type != "Balance Sheet":
frappe.throw(_("Debit To account must be a Balance Sheet account"))
frappe.throw(_("Please ensure {} account is a Balance Sheet account. \
You can change the parent account to a Balance Sheet account or select a different account.")
.format(frappe.bold("Debit To")), title=_("Invalid Account"))
if self.customer and account.account_type != "Receivable":
frappe.throw(_("Debit To account must be a Receivable account"))
frappe.throw(_("Please ensure {} account is a Receivable account. \
Change the account type to Receivable or select a different account.")
.format(frappe.bold("Debit To")), title=_("Invalid Account"))
self.party_account_currency = account.account_currency
@ -1223,18 +1231,38 @@ class SalesInvoice(SellingController):
self.status = 'Draft'
return
precision = self.precision("outstanding_amount")
outstanding_amount = flt(self.outstanding_amount, precision)
due_date = getdate(self.due_date)
nowdate = getdate()
discounting_status = None
if self.is_discounted:
discountng_status = get_discounting_status(self.name)
if not status:
precision = self.precision("outstanding_amount")
args = [
self.name,
self.outstanding_amount,
self.is_discounted,
self.is_return,
self.due_date,
self.docstatus,
precision,
]
self.status = get_status(args)
if self.docstatus == 2:
status = "Cancelled"
elif self.docstatus == 1:
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 due_date < nowdate:
self.status = "Overdue"
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 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:
self.status = "Paid"
else:
self.status = "Submitted"
else:
self.status = "Draft"
if update:
self.db_set('status', self.status, update_modified = update_modified)
@ -1259,42 +1287,6 @@ def get_discounting_status(sales_invoice):
return status
def get_status(*args):
sales_invoice, outstanding_amount, is_discounted, is_return, due_date, docstatus, precision = args[0]
discounting_status = None
if is_discounted:
discounting_status = get_discounting_status(sales_invoice)
outstanding_amount = flt(outstanding_amount, precision)
due_date = getdate(due_date)
now_date = getdate()
if docstatus == 2:
status = "Cancelled"
elif docstatus == 1:
if outstanding_amount > 0 and due_date < now_date and is_discounted and discounting_status=='Disbursed':
status = "Overdue and Discounted"
elif outstanding_amount > 0 and due_date < now_date:
status = "Overdue"
elif outstanding_amount > 0 and due_date >= now_date and is_discounted and discounting_status=='Disbursed':
status = "Unpaid and Discounted"
elif outstanding_amount > 0 and due_date >= now_date:
status = "Unpaid"
#Check if outstanding amount is 0 due to credit note issued against invoice
elif outstanding_amount <= 0 and is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': sales_invoice, 'docstatus': 1}):
status = "Credit Note Issued"
elif is_return == 1:
status = "Return"
elif outstanding_amount <=0:
status = "Paid"
else:
status = "Submitted"
else:
status = "Draft"
return status
def validate_inter_company_party(doctype, party, company, inter_company_reference):
if not party:
return

View File

@ -786,7 +786,7 @@ class TestSalesInvoice(unittest.TestCase):
def test_make_pos_invoice(self):
from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
make_pos_profile()
pos_profile = make_pos_profile()
pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
@ -802,7 +802,7 @@ class TestSalesInvoice(unittest.TestCase):
pos.append("taxes", tax)
invoice_data = [{'09052016142': pos}]
si = make_invoice(invoice_data).get('invoice')
si = make_invoice(pos_profile, invoice_data).get('invoice')
self.assertEqual(si[0], '09052016142')
sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': '09052016142', 'docstatus': 1})
@ -820,7 +820,7 @@ class TestSalesInvoice(unittest.TestCase):
if allow_negative_stock:
frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 0)
make_pos_profile()
pos_profile = make_pos_profile()
timestamp = cint(time.time())
item = make_item("_Test POS Item")
@ -834,7 +834,7 @@ class TestSalesInvoice(unittest.TestCase):
{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 330}]
invoice_data = [{timestamp: pos}]
si = make_invoice(invoice_data).get('invoice')
si = make_invoice(pos_profile, invoice_data).get('invoice')
self.assertEqual(si[0], timestamp)
sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp})
@ -843,7 +843,7 @@ class TestSalesInvoice(unittest.TestCase):
timestamp = cint(time.time())
pos["offline_pos_name"] = timestamp
invoice_data = [{timestamp: pos}]
si1 = make_invoice(invoice_data).get('invoice')
si1 = make_invoice(pos_profile, invoice_data).get('invoice')
self.assertEqual(si1[0], timestamp)
sales_invoice1 = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp})

View File

@ -136,12 +136,11 @@ def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
def make_entry(args, adv_adj, update_outstanding, from_repost=False):
args.update({"doctype": "GL Entry"})
gle = frappe.get_doc(args)
gle = frappe.new_doc("GL Entry")
gle.update(args)
gle.flags.ignore_permissions = 1
gle.flags.from_repost = from_repost
gle.validate()
gle.flags.ignore_permissions = True
gle.db_insert()
gle.run_method("on_update_with_args", adv_adj, update_outstanding, from_repost)
gle.flags.ignore_validate = True

View File

@ -11,7 +11,7 @@ from frappe.utils import (add_days, getdate, formatdate, date_diff,
add_years, get_timestamp, nowdate, flt, cstr, add_months, get_last_day)
from frappe.contacts.doctype.address.address import (get_address_display,
get_default_address, get_company_address)
from frappe.contacts.doctype.contact.contact import get_contact_details, get_default_contact
from frappe.contacts.doctype.contact.contact import get_contact_details
from erpnext.exceptions import PartyFrozen, PartyDisabled, InvalidAccountCurrency
from erpnext.accounts.utils import get_fiscal_year
from erpnext import get_company_currency
@ -281,8 +281,8 @@ def validate_party_gle_currency(party_type, party, company, party_account_curren
existing_gle_currency = get_party_gle_currency(party_type, party, company)
if existing_gle_currency and party_account_currency != existing_gle_currency:
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
.format(party_type, party, existing_gle_currency), InvalidAccountCurrency)
frappe.throw(_("{0} {1} has accounting entries in currency {2} for company {3}. Please select a receivable or payable account with currency {2}.")
.format(frappe.bold(party_type), frappe.bold(party), frappe.bold(existing_gle_currency), frappe.bold(company)), InvalidAccountCurrency)
def validate_party_accounts(doc):
companies = []
@ -295,15 +295,13 @@ def validate_party_accounts(doc):
companies.append(account.company)
party_account_currency = frappe.db.get_value("Account", account.account, "account_currency", cache=True)
existing_gle_currency = get_party_gle_currency(doc.doctype, doc.name, account.company)
if frappe.db.get_default("Company"):
company_default_currency = frappe.get_cached_value('Company',
frappe.db.get_default("Company"), "default_currency")
else:
company_default_currency = frappe.db.get_value('Company', account.company, "default_currency")
if existing_gle_currency and party_account_currency != existing_gle_currency:
frappe.throw(_("Accounting entries have already been made in currency {0} for company {1}. Please select a receivable or payable account with currency {0}.").format(existing_gle_currency, account.company))
validate_party_gle_currency(doc.doctype, doc.name, account.company, party_account_currency)
if doc.get("default_currency") and party_account_currency and company_default_currency:
if doc.default_currency != party_account_currency and doc.default_currency != company_default_currency:
@ -615,3 +613,26 @@ def get_partywise_advanced_payment_amount(party_type, posting_date = None):
if data:
return frappe._dict(data)
def get_default_contact(doctype, name):
"""
Returns default contact for the given doctype and name.
Can be ordered by `contact_type` to either is_primary_contact or is_billing_contact.
"""
out = frappe.db.sql("""
SELECT dl.parent, c.is_primary_contact, c.is_billing_contact
FROM `tabDynamic Link` dl
INNER JOIN tabContact c ON c.name = dl.parent
WHERE
dl.link_doctype=%s AND
dl.link_name=%s AND
dl.parenttype = "Contact"
ORDER BY is_primary_contact DESC, is_billing_contact DESC
""", (doctype, name))
if out:
try:
return out[0][0]
except:
return None
else:
return None

View File

@ -218,15 +218,15 @@
<td></td>
<td style="text-align: right"><b>{%= __("Total") %}</b></td>
<td style="text-align: right">
{%= format_currency(data[i]["invoiced"], data[i]["currency"] ) %}</td>
{%= format_currency(data[i]["invoiced"], data[0]["currency"] ) %}</td>
{% if(!filters.show_future_payments) { %}
<td style="text-align: right">
{%= format_currency(data[i]["paid"], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["credit_note"], data[i]["currency"]) %} </td>
{%= format_currency(data[i]["paid"], data[0]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["credit_note"], data[0]["currency"]) %} </td>
{% } %}
<td style="text-align: right">
{%= format_currency(data[i]["outstanding"], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["outstanding"], data[0]["currency"]) %}</td>
{% if(filters.show_future_payments) { %}
{% if(report.report_name === "Accounts Receivable") { %}
@ -234,8 +234,8 @@
{%= data[i]["po_no"] %}</td>
{% } %}
<td style="text-align: right">{%= data[i]["future_ref"] %}</td>
<td style="text-align: right">{%= format_currency(data[i]["future_amount"], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["remaining_balance"], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["future_amount"], data[0]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["remaining_balance"], data[0]["currency"]) %}</td>
{% } %}
{% } %}
{% } else { %}
@ -256,10 +256,10 @@
{% } else { %}
<td><b>{%= __("Total") %}</b></td>
{% } %}
<td style="text-align: right">{%= format_currency(data[i]["invoiced"], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["paid"], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["credit_note"], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["outstanding"], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["invoiced"], data[0]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["paid"], data[0]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["credit_note"], data[0]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["outstanding"], data[0]["currency"]) %}</td>
{% } %}
{% } %}
</tr>

View File

@ -7,7 +7,7 @@ from frappe import _, scrub
from frappe.utils import getdate, nowdate, flt, cint, formatdate, cstr, now, time_diff_in_seconds
from collections import OrderedDict
from erpnext.accounts.utils import get_currency_precision
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children
# This report gives a summary of all Outstanding Invoices considering the following
@ -603,7 +603,6 @@ class ReceivablePayableReport(object):
self.add_supplier_filters(conditions, values)
self.add_accounting_dimensions_filters(conditions, values)
return " and ".join(conditions), values
def get_order_by_condition(self):
@ -666,13 +665,16 @@ class ReceivablePayableReport(object):
doctype=doctype, lft=lft, rgt=rgt, key=key)
def add_accounting_dimensions_filters(self, conditions, values):
accounting_dimensions = get_accounting_dimensions()
accounting_dimensions = get_accounting_dimensions(as_list=False)
if accounting_dimensions:
for dimension in accounting_dimensions:
if self.filters.get(dimension):
conditions.append("{0} = %s".format(dimension))
values.append(self.filters.get(dimension))
if self.filters.get(dimension.fieldname):
if frappe.get_cached_value('DocType', dimension.document_type, 'is_tree'):
self.filters[dimension.fieldname] = get_dimension_with_children(dimension.document_type,
self.filters.get(dimension.fieldname))
conditions.append("{0} in %s".format(dimension.fieldname))
values.append(tuple(self.filters.get(dimension.fieldname)))
def get_gle_balance(self, gle):
# get the balance of the GL (debit - credit) or reverse balance based on report type

View File

@ -16,7 +16,7 @@ from frappe import _
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
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children
def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_values=False,
company=None, reset_period_on_fy_change=True):
@ -389,7 +389,7 @@ def set_gl_entries_by_account(
def get_additional_conditions(from_date, ignore_closing_entries, filters):
additional_conditions = []
accounting_dimensions = get_accounting_dimensions()
accounting_dimensions = get_accounting_dimensions(as_list=False)
if ignore_closing_entries:
additional_conditions.append("ifnull(voucher_type, '')!='Period Closing Voucher'")
@ -412,11 +412,14 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters):
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):
additional_conditions.append("{0} in (%({0})s)".format(dimension))
if filters.get(dimension.fieldname):
if frappe.get_cached_value('DocType', dimension.document_type, 'is_tree'):
filters[dimension.fieldname] = get_dimension_with_children(dimension.document_type,
filters.get(dimension.fieldname))
additional_conditions.append("{0} in %({0})s".format(dimension.fieldname))
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""

View File

@ -2,7 +2,7 @@
<h4 class="text-center">
{% if (filters.party_name) { %}
{%= filters.party_name %}
{% } else if (filters.party && filters.show_name) { %}
{% } else if (filters.party) { %}
{%= filters.party %}
{% } else if (filters.account) { %}
{%= filters.account %}

View File

@ -10,7 +10,7 @@ from frappe import _, _dict
from erpnext.accounts.utils import get_account_currency
from erpnext.accounts.report.financial_statements import get_cost_centers_with_children
from six import iteritems
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children
from collections import OrderedDict
def execute(filters=None):
@ -131,7 +131,7 @@ def get_gl_entries(filters):
gl_entries = frappe.db.sql(
"""
select
posting_date, account, party_type, party,
name as gl_entry, posting_date, account, party_type, party,
voucher_type, voucher_no, cost_center, project,
against_voucher_type, against_voucher, account_currency,
remarks, against, is_opening {select_fields}
@ -194,12 +194,15 @@ def get_conditions(filters):
if match_conditions:
conditions.append(match_conditions)
accounting_dimensions = get_accounting_dimensions()
accounting_dimensions = get_accounting_dimensions(as_list=False)
if accounting_dimensions:
for dimension in accounting_dimensions:
if filters.get(dimension):
conditions.append("{0} in (%({0})s)".format(dimension))
if filters.get(dimension.fieldname):
if frappe.get_cached_value('DocType', dimension.document_type, 'is_tree'):
filters[dimension.fieldname] = get_dimension_with_children(dimension.document_type,
filters.get(dimension.fieldname))
conditions.append("{0} in %({0})s".format(dimension.fieldname))
return "and {}".format(" and ".join(conditions)) if conditions else ""
@ -359,6 +362,12 @@ def get_columns(filters):
currency = get_company_currency(company)
columns = [
{
"fieldname": "gl_entry",
"fieldtype": "Link",
"options": "GL Entry",
"hidden": 1
},
{
"label": _("Posting Date"),
"fieldname": "posting_date",

View File

@ -201,7 +201,8 @@ def get_columns(additional_table_columns, filters):
{
'label': _('Mode Of Payment'),
'fieldname': 'mode_of_payment',
'fieldtype': 'Data',
'fieldtype': 'Link',
'options': 'Mode of Payment',
'width': 120
},
{
@ -309,6 +310,8 @@ def get_items(filters, additional_query_columns):
if additional_query_columns:
additional_query_columns = ', ' + ', '.join(additional_query_columns)
else:
additional_query_columns = ''
return frappe.db.sql("""
select
@ -320,7 +323,7 @@ def get_items(filters, additional_query_columns):
`tabPurchase Invoice Item`.`purchase_receipt`, `tabPurchase Invoice Item`.`po_detail`,
`tabPurchase Invoice Item`.`expense_account`, `tabPurchase Invoice Item`.`stock_qty`,
`tabPurchase Invoice Item`.`stock_uom`, `tabPurchase Invoice Item`.`base_net_amount`,
`tabPurchase Invoice`.supplier_name, `tabPurchase Invoice`.mode_of_payment {0}
`tabPurchase Invoice`.`supplier_name`, `tabPurchase Invoice`.`mode_of_payment` {0}
from `tabPurchase Invoice`, `tabPurchase Invoice Item`
where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and
`tabPurchase Invoice`.docstatus = 1 %s

View File

@ -373,6 +373,8 @@ def get_items(filters, additional_query_columns):
if additional_query_columns:
additional_query_columns = ', ' + ', '.join(additional_query_columns)
else:
additional_query_columns = ''
return frappe.db.sql("""
select

View File

@ -6,7 +6,7 @@ import frappe
from frappe.utils import flt
from frappe import msgprint, _
from frappe.model.meta import get_field_precision
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children
def execute(filters=None):
return _execute(filters)
@ -341,14 +341,18 @@ def get_conditions(filters):
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s)"""
accounting_dimensions = get_accounting_dimensions()
accounting_dimensions = get_accounting_dimensions(as_list=False)
if accounting_dimensions:
for dimension in accounting_dimensions:
if filters.get(dimension):
if filters.get(dimension.fieldname):
if frappe.get_cached_value('DocType', dimension.document_type, 'is_tree'):
filters[dimension.fieldname] = get_dimension_with_children(dimension.document_type,
filters.get(dimension.fieldname))
conditions += """ and exists(select name from `tabSales Invoice Item`
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Item`.{0}, '') = %({0})s)""".format(dimension)
and ifnull(`tabSales Invoice Item`.{0}, '') in %({0})s)""".format(dimension.fieldname)
return conditions

View File

@ -7,7 +7,7 @@ from frappe import _
from frappe.utils import flt, getdate, formatdate, cstr
from erpnext.accounts.report.financial_statements \
import filter_accounts, set_gl_entries_by_account, filter_out_zero_value_rows
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children
value_fields = ("opening_debit", "opening_credit", "debit", "credit", "closing_debit", "closing_credit")
@ -109,7 +109,7 @@ def get_rootwise_opening_balances(filters, report_type):
additional_conditions += fb_conditions
accounting_dimensions = get_accounting_dimensions()
accounting_dimensions = get_accounting_dimensions(as_list=False)
query_filters = {
"company": filters.company,
@ -122,11 +122,14 @@ def get_rootwise_opening_balances(filters, report_type):
if accounting_dimensions:
for dimension in accounting_dimensions:
if filters.get(dimension):
additional_conditions += """ and {0} in (%({0})s) """.format(dimension)
if filters.get(dimension.fieldname):
if frappe.get_cached_value('DocType', dimension.document_type, 'is_tree'):
filters[dimension.fieldname] = get_dimension_with_children(dimension.document_type,
filters.get(dimension.fieldname))
additional_conditions += "and {0} in %({0})s".format(dimension.fieldname)
query_filters.update({
dimension: filters.get(dimension)
dimension.fieldname: filters.get(dimension.fieldname)
})
gle = frappe.db.sql("""

View File

@ -139,12 +139,14 @@
"read_only": 1
}
],
"is_tree": 1,
"links": [],
"modified": "2020-03-02 19:34:28.362267",
"modified": "2020-03-18 18:00:08.885805",
"modified_by": "Administrator",
"module": "Assets",
"name": "Location",
"name_case": "Title Case",
"nsm_parent_field": "parent_location",
"owner": "Administrator",
"permissions": [
{

View File

@ -499,7 +499,8 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
reference_doctype: me.frm.doctype,
reference_name: me.frm.docname,
content: __('Reason for hold: ')+data.reason_for_hold,
comment_email: frappe.session.user
comment_email: frappe.session.user,
comment_by: frappe.session.user_fullname
},
callback: function(r) {
if(!r.exc) {

View File

@ -34,4 +34,4 @@ def get_data():
'items': ['Pricing Rule']
}
]
}
}

View File

@ -4,15 +4,17 @@
// attach required files
{% include 'erpnext/public/js/controllers/buying.js' %};
frappe.ui.form.on('Suppier Quotation', {
setup: function(frm) {
frm.custom_make_buttons = {
'Purchase Order': 'Purchase Order'
}
}
});
erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({
setup: function() {
this.frm.custom_make_buttons = {
'Purchase Order': 'Purchase Order',
'Quotation': 'Quotation',
'Subscription': 'Subscription'
}
this._super();
},
refresh: function() {
var me = this;
this._super();

View File

@ -1,22 +0,0 @@
{
"cards": [],
"charts": [],
"creation": "2020-01-28 11:49:55.003637",
"developer_mode_only": 0,
"disable_user_customization": 0,
"docstatus": 0,
"doctype": "Desk Page",
"extends_another_page": 0,
"icon": "",
"idx": 0,
"is_standard": 1,
"label": "Communication",
"modified": "2020-03-12 16:30:40.534226",
"modified_by": "Administrator",
"module": "Communication",
"name": "Communication",
"owner": "Administrator",
"pin_to_bottom": 0,
"pin_to_top": 0,
"shortcuts": []
}

View File

@ -19,6 +19,7 @@ from erpnext.accounts.doctype.pricing_rule.utils import (apply_pricing_rule_on_t
from erpnext.exceptions import InvalidCurrency
from six import text_type
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
from erpnext.stock.get_item_details import get_item_warehouse
force_item_fields = ("item_group", "brand", "stock_uom", "is_fixed_asset", "item_tax_rate", "pricing_rules")
@ -1126,16 +1127,16 @@ def set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname,
"""
Returns a Sales Order Item child item containing the default values
"""
p_doctype = frappe.get_doc(parent_doctype, parent_doctype_name)
child_item = frappe.new_doc('Sales Order Item', p_doctype, child_docname)
p_doc = frappe.get_doc(parent_doctype, parent_doctype_name)
child_item = frappe.new_doc('Sales Order Item', p_doc, child_docname)
item = frappe.get_doc("Item", item_code)
child_item.item_code = item.item_code
child_item.item_name = item.item_name
child_item.description = item.description
child_item.reqd_by_date = p_doctype.delivery_date
child_item.reqd_by_date = p_doc.delivery_date
child_item.uom = item.stock_uom
child_item.conversion_factor = get_conversion_factor(item_code, item.stock_uom).get("conversion_factor") or 1.0
child_item.warehouse = p_doctype.set_warehouse or p_doctype.items[0].warehouse
child_item.warehouse = get_item_warehouse(item, p_doc, overwrite_warehouse=True)
return child_item
@ -1143,13 +1144,13 @@ def set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docna
"""
Returns a Purchase Order Item child item containing the default values
"""
p_doctype = frappe.get_doc(parent_doctype, parent_doctype_name)
child_item = frappe.new_doc('Purchase Order Item', p_doctype, child_docname)
p_doc = frappe.get_doc(parent_doctype, parent_doctype_name)
child_item = frappe.new_doc('Purchase Order Item', p_doc, child_docname)
item = frappe.get_doc("Item", item_code)
child_item.item_code = item.item_code
child_item.item_name = item.item_name
child_item.description = item.description
child_item.schedule_date = p_doctype.schedule_date
child_item.schedule_date = p_doc.schedule_date
child_item.uom = item.stock_uom
child_item.conversion_factor = get_conversion_factor(item_code, item.stock_uom).get("conversion_factor") or 1.0
child_item.base_rate = 1 # Initiallize value will update in parent validation

View File

@ -672,19 +672,32 @@ class BuyingController(StockController):
# If asset has to be auto created
# Check for asset naming series
if item_data.get('asset_naming_series'):
created_assets = []
for qty in range(cint(d.qty)):
self.make_asset(d)
is_plural = 's' if cint(d.qty) != 1 else ''
messages.append(_('{0} Asset{2} Created for <b>{1}</b>').format(cint(d.qty), d.item_code, is_plural))
asset = self.make_asset(d)
created_assets.append(asset)
if len(created_assets) > 5:
# dont show asset form links if more than 5 assets are created
messages.append(_('{} Asset{} created for {}').format(len(created_assets), is_plural, frappe.bold(d.item_code)))
else:
assets_link = list(map(lambda d: frappe.utils.get_link_to_form('Asset', d), created_assets))
assets_link = frappe.bold(','.join(assets_link))
is_plural = 's' if len(created_assets) != 1 else ''
messages.append(
_('Asset{} {assets_link} created for {}').format(is_plural, frappe.bold(d.item_code), assets_link=assets_link)
)
else:
frappe.throw(_("Row {1}: Asset Naming Series is mandatory for the auto creation for item {0}")
.format(d.item_code, d.idx))
frappe.throw(_("Row {}: Asset Naming Series is mandatory for the auto creation for item {}")
.format(d.idx, frappe.bold(d.item_code)))
else:
messages.append(_("Assets not created for <b>{0}</b>. You will have to create asset manually.")
.format(d.item_code))
messages.append(_("Assets not created for {0}. You will have to create asset manually.")
.format(frappe.bold(d.item_code)))
for message in messages:
frappe.msgprint(message, title="Success")
frappe.msgprint(message, title="Success", indicator="green")
def make_asset(self, row):
if not row.asset_location:
@ -716,6 +729,8 @@ class BuyingController(StockController):
asset.set_missing_values()
asset.insert()
return asset.name
def update_fixed_asset(self, field, delete_asset = False):
for d in self.get("items"):
if d.is_fixed_asset:
@ -745,7 +760,7 @@ class BuyingController(StockController):
asset.supplier = None
if asset.docstatus == 1 and delete_asset:
frappe.throw(_('Cannot cancel this document as it is linked with submitted asset {0}.\
Please cancel the it to continue.').format(asset.name))
Please cancel the it to continue.').format(frappe.utils.get_link_to_form('Asset', asset.name)))
asset.flags.ignore_validate_update_after_submit = True
asset.flags.ignore_mandatory = True
@ -1026,4 +1041,4 @@ def get_batches_with_qty(item_code, fg_item, required_qty, transferred_batch_qty
available_batches.append({'batch': batch, 'qty': available_qty})
required_qty -= available_qty
return available_batches
return available_batches

View File

@ -3,6 +3,7 @@
from __future__ import unicode_literals
import frappe
import erpnext
from frappe.desk.reportview import get_match_cond, get_filters_cond
from frappe.utils import nowdate, getdate
from collections import defaultdict
@ -129,23 +130,26 @@ def supplier_query(doctype, txt, searchfield, start, page_len, filters):
})
def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
company_currency = erpnext.get_company_currency(filters.get('company'))
tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
where tabAccount.docstatus!=2
and account_type in (%s)
and is_group = 0
and company = %s
and account_currency = %s
and `%s` LIKE %s
order by idx desc, name
limit %s, %s""" %
(", ".join(['%s']*len(filters.get("account_type"))), "%s", searchfield, "%s", "%s", "%s"),
tuple(filters.get("account_type") + [filters.get("company"), "%%%s%%" % txt,
(", ".join(['%s']*len(filters.get("account_type"))), "%s", "%s", searchfield, "%s", "%s", "%s"),
tuple(filters.get("account_type") + [filters.get("company"), company_currency, "%%%s%%" % txt,
start, page_len]))
if not tax_accounts:
tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
where tabAccount.docstatus!=2 and is_group = 0
and company = %s and `%s` LIKE %s limit %s, %s"""
% ("%s", searchfield, "%s", "%s", "%s"),
(filters.get("company"), "%%%s%%" % txt, start, page_len))
and company = %s and account_currency = %s and `%s` LIKE %s limit %s, %s""" #nosec
% ("%s", "%s", searchfield, "%s", "%s", "%s"),
(filters.get("company"), company_currency, "%%%s%%" % txt, start, page_len))
return tax_accounts
@ -175,6 +179,12 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
# scan description only if items are less than 50000
description_cond = 'or tabItem.description LIKE %(txt)s'
extra_cond = " and tabItem.has_variants=0"
if (filters and isinstance(filters, dict)
and filters.get("doctype") == "BOM"):
extra_cond = ""
del filters["doctype"]
return frappe.db.sql("""select tabItem.name,
if(length(tabItem.item_name) > 40,
concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name,
@ -184,11 +194,11 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
{columns}
from tabItem
where tabItem.docstatus < 2
and tabItem.has_variants=0
and tabItem.disabled=0
and (tabItem.end_of_life > %(today)s or ifnull(tabItem.end_of_life, '0000-00-00')='0000-00-00')
and ({scond} or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s)
{description_cond})
{extra_cond}
{fcond} {mcond}
order by
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
@ -199,6 +209,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
key=searchfield,
columns=columns,
scond=searchfields,
extra_cond=extra_cond,
fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'),
mcond=get_match_cond(doctype).replace('%', '%%'),
description_cond = description_cond),

View File

@ -69,6 +69,17 @@ status_map = {
["Cancelled", "eval:self.docstatus==2"],
["Closed", "eval:self.status=='Closed'"],
],
"Purchase Invoice": [
["Draft", None],
["Submitted", "eval:self.docstatus==1"],
["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"],
["Return", "eval:self.is_return==1 and self.docstatus==1"],
["Debit Note Issued",
"eval:self.outstanding_amount <= 0 and self.docstatus==1 and self.is_return==0 and get_value('Purchase Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"],
["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"],
["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"],
["Cancelled", "eval:self.docstatus==2"],
],
"Material Request": [
["Draft", None],
["Stopped", "eval:self.status == 'Stopped'"],

View File

@ -238,7 +238,7 @@ class StockController(AccountsController):
for d in self.items:
if not d.batch_no: continue
serial_nos = [d.name for d in frappe.get_all("Serial No", {'batch_no': d.batch_no})]
serial_nos = [sr.name for sr in frappe.get_all("Serial No", {'batch_no': d.batch_no})]
if serial_nos:
frappe.db.set_value("Serial No", { 'name': ['in', serial_nos] }, "batch_no", None)

View File

@ -172,7 +172,6 @@
"options": "Customer"
},
{
"depends_on": "eval: doc.source==\"Campaign\"",
"fieldname": "campaign_name",
"fieldtype": "Link",
"label": "Campaign Name",
@ -514,4 +513,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "title"
}
}

View File

@ -132,10 +132,17 @@ class Lead(SellingController):
# do not create an address if no fields are available,
# skipping country since the system auto-sets it from system defaults
if not any([self.get(field) for field in address_fields if field != "country"]):
address = frappe.new_doc("Address")
mandatory_fields = [ df.fieldname for df in address.meta.fields if df.reqd ]
if not all([self.get(field) for field in mandatory_fields]):
frappe.msgprint(_('Missing mandatory fields in address. \
{0} to create address' ).format("<a href='desk#Form/Address/New Address 1' \
> Click here </a>"),
alert=True, indicator='yellow')
return
address = frappe.new_doc("Address")
address.update({addr_field: self.get(addr_field) for addr_field in address_fields})
address.update({info_field: self.get(info_field) for info_field in info_fields})
address.insert()

View File

@ -216,7 +216,8 @@
{
"fieldname": "opportunity_amount",
"fieldtype": "Currency",
"label": "Opportunity Amount"
"label": "Opportunity Amount",
"options": "currency"
},
{
"default": "0",
@ -422,7 +423,7 @@
"icon": "fa fa-info-sign",
"idx": 195,
"links": [],
"modified": "2020-01-13 16:18:44.477818",
"modified": "2020-03-20 12:28:45.228994",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity",

View File

@ -6,46 +6,28 @@ from __future__ import unicode_literals
import frappe
from frappe.utils.make_random import get_random
from erpnext.assets.doctype.asset.asset import make_purchase_invoice, make_sales_invoice
from erpnext.assets.doctype.asset.asset import make_sales_invoice
from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset
def work():
frappe.set_user(frappe.db.get_global('demo_accounts_user'))
asset_list = make_asset_purchase_entry()
if not asset_list:
# fixed_asset.work() already run
return
# Enable booking asset depreciation entry automatically
frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1)
# post depreciation entries as on today
post_depreciation_entries()
# scrap a random asset
frappe.db.set_value("Company", "Wind Power LLC", "disposal_account", "Gain/Loss on Asset Disposal - WPL")
asset = get_random_asset()
scrap_asset(asset.name)
# Sell a random asset
sell_an_asset()
def make_asset_purchase_entry():
asset_list = frappe.get_all("Asset", filters={"purchase_invoice": ["in", ("", None)]},
fields=["name", "item_code", "gross_purchase_amount", "company", "purchase_date"])
# make purchase invoice
for asset in asset_list:
pi = make_purchase_invoice(asset.name, asset.item_code, asset.gross_purchase_amount,
asset.company, asset.purchase_date)
pi.supplier = get_random("Supplier")
pi.save()
pi.submit()
return asset_list
# Sell a random asset
sell_an_asset()
def sell_an_asset():
asset = get_random_asset()
@ -55,8 +37,9 @@ def sell_an_asset():
if asset.value_after_depreciation else asset.gross_purchase_amount * 0.9
si.save()
si.submit()
def get_random_asset():
return frappe.db.sql(""" select name, item_code, value_after_depreciation, gross_purchase_amount
from `tabAsset`
from `tabAsset`
where docstatus=1 and status not in ("Scrapped", "Sold") order by rand() limit 1""", as_dict=1)[0]

View File

@ -1,274 +1,90 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:assessment_group_name",
"beta": 0,
"creation": "2016-08-04 04:42:48.319388",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:assessment_group_name",
"creation": "2016-08-04 04:42:48.319388",
"doctype": "DocType",
"editable_grid": 1,
"field_order": [
"assessment_group_name",
"is_group",
"section_break_2",
"parent_assessment_group",
"lft",
"rgt",
"old_parent"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "assessment_group_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Assessment Group Name",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "assessment_group_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Assessment Group Name",
"reqd": 1,
"unique": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "is_group",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Is Group",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"default": "0",
"fieldname": "is_group",
"fieldtype": "Check",
"label": "Is Group"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_2",
"fieldtype": "Section Break",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "section_break_2",
"fieldtype": "Section Break",
"hidden": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "parent_assessment_group",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Parent Assessment Group",
"length": 0,
"no_copy": 0,
"options": "Assessment Group",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "parent_assessment_group",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Parent Assessment Group",
"options": "Assessment Group",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "lft",
"fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "lft",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "lft",
"fieldtype": "Int",
"label": "lft"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "rgt",
"fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "rgt",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "rgt",
"fieldtype": "Int",
"label": "rgt"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "old_parent",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "old_parent",
"length": 0,
"no_copy": 0,
"options": "Assessment Group",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
"fieldname": "old_parent",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "old_parent",
"options": "Assessment Group"
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-11-10 19:09:25.366400",
"modified_by": "Administrator",
"module": "Education",
"name": "Assessment Group",
"name_case": "",
"owner": "Administrator",
],
"is_tree": 1,
"links": [],
"modified": "2020-03-18 18:01:14.710416",
"modified_by": "Administrator",
"module": "Education",
"name": "Assessment Group",
"nsm_parent_field": "parent_assessment_group",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Academics User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Academics User",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
],
"quick_entry": 1,
"restrict_to_domain": "Education",
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -74,7 +74,7 @@
}
],
"image_field": "hero_image",
"modified": "2019-06-12 12:34:23.748157",
"modified": "2020-03-29 12:50:27.677589",
"modified_by": "Administrator",
"module": "Education",
"name": "Course",
@ -103,6 +103,30 @@
"role": "Instructor",
"share": 1,
"write": 1
},
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Administrator",
"share": 1,
"write": 1
},
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Education Manager",
"share": 1,
"write": 1
}
],
"restrict_to_domain": "Education",

View File

@ -0,0 +1,60 @@
{
"custom_fields": [
{
"_assign": null,
"_comments": null,
"_liked_by": null,
"_user_tags": null,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"collapsible_depends_on": null,
"columns": 0,
"creation": "2019-12-02 11:00:03.432994",
"default": null,
"depends_on": null,
"description": null,
"docstatus": 0,
"dt": "Contact",
"fetch_from": null,
"fetch_if_empty": 0,
"fieldname": "is_billing_contact",
"fieldtype": "Check",
"hidden": 0,
"idx": 27,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"insert_after": "is_primary_contact",
"label": "Is Billing Contact",
"length": 0,
"modified": "2019-12-02 11:00:03.432994",
"modified_by": "Administrator",
"name": "Contact-is_billing_contact",
"no_copy": 0,
"options": null,
"owner": "Administrator",
"parent": null,
"parentfield": null,
"parenttype": null,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": null,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"translatable": 0,
"unique": 0,
"width": null
}
],
"custom_perms": [],
"doctype": "Contact",
"property_setters": [],
"sync_on_migrate": 1
}

View File

@ -1,542 +1,205 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:healthcare_service_unit_name",
"beta": 1,
"creation": "2016-09-21 13:48:14.731437",
"custom": 0,
"description": "Healthcare Service Unit",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1,
"field_order": [
"healthcare_service_unit_name",
"parent_healthcare_service_unit",
"is_group",
"service_unit_type",
"allow_appointments",
"overlap_appointments",
"inpatient_occupancy",
"occupancy_status",
"warehouse",
"company",
"lft",
"rgt",
"old_parent"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "healthcare_service_unit_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Service Unit",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
"columns": 0,
"fieldname": "parent_healthcare_service_unit",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Parent Service Unit",
"length": 0,
"no_copy": 0,
"options": "Healthcare Service Unit",
"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": "Healthcare Service Unit"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
"columns": 0,
"default": "0",
"depends_on": "eval:doc.inpatient_occupancy != 1 && doc.allow_appointments != 1",
"fieldname": "is_group",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Is Group",
"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": "Is Group"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_group != 1",
"fieldname": "service_unit_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": "Service Unit Type",
"length": 0,
"no_copy": 0,
"options": "Healthcare Service Unit Type",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"options": "Healthcare Service Unit Type"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
"columns": 0,
"default": "0",
"depends_on": "eval:doc.is_group != 1 && doc.inpatient_occupancy != 1",
"fetch_from": "service_unit_type.allow_appointments",
"fieldname": "allow_appointments",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allow Appointments",
"length": 0,
"no_copy": 1,
"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,
"default": "0",
"depends_on": "eval:doc.is_group != 1 && doc.allow_appointments == 1 && doc.inpatient_occupany != 1",
"fetch_from": "service_unit_type.overlap_appointments",
"fieldname": "overlap_appointments",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allow Overlap",
"length": 0,
"no_copy": 1,
"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": 1,
"collapsible": 0,
"columns": 0,
"default": "0",
"depends_on": "eval:doc.allow_appointments != 1 && doc.is_group != 1",
"fetch_from": "service_unit_type.inpatient_occupancy",
"fieldname": "inpatient_occupancy",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Inpatient Occupancy",
"length": 0,
"no_copy": 1,
"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": 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,
"default": "",
"depends_on": "eval:doc.inpatient_occupancy == 1",
"fieldname": "occupancy_status",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Occupancy Status",
"length": 0,
"no_copy": 1,
"options": "Vacant\nOccupied",
"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": 1,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_group != 1",
"fieldname": "warehouse",
"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": "Warehouse",
"length": 0,
"no_copy": 1,
"options": "Warehouse",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"options": "Warehouse"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"length": 0,
"no_copy": 0,
"options": "Company",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 1,
"report_hide": 0,
"reqd": 1,
"search_index": 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": "lft",
"fieldtype": "Int",
"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": "lft",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"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": "rgt",
"fieldtype": "Int",
"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": "rgt",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"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": "old_parent",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Old Parent",
"length": 0,
"no_copy": 1,
"options": "Healthcare Service Unit",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"report_hide": 1
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-10-04 21:09:52.261882",
"is_tree": 1,
"links": [],
"modified": "2020-03-18 18:02:23.713439",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Healthcare Service Unit",
"name_case": "",
"nsm_parent_field": "parent_healthcare_service_unit",
"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": "Nursing User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 0
"share": 1
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Healthcare Administrator",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Physician",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"restrict_to_domain": "Healthcare",
"search_fields": "healthcare_service_unit_name",
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "healthcare_service_unit_name",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
"track_changes": 1
}

View File

@ -386,5 +386,5 @@ def get_procedure_prescribed(patient):
return frappe.db.sql("""select pp.name, pp.procedure, pp.parent, ct.practitioner,
ct.encounter_date, pp.practitioner, pp.date, pp.department
from `tabPatient Encounter` ct, `tabProcedure Prescription` pp
where ct.patient='{0}' and pp.parent=ct.name and pp.appointment_booked=0
order by ct.creation desc""".format(patient))
where ct.patient=%(patient)s and pp.parent=ct.name and pp.appointment_booked=0
order by ct.creation desc""", {"patient": patient})

View File

@ -129,11 +129,13 @@
],
"icon": "fa fa-sitemap",
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2019-12-12 14:48:35.254308",
"modified": "2020-03-18 18:03:27.784362",
"modified_by": "Administrator",
"module": "HR",
"name": "Department",
"nsm_parent_field": "parent_department",
"owner": "Administrator",
"permissions": [
{

View File

@ -48,12 +48,17 @@ def get_abbreviated_name(name, company):
@frappe.whitelist()
def get_children(doctype, parent=None, company=None, is_root=False):
condition = ''
var_dict = {
"name": get_root_of("Department"),
"parent": parent,
"company": company,
}
if company == parent:
condition = "name='{0}'".format(get_root_of("Department"))
condition = "name=%(name)s"
elif company:
condition = "parent_department='{0}' and company='{1}'".format(parent, company)
condition = "parent_department=%(parent)s and company=%(company)s"
else:
condition = "parent_department = '{0}'".format(parent)
condition = "parent_department = %(parent)s"
return frappe.db.sql("""
select
@ -62,7 +67,7 @@ def get_children(doctype, parent=None, company=None, is_root=False):
from `tab{doctype}`
where
{condition}
order by name""".format(doctype=doctype, condition=condition), as_dict=1)
order by name""".format(doctype=doctype, condition=condition), var_dict, as_dict=1)
@frappe.whitelist()
def add_node():

View File

@ -190,6 +190,7 @@ def get_benefit_component_amount(employee, start_date, end_date, salary_componen
component_max_benefit, depends_on_payment_days = frappe.db.get_value("Salary Component",
salary_component, ["max_benefit_amount", "depends_on_payment_days"])
benefit_amount = 0
if benefit_application:
benefit_amount = frappe.db.get_value("Employee Benefit Application Detail",
{"parent": benefit_application[0][0], "earning_component": salary_component}, "amount")

View File

@ -71,7 +71,7 @@
"label": "Amount",
"oldfieldname": "tax_amount",
"oldfieldtype": "Currency",
"options": "currency"
"options": "Company:company:default_currency"
},
{
"columns": 2,
@ -81,7 +81,7 @@
"label": "Total",
"oldfieldname": "total",
"oldfieldtype": "Currency",
"options": "currency",
"options": "Company:company:default_currency",
"read_only": 1
},
{
@ -95,7 +95,7 @@
],
"istable": 1,
"links": [],
"modified": "2019-12-11 13:50:02.883328",
"modified": "2020-03-11 13:25:06.721917",
"modified_by": "Administrator",
"module": "HR",
"name": "Expense Taxes and Charges",

View File

@ -130,7 +130,7 @@ class LeaveApplication(Document):
if self.status == "Approved":
for dt in daterange(getdate(self.from_date), getdate(self.to_date)):
date = dt.strftime("%Y-%m-%d")
status = "Half Day" if date == self.half_day_date else "On Leave"
status = "Half Day" if getdate(date) == getdate(self.half_day_date) else "On Leave"
attendance_name = frappe.db.exists('Attendance', dict(employee = self.employee,
attendance_date = date, docstatus = ('!=', 2)))

View File

@ -6,11 +6,14 @@ from __future__ import unicode_literals
import frappe
import unittest
from frappe.utils import nowdate,flt, cstr,random_string
# test_records = frappe.get_test_records('Vehicle Log')
class TestVehicleLog(unittest.TestCase):
def test_make_vehicle_log_and_syncing_of_odometer_value(self):
employee_id=frappe.db.sql("""select name from `tabEmployee` order by modified desc limit 1""")[0][0]
employee_id = frappe.db.sql("""select name from `tabEmployee` where status='Active' order by modified desc limit 1""")
employee_id = employee_id[0][0] if employee_id else None
license_plate = get_vehicle(employee_id)
vehicle_log = frappe.get_doc({
"doctype": "Vehicle Log",
"license_plate": cstr(license_plate),

View File

@ -3,11 +3,6 @@
frappe.ui.form.on("Vehicle Log", {
refresh: function(frm) {
if(frm.doc.license_plate && frm.doc.__islocal){
frm.events.set_vehicle_details(frm);
}
if(frm.doc.docstatus == 1) {
frm.add_custom_button(__('Expense Claim'), function() {
frm.events.expense_claim(frm);
@ -16,27 +11,6 @@ frappe.ui.form.on("Vehicle Log", {
}
},
license_plate: function(frm) {
if(frm.doc.license_plate){
frm.events.set_vehicle_details(frm);
}
},
set_vehicle_details: function(frm) {
frappe.call({
method: "erpnext.hr.doctype.vehicle_log.vehicle_log.get_make_model",
args: {
license_plate: frm.doc.license_plate
},
callback: function(r) {
frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "make", r.message[0]);
frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "model", r.message[1]);
frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "last_odometer", r.message[2]);
frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "employee", r.message[3]);
}
});
},
expense_claim: function(frm){
frappe.call({
method: "erpnext.hr.doctype.vehicle_log.vehicle_log.make_expense_claim",

View File

@ -1,5 +1,4 @@
{
"actions": [],
"autoname": "naming_series:",
"creation": "2016-09-03 14:14:51.788550",
"doctype": "DocType",
@ -56,6 +55,8 @@
"reqd": 1
},
{
"fetch_from": "license_plate.employee",
"fetch_if_empty": 1,
"fieldname": "employee",
"fieldtype": "Link",
"in_list_view": 1,
@ -73,11 +74,13 @@
"fieldtype": "Column Break"
},
{
"fetch_from": "license_plate.model",
"fieldname": "model",
"fieldtype": "Read Only",
"label": "Model"
},
{
"fetch_from": "license_plate.make",
"fieldname": "make",
"fieldtype": "Read Only",
"label": "Make"
@ -152,6 +155,7 @@
"read_only": 1
},
{
"fetch_from": "license_plate.last_odometer",
"fieldname": "last_odometer",
"fieldtype": "Int",
"label": "last Odometer Value ",
@ -164,8 +168,7 @@
}
],
"is_submittable": 1,
"links": [],
"modified": "2020-01-28 12:43:34.419647",
"modified": "2020-03-18 16:45:45.060761",
"modified_by": "Administrator",
"module": "HR",
"name": "Vehicle Log",

View File

@ -12,18 +12,7 @@ from frappe.model.document import Document
class VehicleLog(Document):
def validate(self):
if flt(self.odometer) < flt(self.last_odometer):
frappe.throw(_("Current Odometer reading entered should be greater than initial Vehicle Odometer {0}").format(self.last_odometer))
for service_detail in self.service_detail:
if (service_detail.service_item or service_detail.type or service_detail.frequency or service_detail.expense_amount):
if not (service_detail.service_item and service_detail.type and service_detail.frequency and service_detail.expense_amount):
frappe.throw(_("Service Item,Type,frequency and expense amount are required"))
def before_insert(self):
model_details = get_make_model(self.license_plate)
self.make = model_details[0]
self.model = model_details[1]
self.last_odometer = model_details[2]
self.employee = model_details[3]
frappe.throw(_("Current Odometer Value should be greater than Last Odometer Value {0}").format(self.last_odometer))
def on_submit(self):
frappe.db.set_value("Vehicle", self.license_plate, "last_odometer", self.odometer)
@ -34,35 +23,26 @@ class VehicleLog(Document):
updated_odometer_value = int(frappe.db.get_value("Vehicle", self.license_plate, "last_odometer")) - distance_travelled
frappe.db.set_value("Vehicle", self.license_plate, "last_odometer", updated_odometer_value)
@frappe.whitelist()
def get_make_model(license_plate):
vehicle=frappe.get_doc("Vehicle",license_plate)
return (vehicle.make, vehicle.model, vehicle.last_odometer, vehicle.employee)
@frappe.whitelist()
def make_expense_claim(docname):
def check_exp_claim_exists():
exp_claim = frappe.db.sql("""select name from `tabExpense Claim` where vehicle_log=%s""",vehicle_log.name)
return exp_claim[0][0] if exp_claim else ""
def calc_service_exp():
total_exp_amt=0
exp_claim = check_exp_claim_exists()
if exp_claim:
frappe.throw(_("Expense Claim {0} already exists for the Vehicle Log").format(exp_claim))
for serdetail in vehicle_log.service_detail:
total_exp_amt = total_exp_amt + serdetail.expense_amount
return total_exp_amt
expense_claim = frappe.db.exists("Expense Claim", {"vehicle_log": docname})
if expense_claim:
frappe.throw(_("Expense Claim {0} already exists for the Vehicle Log").format(expense_claim))
vehicle_log = frappe.get_doc("Vehicle Log", docname)
service_expense = sum([flt(d.expense_amount) for d in vehicle_log.service_detail])
claim_amount = service_expense + flt(vehicle_log.price)
if not claim_amount:
frappe.throw(_("No additional expenses has been added"))
exp_claim = frappe.new_doc("Expense Claim")
exp_claim.employee=vehicle_log.employee
exp_claim.vehicle_log=vehicle_log.name
exp_claim.remark=_("Expense Claim for Vehicle Log {0}").format(vehicle_log.name)
fuel_price=vehicle_log.price
total_claim_amt=calc_service_exp() + fuel_price
exp_claim.append("expenses",{
"expense_date":vehicle_log.date,
"description":_("Vehicle Expenses"),
"amount":total_claim_amt
exp_claim.employee = vehicle_log.employee
exp_claim.vehicle_log = vehicle_log.name
exp_claim.remark = _("Expense Claim for Vehicle Log {0}").format(vehicle_log.name)
exp_claim.append("expenses", {
"expense_date": vehicle_log.date,
"description": _("Vehicle Expenses"),
"amount": claim_amount
})
return exp_claim.as_dict()

View File

@ -1,153 +1,57 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2016-09-03 19:20:14.561962",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
"creation": "2016-09-03 19:20:14.561962",
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"service_item",
"type",
"frequency",
"expense_amount"
],
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "service_item",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Service Item",
"length": 0,
"no_copy": 0,
"options": "\nBrake Oil\nBrake Pad\nClutch Plate\nEngine Oil\nOil Change\nWheels",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "service_item",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Service Item",
"options": "\nBrake Oil\nBrake Pad\nClutch Plate\nEngine Oil\nOil Change\nWheels",
"reqd": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "type",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Type",
"length": 0,
"no_copy": 0,
"options": "\nInspection\nService\nChange",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "type",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Type",
"options": "\nInspection\nService\nChange",
"reqd": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "frequency",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Frequency",
"length": 0,
"no_copy": 0,
"options": "\nMileage\nMonthly\nQuarterly\nHalf Yearly\nYearly",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "frequency",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Frequency",
"options": "\nMileage\nMonthly\nQuarterly\nHalf Yearly\nYearly",
"reqd": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "expense_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Expense",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
"fieldname": "expense_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Expense",
"reqd": 1
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-01-09 11:10:29.476907",
"modified_by": "Administrator",
"module": "HR",
"name": "Vehicle Service",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
],
"istable": 1,
"modified": "2020-03-18 16:49:46.645004",
"modified_by": "Administrator",
"module": "HR",
"name": "Vehicle Service",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -273,11 +273,11 @@ class TestLoan(unittest.TestCase):
penalty_amount = (accrued_interest_amount * 4 * 25) / (100 * days_in_year(get_datetime(first_date).year))
lia = frappe.get_all("Loan Interest Accrual", fields=["is_paid"],
filters={"loan": loan.name}, order_by="posting_date")
lia1 = frappe.get_value("Loan Interest Accrual", {"loan": loan.name, "is_paid": 1}, 'name')
lia2 = frappe.get_value("Loan Interest Accrual", {"loan": loan.name, "is_paid": 0}, 'name')
self.assertTrue(lia[0].get('is_paid'))
self.assertFalse(lia[1].get('is_paid'))
self.assertTrue(lia1)
self.assertTrue(lia2)
def test_security_shortfall(self):
pledges = []
@ -294,18 +294,21 @@ class TestLoan(unittest.TestCase):
make_loan_disbursement_entry(loan.name, loan.loan_amount)
frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = %s
where loan_security=%s""", (100, 'Test Security 2'))
frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = 100
where loan_security='Test Security 2'""")
check_for_ltv_shortfall()
loan_security_shortfall = frappe.get_doc("Loan Security Shortfall", {"loan": loan.name})
self.assertTrue(loan_security_shortfall)
self.assertEquals(loan_security_shortfall.loan_amount, 1000000.00)
self.assertEquals(loan_security_shortfall.security_value, 400000.00)
self.assertEquals(loan_security_shortfall.shortfall_amount, 600000.00)
frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = 250
where loan_security='Test Security 2'""")
def create_loan_accounts():
if not frappe.db.exists("Account", "Loans and Advances (Assets) - _TC"):
frappe.get_doc({
@ -399,7 +402,8 @@ def create_loan_security_type():
"doctype": "Loan Security Type",
"loan_security_type": "Stock",
"unit_of_measure": "Nos",
"haircut": 50.00
"haircut": 50.00,
"loan_to_value_ratio": 50
}).insert(ignore_permissions=True)
def create_loan_security():

View File

@ -130,9 +130,10 @@ def make_accrual_interest_entry_for_term_loans(posting_date=None):
loan.loan_account, loan.principal_amount + loan.balance_loan_amount, loan.interest_amount,
payable_principal = loan.principal_amount , posting_date=posting_date)
frappe.db.sql("""UPDATE `tabRepayment Schedule`
SET is_accrued = 1 where name in (%s)""" #nosec
% ", ".join(['%s']*len(accrued_entries)), tuple(accrued_entries))
if accrued_entries:
frappe.db.sql("""UPDATE `tabRepayment Schedule`
SET is_accrued = 1 where name in (%s)""" #nosec
% ", ".join(['%s']*len(accrued_entries)), tuple(accrued_entries))
def make_loan_interest_accrual_entry(loan, applicant_type, applicant, interest_income_account, loan_account,
pending_principal_amount, interest_amount, payable_principal=None, process_loan_interest=None, posting_date=None):

View File

@ -14,27 +14,37 @@ frappe.ui.form.on('Blanket Order', {
refresh: function(frm) {
erpnext.hide_company();
if (frm.doc.customer && frm.doc.docstatus === 1) {
frm.add_custom_button(__('View Orders'), function() {
frappe.set_route('List', 'Sales Order', {blanket_order: frm.doc.name});
});
frm.add_custom_button(__("Create Sales Order"), function(){
frm.add_custom_button(__("Sales Order"), function() {
frappe.model.open_mapped_doc({
method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_sales_order",
frm: frm
method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_order",
frm: frm,
args: {
doctype: 'Sales Order'
}
});
}).addClass("btn-primary");
}, __('Create'));
frm.add_custom_button(__("Quotation"), function() {
frappe.model.open_mapped_doc({
method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_order",
frm: frm,
args: {
doctype: 'Quotation'
}
});
}, __('Create'));
}
if (frm.doc.supplier && frm.doc.docstatus === 1) {
frm.add_custom_button(__('View Orders'), function() {
frappe.set_route('List', 'Purchase Order', {blanket_order: frm.doc.name});
});
frm.add_custom_button(__("Create Purchase Order"), function(){
frm.add_custom_button(__("Purchase Order"), function(){
frappe.model.open_mapped_doc({
method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_purchase_order",
frm: frm
method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_order",
frm: frm,
args: {
doctype: 'Purchase Order'
}
});
}).addClass("btn-primary");
}, __('Create'));
}
},

View File

@ -14,10 +14,18 @@ from erpnext.stock.doctype.item.item import get_item_defaults
class BlanketOrder(Document):
def validate(self):
self.validate_dates()
self.validate_duplicate_items()
def validate_dates(self):
if getdate(self.from_date) > getdate(self.to_date):
frappe.throw(_("From date cannot be greater than To date"))
frappe.throw(_("From date cannot be greater than To date"))
def validate_duplicate_items(self):
item_list = []
for item in self.items:
if item.item_code in item_list:
frappe.throw(_("Note: Item {0} added multiple times").format(frappe.bold(item.item_code)))
item_list.append(item.item_code)
def update_ordered_qty(self):
ref_doctype = "Sales Order" if self.blanket_order_type == "Selling" else "Purchase Order"
@ -35,7 +43,14 @@ class BlanketOrder(Document):
d.db_set("ordered_qty", item_ordered_qty.get(d.item_code, 0))
@frappe.whitelist()
def make_sales_order(source_name):
def make_order(source_name):
doctype = frappe.flags.args.doctype
def update_doc(source_doc, target_doc, source_parent):
if doctype == 'Quotation':
target_doc.quotation_to = 'Customer'
target_doc.party_name = source_doc.customer
def update_item(source, target, source_parent):
target_qty = source.get("qty") - source.get("ordered_qty")
target.qty = target_qty if not flt(target_qty) < 0 else 0
@ -49,39 +64,11 @@ def make_sales_order(source_name):
target_doc = get_mapped_doc("Blanket Order", source_name, {
"Blanket Order": {
"doctype": "Sales Order"
"doctype": doctype,
"postprocess": update_doc
},
"Blanket Order Item": {
"doctype": "Sales Order Item",
"field_map": {
"rate": "blanket_order_rate",
"parent": "blanket_order"
},
"postprocess": update_item
}
})
return target_doc
@frappe.whitelist()
def make_purchase_order(source_name):
def update_item(source, target, source_parent):
target_qty = source.get("qty") - source.get("ordered_qty")
target.qty = target_qty if not flt(target_qty) < 0 else 0
item = get_item_defaults(target.item_code, source_parent.company)
if item:
target.item_name = item.get("item_name")
target.description = item.get("description")
target.uom = item.get("stock_uom")
target.warehouse = item.get("default_warehouse")
target.against_blanket_order = 1
target.blanket_order = source_name
target_doc = get_mapped_doc("Blanket Order", source_name, {
"Blanket Order": {
"doctype": "Purchase Order"
},
"Blanket Order Item": {
"doctype": "Purchase Order Item",
"doctype": doctype + " Item",
"field_map": {
"rate": "blanket_order_rate",
"parent": "blanket_order"

View File

@ -6,7 +6,7 @@ def get_data():
'fieldname': 'blanket_order',
'transactions': [
{
'items': ['Purchase Order', 'Sales Order']
'items': ['Purchase Order', 'Sales Order', 'Quotation']
}
]
}

View File

@ -7,13 +7,17 @@ import frappe
import unittest
from frappe.utils import add_months, today
from erpnext import get_company_currency
from .blanket_order import make_sales_order, make_purchase_order
from .blanket_order import make_order
class TestBlanketOrder(unittest.TestCase):
def setUp(self):
frappe.flags.args = frappe._dict()
def test_sales_order_creation(self):
bo = make_blanket_order(blanket_order_type="Selling")
so = make_sales_order(bo.name)
frappe.flags.args.doctype = 'Sales Order'
so = make_order(bo.name)
so.currency = get_company_currency(so.company)
so.delivery_date = today()
so.items[0].qty = 10
@ -29,7 +33,8 @@ class TestBlanketOrder(unittest.TestCase):
self.assertEqual(so.items[0].qty, bo.items[0].ordered_qty)
# test the quantity
so1 = make_sales_order(bo.name)
frappe.flags.args.doctype = 'Sales Order'
so1 = make_order(bo.name)
so1.currency = get_company_currency(so1.company)
self.assertEqual(so1.items[0].qty, (bo.items[0].qty-bo.items[0].ordered_qty))
@ -37,7 +42,8 @@ class TestBlanketOrder(unittest.TestCase):
def test_purchase_order_creation(self):
bo = make_blanket_order(blanket_order_type="Purchasing")
po = make_purchase_order(bo.name)
frappe.flags.args.doctype = 'Purchase Order'
po = make_order(bo.name)
po.currency = get_company_currency(po.company)
po.schedule_date = today()
po.items[0].qty = 10
@ -53,7 +59,8 @@ class TestBlanketOrder(unittest.TestCase):
self.assertEqual(po.items[0].qty, bo.items[0].ordered_qty)
# test the quantity
po1 = make_sales_order(bo.name)
frappe.flags.args.doctype = 'Purchase Order'
po1 = make_order(bo.name)
po1.currency = get_company_currency(po1.company)
self.assertEqual(po1.items[0].qty, (bo.items[0].qty-bo.items[0].ordered_qty))
@ -78,7 +85,7 @@ def make_blanket_order(**args):
"qty": args.quantity or 1000,
"rate": args.rate or 100
})
bo.insert()
bo.submit()
return bo

View File

@ -29,7 +29,10 @@ frappe.ui.form.on("BOM", {
frm.set_query("item", function() {
return {
query: "erpnext.controllers.queries.item_query"
query: "erpnext.controllers.queries.item_query",
filters: {
"doctype": "BOM"
}
};
});
@ -43,8 +46,7 @@ frappe.ui.form.on("BOM", {
frm.set_query("item_code", "items", function() {
return {
query: "erpnext.controllers.queries.item_query",
filters: [["Item", "name", "!=", cur_frm.doc.item]]
query: "erpnext.controllers.queries.item_query"
};
});
@ -120,22 +122,58 @@ frappe.ui.form.on("BOM", {
});
}
}
if (frm.doc.__onload && frm.doc.__onload["has_variants"]) {
frm.set_intro(__('This is a Template BOM and will be used to make the work order for {0} of the item {1}',
[
`<a class="variants-intro">variants</a>`,
`<a href="#Form/Item/${frm.doc.item}">${frm.doc.item}</a>`,
]), true);
frm.$wrapper.find(".variants-intro").on("click", () => {
frappe.set_route("List", "Item", {"variant_of": frm.doc.item});
});
}
},
make_work_order: function(frm) {
const fields = [{
const fields = [];
if (frm.doc.__onload && frm.doc.__onload["has_variants"]) {
fields.push({
fieldtype: 'Link',
label: __('Variant Item'),
fieldname: 'item',
options: "Item",
reqd: 1,
get_query: function() {
return {
query: "erpnext.controllers.queries.item_query",
filters: {
"variant_of": frm.doc.item
}
};
}
});
}
fields.push({
fieldtype: 'Float',
label: __('Qty To Manufacture'),
fieldname: 'qty',
reqd: 1,
default: 1
}];
});
frappe.prompt(fields, data => {
let item = data.item || frm.doc.item;
frappe.call({
method: "erpnext.manufacturing.doctype.work_order.work_order.make_work_order",
args: {
item: frm.doc.item,
bom_no: frm.doc.name,
item: item,
qty: data.qty || 0.0,
project: frm.doc.project
},

View File

@ -59,6 +59,10 @@ class BOM(WebsiteGenerator):
self.name = name
def onload(self):
super(BOM, self).onload()
if self.get("item") and cint(frappe.db.get_value("Item", self.item, "has_variants")):
self.set_onload("has_variants", True)
def validate(self):
self.route = frappe.scrub(self.name).replace('_', '-')
@ -114,10 +118,6 @@ class BOM(WebsiteGenerator):
child = self.append('operations', d)
child.hour_rate = flt(d.hour_rate / self.conversion_rate, 2)
def validate_rm_item(self, item):
if (item[0]['name'] in [it.item_code for it in self.items]) and item[0]['name'] == self.item:
frappe.throw(_("BOM #{0}: Raw material cannot be same as main Item").format(self.name))
def set_bom_material_details(self):
for item in self.get("items"):
self.validate_bom_currecny(item)
@ -147,7 +147,6 @@ class BOM(WebsiteGenerator):
args = json.loads(args)
item = self.get_item_det(args['item_code'])
self.validate_rm_item(item)
args['bom_no'] = args['bom_no'] or item and cstr(item[0]['default_bom']) or ''
args['transfer_for_manufacture'] = (cstr(args.get('include_item_in_manufacturing', '')) or
@ -498,6 +497,14 @@ class BOM(WebsiteGenerator):
self.scrap_material_cost = total_sm_cost
self.base_scrap_material_cost = base_total_sm_cost
def update_new_bom(self, old_bom, new_bom, rate):
for d in self.get("items"):
if d.bom_no != old_bom: continue
d.bom_no = new_bom
d.rate = rate
d.amount = (d.stock_qty or d.qty) * rate
def update_exploded_items(self):
""" Update Flat BOM, following will be correct data"""
self.get_exploded_items()
@ -827,6 +834,10 @@ def add_operations_cost(stock_entry, work_order=None, expense_account=None):
def get_bom_diff(bom1, bom2):
from frappe.model import table_fields
if bom1 == bom2:
frappe.throw(_("BOM 1 {0} and BOM 2 {1} should not be same")
.format(frappe.bold(bom1), frappe.bold(bom2)))
doc1 = frappe.get_doc('BOM', bom1)
doc2 = frappe.get_doc('BOM', bom2)

View File

@ -14,10 +14,13 @@ import click
class BOMUpdateTool(Document):
def replace_bom(self):
self.validate_bom()
self.update_new_bom()
unit_cost = get_new_bom_unit_cost(self.new_bom)
self.update_new_bom(unit_cost)
frappe.cache().delete_key('bom_children')
bom_list = self.get_parent_boms(self.new_bom)
updated_bom = []
with click.progressbar(bom_list) as bom_list:
pass
for bom in bom_list:
@ -26,7 +29,9 @@ class BOMUpdateTool(Document):
# this is only used for versioning and we do not want
# to make separate db calls by using load_doc_before_save
# which proves to be expensive while doing bulk replace
bom_obj._doc_before_save = bom_obj.as_dict()
bom_obj._doc_before_save = bom_obj
bom_obj.update_new_bom(self.current_bom, self.new_bom, unit_cost)
bom_obj.update_exploded_items()
bom_obj.calculate_cost()
bom_obj.update_parent_cost()
bom_obj.db_update()
@ -43,14 +48,10 @@ class BOMUpdateTool(Document):
!= frappe.db.get_value("BOM", self.new_bom, "item"):
frappe.throw(_("The selected BOMs are not for the same item"))
def update_new_bom(self):
new_bom_unitcost = frappe.db.sql("""SELECT `total_cost`/`quantity`
FROM `tabBOM` WHERE name = %s""", self.new_bom)
new_bom_unitcost = flt(new_bom_unitcost[0][0]) if new_bom_unitcost else 0
def update_new_bom(self, unit_cost):
frappe.db.sql("""update `tabBOM Item` set bom_no=%s,
rate=%s, amount=stock_qty*%s where bom_no = %s and docstatus < 2 and parenttype='BOM'""",
(self.new_bom, new_bom_unitcost, new_bom_unitcost, self.current_bom))
(self.new_bom, unit_cost, unit_cost, self.current_bom))
def get_parent_boms(self, bom, bom_list=[]):
data = frappe.db.sql("""SELECT DISTINCT parent FROM `tabBOM Item`
@ -65,12 +66,18 @@ class BOMUpdateTool(Document):
return list(set(bom_list))
def get_new_bom_unit_cost(bom):
new_bom_unitcost = frappe.db.sql("""SELECT `total_cost`/`quantity`
FROM `tabBOM` WHERE name = %s""", bom)
return flt(new_bom_unitcost[0][0]) if new_bom_unitcost else 0
@frappe.whitelist()
def enqueue_replace_bom(args):
if isinstance(args, string_types):
args = json.loads(args)
frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.replace_bom", args=args, timeout=4000)
frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.replace_bom", args=args, timeout=40000)
frappe.msgprint(_("Queued for replacing the BOM. It may take a few minutes."))
@frappe.whitelist()

View File

@ -20,7 +20,7 @@ frappe.ui.form.on('Job Card', {
}
}
if (frm.doc.docstatus == 0 && frm.doc.for_quantity > frm.doc.total_completed_qty
if (frm.doc.docstatus == 0 && (frm.doc.for_quantity > frm.doc.total_completed_qty || !frm.doc.for_quantity)
&& (!frm.doc.items.length || frm.doc.for_quantity == frm.doc.transferred_qty)) {
frm.trigger("prepare_timer_buttons");
}
@ -59,10 +59,14 @@ frappe.ui.form.on('Job Card', {
let completed_time = frappe.datetime.now_datetime();
frm.trigger("hide_timer");
frappe.prompt({fieldtype: 'Float', label: __('Completed Quantity'),
fieldname: 'qty', reqd: 1, default: frm.doc.for_quantity}, data => {
frm.events.complete_job(frm, completed_time, data.qty);
}, __("Enter Value"), __("Complete"));
if (frm.doc.for_quantity) {
frappe.prompt({fieldtype: 'Float', label: __('Completed Quantity'),
fieldname: 'qty', reqd: 1, default: frm.doc.for_quantity}, data => {
frm.events.complete_job(frm, completed_time, data.qty);
}, __("Enter Value"), __("Complete"));
} else {
frm.events.complete_job(frm, completed_time, 0);
}
}).addClass("btn-primary");
}
},

View File

@ -99,8 +99,7 @@
"fieldname": "for_quantity",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Qty To Manufacture",
"reqd": 1
"label": "Qty To Manufacture"
},
{
"fieldname": "wip_warehouse",
@ -122,6 +121,7 @@
"options": "Employee"
},
{
"allow_bulk_edit": 1,
"fieldname": "time_logs",
"fieldtype": "Table",
"label": "Time Logs",
@ -290,7 +290,7 @@
}
],
"is_submittable": 1,
"modified": "2019-12-03 13:08:57.926201",
"modified": "2020-03-27 13:36:35.417502",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Job Card",

View File

@ -191,12 +191,9 @@ class JobCard(Document):
if not self.time_logs:
frappe.throw(_("Time logs are required for job card {0}").format(self.name))
if self.total_completed_qty <= 0.0:
frappe.throw(_("Total completed qty must be greater than zero"))
if self.total_completed_qty != self.for_quantity:
frappe.throw(_("The total completed qty({0}) must be equal to qty to manufacture({1})")
.format(frappe.bold(self.total_completed_qty),frappe.bold(self.for_quantity)))
if self.for_quantity and self.total_completed_qty != self.for_quantity:
frappe.throw(_("The total completed qty({0}) must be equal to qty to manufacture({1})"
.format(frappe.bold(self.total_completed_qty),frappe.bold(self.for_quantity))))
def update_work_order(self):
if not self.work_order:
@ -205,27 +202,34 @@ class JobCard(Document):
for_quantity, time_in_mins = 0, 0
from_time_list, to_time_list = [], []
for d in frappe.get_all('Job Card',
filters = {'docstatus': 1, 'operation_id': self.operation_id}):
doc = frappe.get_doc('Job Card', d.name)
for_quantity += doc.total_completed_qty
time_in_mins += doc.total_time_in_mins
for time_log in doc.time_logs:
if time_log.from_time:
from_time_list.append(time_log.from_time)
if time_log.to_time:
to_time_list.append(time_log.to_time)
data = frappe.get_all('Job Card',
fields = ["sum(total_time_in_mins) as time_in_mins", "sum(total_completed_qty) as completed_qty"],
filters = {"docstatus": 1, "work_order": self.work_order,
"workstation": self.workstation, "operation": self.operation})
if data and len(data) > 0:
for_quantity = data[0].completed_qty
time_in_mins = data[0].time_in_mins
if for_quantity:
time_data = frappe.db.sql("""
SELECT
min(from_time) as start_time, max(to_time) as end_time
FROM `tabJob Card` jc, `tabJob Card Time Log` jctl
WHERE
jctl.parent = jc.name and jc.work_order = %s
and jc.workstation = %s and jc.operation = %s and jc.docstatus = 1
""", (self.work_order, self.workstation, self.operation), as_dict=1)
wo = frappe.get_doc('Work Order', self.work_order)
for data in wo.operations:
if data.name == self.operation_id:
if data.workstation == self.workstation and data.operation == self.operation:
data.completed_qty = for_quantity
data.actual_operation_time = time_in_mins
data.actual_start_time = min(from_time_list) if from_time_list else None
data.actual_end_time = max(to_time_list) if to_time_list else None
data.actual_start_time = time_data[0].start_time if time_data else None
data.actual_end_time = time_data[0].end_time if time_data else None
wo.flags.ignore_validate_update_after_submit = True
wo.update_operation_status()

View File

@ -144,7 +144,7 @@ class ProductionPlan(Document):
item_condition = " and mr_item.item_code ={0}".format(frappe.db.escape(self.item_code))
items = frappe.db.sql("""select distinct parent, name, item_code, warehouse, description,
(qty - ordered_qty) as pending_qty
(qty - ordered_qty) * conversion_factor as pending_qty
from `tabMaterial Request Item` mr_item
where parent in (%s) and docstatus = 1 and qty > ordered_qty
and exists (select name from `tabBOM` bom where bom.item=mr_item.item_code

View File

@ -14,6 +14,7 @@ from erpnext.stock.utils import get_bin
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
class TestWorkOrder(unittest.TestCase):
def setUp(self):
@ -82,6 +83,37 @@ class TestWorkOrder(unittest.TestCase):
wo_order.set_work_order_operations()
self.assertEqual(wo_order.planned_operating_cost, cost*2)
def test_resered_qty_for_partial_completion(self):
item = "_Test Item"
warehouse = create_warehouse("Test Warehouse for reserved_qty - _TC")
bin1_at_start = get_bin(item, warehouse)
# reset to correct value
bin1_at_start.update_reserved_qty_for_production()
wo_order = make_wo_order_test_record(item="_Test FG Item", qty=2,
source_warehouse=warehouse, skip_transfer=1)
bin1_on_submit = get_bin(item, warehouse)
# reserved qty for production is updated
self.assertEqual(cint(bin1_at_start.reserved_qty_for_production) + 2,
cint(bin1_on_submit.reserved_qty_for_production))
test_stock_entry.make_stock_entry(item_code="_Test Item",
target=warehouse, qty=100, basic_rate=100)
test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100",
target=warehouse, qty=100, basic_rate=100)
s = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 1))
s.submit()
bin1_at_completion = get_bin(item, warehouse)
self.assertEqual(cint(bin1_at_completion.reserved_qty_for_production),
cint(bin1_on_submit.reserved_qty_for_production) - 1)
def test_production_item(self):
wo_order = make_wo_order_test_record(item="_Test FG Item", qty=1, do_not_save=True)
frappe.db.set_value("Item", "_Test FG Item", "end_of_life", "2000-1-1")
@ -404,7 +436,7 @@ def make_wo_order_test_record(**args):
wo_order.company = args.company or "_Test Company"
wo_order.stock_uom = args.stock_uom or "_Test UOM"
wo_order.use_multi_level_bom=0
wo_order.skip_transfer=1
wo_order.skip_transfer=args.skip_transfer or 0
wo_order.get_items_and_operations_from_bom()
wo_order.sales_order = args.sales_order or None
wo_order.planned_start_date = args.planned_start_date or now()

View File

@ -279,7 +279,7 @@ class WorkOrder(Document):
if enable_capacity_planning and job_card_doc:
row.planned_start_time = job_card_doc.time_logs[-1].from_time
row.planned_end_time = job_card_doc.time_logs[-1].to_time
print(row.planned_start_time, original_start_time, plan_days)
if date_diff(row.planned_start_time, original_start_time) > plan_days:
frappe.message_log.pop()
frappe.throw(_("Unable to find the time slot in the next {0} days for the operation {1}.")
@ -314,7 +314,7 @@ class WorkOrder(Document):
stock_entry = frappe.db.sql("""select name from `tabStock Entry`
where work_order = %s and docstatus = 1""", self.name)
if stock_entry:
frappe.throw(_("Cannot cancel because submitted Stock Entry {0} exists").format(stock_entry[0][0]))
frappe.throw(_("Cannot cancel because submitted Stock Entry {0} exists").format(frappe.utils.get_link_to_form('Stock Entry', stock_entry[0][0])))
def update_planned_qty(self):
update_bin_qty(self.production_item, self.fg_warehouse, {
@ -468,6 +468,9 @@ class WorkOrder(Document):
update bin reserved_qty_for_production
called from Stock Entry for production, after submit, cancel
'''
# calculate consumed qty based on submitted stock entries
self.update_consumed_qty_for_required_items()
if self.docstatus==1:
# calculate transferred qty based on submitted stock entries
self.update_transaferred_qty_for_required_items()
@ -475,9 +478,6 @@ class WorkOrder(Document):
# update in bin
self.update_reserved_qty_for_production()
# calculate consumed qty based on submitted stock entries
self.update_consumed_qty_for_required_items()
def update_reserved_qty_for_production(self, items=None):
'''update reserved_qty_for_production in bins'''
for d in self.required_items:
@ -552,24 +552,33 @@ class WorkOrder(Document):
d.db_set('transferred_qty', flt(transferred_qty), update_modified = False)
def update_consumed_qty_for_required_items(self):
'''update consumed qty from submitted stock entries for that item against
the work order'''
'''
Update consumed qty from submitted stock entries
against a work order for each stock item
'''
for d in self.required_items:
consumed_qty = frappe.db.sql('''select sum(qty)
from `tabStock Entry` entry, `tabStock Entry Detail` detail
where
for item in self.required_items:
consumed_qty = frappe.db.sql('''
SELECT
SUM(qty)
FROM
`tabStock Entry` entry,
`tabStock Entry Detail` detail
WHERE
entry.work_order = %(name)s
and (entry.purpose = "Material Consumption for Manufacture"
or entry.purpose = "Manufacture")
and entry.docstatus = 1
and detail.parent = entry.name
and (detail.item_code = %(item)s or detail.original_item = %(item)s)''', {
'name': self.name,
'item': d.item_code
})[0][0]
AND (entry.purpose = "Material Consumption for Manufacture"
OR entry.purpose = "Manufacture")
AND entry.docstatus = 1
AND detail.parent = entry.name
AND detail.s_warehouse IS NOT null
AND (detail.item_code = %(item)s
OR detail.original_item = %(item)s)
''', {
'name': self.name,
'item': item.item_code
})[0][0]
d.db_set('consumed_qty', flt(consumed_qty), update_modified = False)
item.db_set('consumed_qty', flt(consumed_qty), update_modified=False)
def make_bom(self):
data = frappe.db.sql(""" select sed.item_code, sed.qty, sed.s_warehouse
@ -648,7 +657,7 @@ def get_item_details(item, project = None):
return res
@frappe.whitelist()
def make_work_order(item, qty=0, project=None):
def make_work_order(bom_no, item, qty=0, project=None):
if not frappe.has_permission("Work Order", "write"):
frappe.throw(_("Not permitted"), frappe.PermissionError)
@ -657,6 +666,7 @@ def make_work_order(item, qty=0, project=None):
wo_doc = frappe.new_doc("Work Order")
wo_doc.production_item = item
wo_doc.update(item_details)
wo_doc.bom_no = bom_no
if flt(qty) > 0:
wo_doc.qty = flt(qty)

View File

@ -22,7 +22,14 @@ erpnext.BOMComparisonTool = class BOMComparisonTool {
fieldname: 'name1',
fieldtype: 'Link',
options: 'BOM',
change: () => this.fetch_and_render()
change: () => this.fetch_and_render(),
get_query: () => {
return {
filters: {
"name": ["not in", [this.form.get_value("name2") || ""]]
}
}
}
},
{
fieldtype: 'Column Break'
@ -32,7 +39,14 @@ erpnext.BOMComparisonTool = class BOMComparisonTool {
fieldname: 'name2',
fieldtype: 'Link',
options: 'BOM',
change: () => this.fetch_and_render()
change: () => this.fetch_and_render(),
get_query: () => {
return {
filters: {
"name": ["not in", [this.form.get_value("name1") || ""]]
}
}
}
},
{
fieldtype: 'Section Break'

View File

@ -581,7 +581,7 @@ erpnext.patches.v11_0.rename_bom_wo_fields
erpnext.patches.v12_0.set_default_homepage_type
erpnext.patches.v11_0.rename_additional_salary_component_additional_salary
erpnext.patches.v11_0.renamed_from_to_fields_in_project
erpnext.patches.v11_0.add_permissions_in_gst_settings
erpnext.patches.v11_0.add_permissions_in_gst_settings #2020-04-04
erpnext.patches.v11_1.setup_guardian_role
execute:frappe.delete_doc('DocType', 'Notification Control')
erpnext.patches.v12_0.set_gst_category
@ -626,10 +626,11 @@ erpnext.patches.v12_0.update_ewaybill_field_position
erpnext.patches.v12_0.create_accounting_dimensions_in_missing_doctypes
erpnext.patches.v11_1.set_status_for_material_request_type_manufacture
erpnext.patches.v12_0.move_plaid_settings_to_doctype
execute:frappe.reload_doc('desk', 'doctype','dashboard_chart_link')
execute:frappe.reload_doc('desk', 'doctype','dashboard')
execute:frappe.reload_doc('desk', 'doctype','dashboard_chart_source')
execute:frappe.reload_doc('desk', 'doctype','dashboard_chart')
execute:frappe.reload_doc('desk', 'doctype', 'dashboard_chart_link')
execute:frappe.reload_doc('desk', 'doctype', 'dashboard')
execute:frappe.reload_doc('desk', 'doctype', 'dashboard_chart_source')
execute:frappe.reload_doc('desk', 'doctype', 'dashboard_chart')
execute:frappe.reload_doc('desk', 'doctype', 'dashboard_chart_field')
erpnext.patches.v12_0.add_default_dashboards
erpnext.patches.v12_0.remove_bank_remittance_custom_fields
erpnext.patches.v12_0.generate_leave_ledger_entries
@ -658,4 +659,6 @@ erpnext.patches.v12_0.set_permission_einvoicing
erpnext.patches.v12_0.set_published_in_hub_tracked_item
erpnext.patches.v12_0.set_job_offer_applicant_email
erpnext.patches.v12_0.create_irs_1099_field_united_states
erpnext.patches.v12_0.move_bank_account_swift_number_to_bank
erpnext.patches.v12_0.rename_bank_reconciliation_fields # 2020-01-22
erpnext.patches.v12_0.set_received_qty_in_material_request_as_per_stock_uom

View File

@ -1,12 +1,9 @@
import frappe
from frappe.permissions import add_permission, update_permission_property
from erpnext.regional.india.setup import add_permissions
def execute():
company = frappe.get_all('Company', filters = {'country': 'India'})
if not company:
return
for doctype in ('GST HSN Code', 'GST Settings'):
add_permission(doctype, 'Accounts Manager', 0)
update_permission_property(doctype, 'Accounts Manager', 0, 'write', 1)
update_permission_property(doctype, 'Accounts Manager', 0, 'create', 1)
add_permissions()

View File

@ -0,0 +1,15 @@
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doc('accounts', 'doctype', 'bank', force=1)
if frappe.db.table_exists('Bank') and frappe.db.table_exists('Bank Account'):
frappe.db.sql("""
UPDATE `tabBank` b, `tabBank Account` ba
SET b.swift_number = ba.swift_number, b.branch_code = ba.branch_code
WHERE b.name = ba.bank
""")
frappe.reload_doc('accounts', 'doctype', 'bank_account')
frappe.reload_doc('accounts', 'doctype', 'payment_request')

View File

@ -0,0 +1,30 @@
from __future__ import unicode_literals
import frappe
def execute():
purchase_receipts = frappe.db.sql("""
SELECT
parent from `tabPurchase Receipt Item`
WHERE
material_request is not null
AND docstatus=1
""",as_dict=1)
purchase_receipts = set([d.parent for d in purchase_receipts])
for pr in purchase_receipts:
doc = frappe.get_doc("Purchase Receipt", pr)
doc.status_updater = [
{
'source_dt': 'Purchase Receipt Item',
'target_dt': 'Material Request Item',
'join_field': 'material_request_item',
'target_field': 'received_qty',
'target_parent_dt': 'Material Request',
'target_parent_field': 'per_received',
'target_ref_field': 'stock_qty',
'source_field': 'stock_qty',
'percent_join_field': 'material_request'
}
]
doc.update_qty()

View File

@ -18,7 +18,7 @@ frappe.ui.form.on("Project", {
};
},
onload: function (frm) {
var so = frappe.meta.get_docfield("Project", "sales_order");
var so = frm.get_docfield("Project", "sales_order");
so.get_route_options_for_new_doc = function (field) {
if (frm.is_new()) return;
return {
@ -135,4 +135,4 @@ function open_form(frm, doctype, child_doctype, parentfield) {
frappe.ui.form.make_quick_entry(doctype, null, null, new_doc);
});
}
}

View File

@ -1,4 +1,5 @@
{
"actions": [],
"allow_import": 1,
"autoname": "TASK-.YYYY.-.#####",
"creation": "2013-01-29 19:25:50",
@ -200,7 +201,6 @@
{
"fieldname": "description",
"fieldtype": "Text Editor",
"in_preview": 1,
"label": "Task Description",
"oldfieldname": "description",
"oldfieldtype": "Text Editor",
@ -361,11 +361,14 @@
],
"icon": "fa fa-check",
"idx": 1,
"is_tree": 1,
"links": [],
"max_attachments": 5,
"modified": "2019-09-10 13:46:24.631754",
"modified": "2020-03-18 18:08:44.153211",
"modified_by": "Administrator",
"module": "Projects",
"name": "Task",
"nsm_parent_field": "parent_task",
"owner": "Administrator",
"permissions": [
{

View File

@ -6,7 +6,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
apply_pricing_rule_on_item: function(item){
let effective_item_rate = item.price_list_rate;
if (item.parenttype === "Sales Order" && item.blanket_order_rate) {
if (in_list(["Sales Order", "Quotation"], item.parenttype) && item.blanket_order_rate) {
effective_item_rate = item.blanket_order_rate;
}
if(item.margin_type == "Percentage"){

View File

@ -4,7 +4,7 @@
erpnext.TransactionController = erpnext.taxes_and_totals.extend({
setup: function() {
this._super();
frappe.flags.hide_serial_batch_dialog = false;
frappe.flags.hide_serial_batch_dialog = true;
frappe.ui.form.on(this.frm.doctype + " Item", "rate", function(frm, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
var has_margin_field = frappe.meta.has_field(cdt, 'margin_type');
@ -165,6 +165,16 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
return (doc.rule_applied) ? "green" : "red";
});
}
let batch_no_field = this.frm.get_docfield("items", "batch_no");
if (batch_no_field) {
batch_no_field.get_route_options_for_new_doc = function(row) {
return {
"item": row.doc.item_code
}
};
}
},
onload: function() {
var me = this;
@ -352,12 +362,17 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
['serial_no', 'batch_no', 'barcode'].forEach(field => {
if (data[field] && frappe.meta.has_field(row_to_modify.doctype, field)) {
let value = (row_to_modify[field] && field === "serial_no")
? row_to_modify[field] + '\n' + data[field] : data[field];
frappe.model.set_value(row_to_modify.doctype,
row_to_modify.name, field, data[field]);
row_to_modify.name, field, value);
}
});
scan_barcode_field.set_value('');
refresh_field("items");
});
}
return false;
@ -519,6 +534,15 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
},
() => me.toggle_conversion_factor(item),
() => {
if (show_batch_dialog)
return frappe.db.get_value("Item", item.item_code, ["has_batch_no", "has_serial_no"])
.then((r) => {
if(r.message.has_batch_no || r.message.has_serial_no) {
frappe.flags.hide_serial_batch_dialog = false;
}
});
},
() => {
if(show_batch_dialog && !frappe.flags.hide_serial_batch_dialog) {
var d = locals[cdt][cdn];
@ -528,7 +552,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
erpnext.show_serial_batch_selector(me.frm, d, (item) => {
me.frm.script_manager.trigger('qty', item.doctype, item.name);
});
if (!me.frm.doc.set_warehouse)
me.frm.script_manager.trigger('warehouse', item.doctype, item.name);
}, undefined, !frappe.flags.hide_serial_batch_dialog);
}
},
() => me.conversion_factor(doc, cdt, cdn, true),

View File

@ -29,7 +29,7 @@ class Quiz {
this.questions.push(question)
this.wrapper.appendChild(question_wrapper);
})
if (data.activity.is_complete) {
if (data.activity && data.activity.is_complete) {
this.disable()
let indicator = 'red'
let message = 'Your are not allowed to attempt the quiz again.'

View File

@ -453,7 +453,8 @@ erpnext.utils.update_child_items = function(opts) {
fields: [{
fieldtype:'Data',
fieldname:"docname",
hidden: 0,
read_only: 1,
hidden: 1,
}, {
fieldtype:'Link',
fieldname:"item_code",

View File

@ -1,23 +1,25 @@
frappe.provide('frappe.ui.form');
erpnext.doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset",
let default_dimensions = {};
let doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset",
"Expense Claim", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note", "Shipping Rule", "Loyalty Program",
"Fee Schedule", "Fee Structure", "Stock Reconciliation", "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool",
"Subscription", "Purchase Order", "Journal Entry", "Material Request", "Purchase Receipt", "Landed Cost Item", "Asset"];
erpnext.child_docs = ["Sales Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account",
let child_docs = ["Sales Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account",
"Material Request Item", "Delivery Note Item", "Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction",
"Landed Cost Item", "Asset Value Adjustment", "Opening Invoice Creation Tool Item", "Subscription Plan"];
frappe.call({
method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimension_filters",
callback: function(r){
callback: function(r) {
erpnext.dimension_filters = r.message[0];
erpnext.default_dimensions = r.message[1];
default_dimensions = r.message[1];
}
});
erpnext.doctypes_with_dimensions.forEach((doctype) => {
doctypes_with_dimensions.forEach((doctype) => {
frappe.ui.form.on(doctype, {
onload: function(frm) {
erpnext.dimension_filters.forEach((dimension) => {
@ -27,41 +29,40 @@ erpnext.doctypes_with_dimensions.forEach((doctype) => {
"is_group": 0
});
}
if (Object.keys(erpnext.default_dimensions).length > 0) {
if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
if (frm.is_new() && frappe.meta.has_field(doctype, 'company') && frm.doc.company) {
frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
}
}
if (frm.doc.items && frm.doc.items.length && frm.doc.docstatus === 0
&& (!frm.doc.items[0][dimension['fieldname']])) {
frm.doc.items[0][dimension['fieldname']] = erpnext.default_dimensions[frm.doc.company][dimension['document_type']];
}
if (frm.doc.accounts && frm.doc.accounts.length && frm.doc.docstatus === 0
&& (!frm.doc.items[0][dimension['fieldname']])) {
frm.doc.accounts[0][dimension['fieldname']] = erpnext.default_dimensions[frm.doc.company][dimension['document_type']];
}
}
});
});
},
company: function(frm) {
if(frm.doc.company && (Object.keys(erpnext.default_dimensions).length > 0)) {
erpnext.dimension_filters.forEach((dimension) => {
if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
}
});
if(frm.doc.company && (Object.keys(default_dimensions || {}).length > 0)
&& default_dimensions[frm.doc.company]) {
frm.trigger('update_dimension');
}
},
update_dimension: function(frm) {
erpnext.dimension_filters.forEach((dimension) => {
if (frm.is_new()) {
if (frm.doc.company && Object.keys(default_dimensions || {}).length > 0
&& default_dimensions[frm.doc.company]) {
if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
frm.set_value(dimension['fieldname'],
default_dimensions[frm.doc.company][dimension['document_type']]);
}
$.each(frm.doc.items || frm.doc.accounts || [], function(i, row) {
frappe.model.set_value(row.doctype, row.name, dimension['fieldname'],
default_dimensions[frm.doc.company][dimension['document_type']])
});
}
}
});
}
});
});
erpnext.child_docs.forEach((doctype) => {
child_docs.forEach((doctype) => {
frappe.ui.form.on(doctype, {
items_add: function(frm, cdt, cdn) {
erpnext.dimension_filters.forEach((dimension) => {
@ -77,14 +78,6 @@ erpnext.child_docs.forEach((doctype) => {
});
},
company: function(frm) {
if(frm.doc.company) {
erpnext.dimension_filters.forEach((dimension) => {
frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
});
}
},
items_add: function(frm, cdt, cdn) {
erpnext.dimension_filters.forEach((dimension) => {
var row = frappe.get_doc(cdt, cdn);

Some files were not shown because too many files have changed in this diff Show More