Merge branch 'develop' into healthcare_refactor

This commit is contained in:
Nabin Hait 2020-03-31 15:59:22 +05:30 committed by GitHub
commit 95330c850c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 785 additions and 698 deletions

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

@ -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

@ -2433,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",
@ -2578,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,
@ -2629,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,
@ -2646,41 +2637,35 @@
"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"
}
}
},
@ -2718,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"
},
@ -2864,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"
@ -3022,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

@ -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

@ -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

@ -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

@ -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

@ -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:

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

@ -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}
@ -362,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

@ -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

@ -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

@ -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

View File

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

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

@ -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

@ -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 = []

View File

@ -135,6 +135,7 @@ frappe.ui.form.on("BOM", {
frappe.call({
method: "erpnext.manufacturing.doctype.work_order.work_order.make_work_order",
args: {
bom_no: frm.doc.name,
item: frm.doc.item,
qty: data.qty || 0.0,
project: frm.doc.project

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

@ -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, {
@ -648,7 +648,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 +657,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

@ -658,4 +658,5 @@ 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

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

@ -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

@ -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

@ -5,14 +5,13 @@ erpnext.SerialNoBatchSelector = Class.extend({
this.show_dialog = show_dialog;
// frm, item, warehouse_details, has_batch, oldest
let d = this.item;
if (d && d.has_batch_no && (!d.batch_no || this.show_dialog)) {
this.has_batch = 1;
this.setup();
this.has_batch = 0; this.has_serial_no = 0;
if (d && d.has_batch_no && (!d.batch_no || this.show_dialog)) this.has_batch = 1;
// !(this.show_dialog == false) ensures that show_dialog is implictly true, even when undefined
} else if(d && d.has_serial_no && !(this.show_dialog == false)) {
this.has_batch = 0;
this.setup();
}
if(d && d.has_serial_no && !(this.show_dialog == false)) this.has_serial_no = 1;
this.setup();
},
setup: function() {
@ -36,16 +35,16 @@ erpnext.SerialNoBatchSelector = Class.extend({
label: __('Item Code'),
default: me.item_code
},
{fieldtype:'Column Break'},
{
fieldname: 'warehouse',
fieldtype:'Link',
options: 'Warehouse',
reqd: me.has_batch && !me.has_serial_no ? 0 : 1,
label: __(me.warehouse_details.type),
default: me.warehouse_details.name,
default: typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : '',
onchange: function(e) {
if(me.has_batch) {
if(me.has_batch && !me.has_serial_no) {
fields = fields.concat(me.get_batch_fields());
} else {
fields = fields.concat(me.get_serial_no_fields());
@ -74,15 +73,16 @@ erpnext.SerialNoBatchSelector = Class.extend({
{
fieldname: 'qty',
fieldtype:'Float',
read_only: me.has_batch,
label: __(me.has_batch ? 'Total Qty' : 'Qty'),
read_only: me.has_batch && !me.has_serial_no,
label: __(me.has_batch && !me.has_serial_no ? 'Total Qty' : 'Qty'),
default: 0
},
{
fieldname: 'auto_fetch_button',
fieldtype:'Button',
hidden: me.has_batch,
label: __('Fetch based on FIFO'),
hidden: me.has_batch && !me.has_serial_no,
label: __('Auto Fetch'),
description: __('Fetch Serial Numbers based on FIFO'),
click: () => {
let qty = this.dialog.fields_dict.qty.get_value();
let numbers = frappe.call({
@ -90,7 +90,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
args: {
qty: qty,
item_code: me.item_code,
warehouse: me.warehouse_details.name,
warehouse: typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : '',
batch_no: me.item.batch_no || null
}
});
@ -109,10 +109,12 @@ erpnext.SerialNoBatchSelector = Class.extend({
}
];
if (this.has_batch) {
if (this.has_batch && !this.has_serial_no) {
title = __("Select Batch Numbers");
fields = fields.concat(this.get_batch_fields());
} else {
// if only serial no OR
// if both batch_no & serial_no then only select serial_no and auto set batches nos
title = __("Select Serial Numbers");
fields = fields.concat(this.get_serial_no_fields());
}
@ -122,25 +124,31 @@ erpnext.SerialNoBatchSelector = Class.extend({
fields: fields
});
if (this.item.serial_no) {
this.dialog.fields_dict.serial_no.set_value(this.item.serial_no);
}
this.dialog.set_primary_action(__('Insert'), function() {
me.values = me.dialog.get_values();
if(me.validate()) {
me.set_items();
me.dialog.hide();
frappe.run_serially([
() => me.update_batch_items(),
() => me.update_serial_no_item(),
() => me.update_batch_serial_no_items(),
() => {
refresh_field("items");
if (me.callback) {
return me.callback(me.item);
}
},
() => me.dialog.hide()
])
}
});
if(this.show_dialog) {
let d = this.item;
if (d.has_serial_no && d.serial_no) {
this.dialog.set_value('serial_no', d.serial_no);
if (this.item.serial_no) {
this.dialog.fields_dict.serial_no.set_value(this.item.serial_no);
}
if (d.has_batch_no && d.batch_no) {
if (this.has_batch && !this.has_serial_no && d.batch_no) {
this.frm.doc.items.forEach(data => {
if(data.item_code == d.item_code) {
this.dialog.fields_dict.batches.df.data.push({
@ -155,7 +163,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
}
}
if (this.has_batch) {
if (this.has_batch && !this.has_serial_no) {
this.update_total_qty();
}
@ -174,7 +182,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
frappe.throw(__("Please select a warehouse"));
return false;
}
if(this.has_batch) {
if(this.has_batch && !this.has_serial_no) {
if(values.batches.length === 0 || !values.batches) {
frappe.throw(__("Please select batches for batched item "
+ values.item_code));
@ -193,34 +201,23 @@ erpnext.SerialNoBatchSelector = Class.extend({
} else {
let serial_nos = values.serial_no || '';
if (!serial_nos || !serial_nos.replace(/\s/g, '').length) {
if (!this.show_dialog) {
frappe.throw(__("Please enter serial numbers for serialized item "
+ values.item_code));
return false;
}
frappe.throw(__("Please enter serial numbers for serialized item "
+ values.item_code));
return false;
}
return true;
}
},
set_items: function() {
var me = this;
if(this.has_batch) {
update_batch_items() {
// clones an items if muliple batches are selected.
if(this.has_batch && !this.has_serial_no) {
this.values.batches.map((batch, i) => {
let batch_no = batch.batch_no;
let row = '';
if (i !== 0 && !this.batch_exists(batch_no)) {
row = this.frm.add_child("items", {
'item_code': this.item.item_code,
'item_name': this.item.item_name,
'price_list_rate': this.item.price_list_rate,
'rate': this.item.rate,
'qty': batch.selected_qty,
'batch_no': batch_no,
'actual_qty': this.item.actual_qty,
'discount_percentage': this.item.discount_percentage
});
row = this.frm.add_child("items", { ...this.item });
} else {
row = this.frm.doc.items.find(i => i.batch_no === batch_no);
}
@ -228,16 +225,59 @@ erpnext.SerialNoBatchSelector = Class.extend({
if (!row) {
row = this.item;
}
// this ensures that qty & batch no is set
this.map_row_values(row, batch, 'batch_no',
'selected_qty', this.values.warehouse);
});
} else {
}
},
update_serial_no_item() {
// just updates serial no for the item
if(this.has_serial_no && !this.has_batch) {
this.map_row_values(this.item, this.values, 'serial_no', 'qty');
}
},
refresh_field("items");
this.callback && this.callback(this.item);
update_batch_serial_no_items() {
// if serial no selected is from different batches, adds new rows for each batch.
if(this.has_batch && this.has_serial_no) {
const selected_serial_nos = this.values.serial_no.split(/\n/g).filter(s => s);
return frappe.db.get_list("Serial No", {
filters: { 'name': ["in", selected_serial_nos]},
fields: ["batch_no", "name"]
}).then((data) => {
// data = [{batch_no: 'batch-1', name: "SR-001"},
// {batch_no: 'batch-2', name: "SR-003"}, {batch_no: 'batch-2', name: "SR-004"}]
const batch_serial_map = data.reduce((acc, d) => {
if (!acc[d['batch_no']]) acc[d['batch_no']] = [];
acc[d['batch_no']].push(d['name'])
return acc
}, {})
// batch_serial_map = { "batch-1": ['SR-001'], "batch-2": ["SR-003", "SR-004"]}
Object.keys(batch_serial_map).map((batch_no, i) => {
let row = '';
const serial_no = batch_serial_map[batch_no];
if (i == 0) {
row = this.item;
this.map_row_values(row, {qty: serial_no.length, batch_no: batch_no}, 'batch_no',
'qty', this.values.warehouse);
} else if (!this.batch_exists(batch_no)) {
row = this.frm.add_child("items", { ...this.item });
row.batch_no = batch_no;
} else {
row = this.frm.doc.items.find(i => i.batch_no === batch_no);
}
const values = {
'qty': serial_no.length,
'serial_no': serial_no.join('\n')
}
this.map_row_values(row, values, 'serial_no',
'qty', this.values.warehouse);
});
})
}
},
batch_exists: function(batch) {
@ -287,7 +327,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
return {
filters: {
item_code: me.item_code,
warehouse: me.warehouse || me.warehouse_details.name
warehouse: me.warehouse || typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : ''
},
query: 'erpnext.controllers.queries.get_batch_no'
};
@ -448,7 +488,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
{
fieldname: 'serial_no',
fieldtype: 'Small Text',
label: __(me.has_batch ? 'Selected Batch Numbers' : 'Selected Serial Numbers'),
label: __(me.has_batch && !me.has_serial_no ? 'Selected Batch Numbers' : 'Selected Serial Numbers'),
onchange: function() {
me.serial_list = this.get_value()
.replace(/\n/g, ' ').match(/\S+/g) || [];

View File

@ -21,6 +21,12 @@ frappe.query_reports["DATEV"] = {
"default": frappe.datetime.now_date(),
"fieldtype": "Date",
"reqd": 1
},
{
"fieldname": "voucher_type",
"label": __("Voucher Type"),
"fieldtype": "Select",
"options": "\nSales Invoice\nPurchase Invoice\nPayment Entry\nExpense Claim\nPayroll Entry\nBank Reconciliation\nAsset\nStock Entry"
}
],
onload: function(query_report) {

View File

@ -62,6 +62,7 @@ def get_transactions(filters, as_dict=1):
filters -- dict of filters to be passed to the sql query
as_dict -- return as list of dicts [0,1]
"""
filter_by_voucher = 'AND gl.voucher_type = %(voucher_type)s' if filters.get('voucher_type') else ''
gl_entries = frappe.db.sql("""
SELECT
@ -80,8 +81,10 @@ def get_transactions(filters, as_dict=1):
gl.posting_date as 'Belegdatum',
gl.voucher_no as 'Belegfeld 1',
gl.remarks as 'Buchungstext',
gl.against_voucher_type as 'Beleginfo - Art 1',
gl.against_voucher as 'Beleginfo - Inhalt 1'
gl.voucher_type as 'Beleginfo - Art 1',
gl.voucher_no as 'Beleginfo - Inhalt 1',
gl.against_voucher_type as 'Beleginfo - Art 2',
gl.against_voucher as 'Beleginfo - Inhalt 2'
FROM `tabGL Entry` gl
@ -109,7 +112,8 @@ def get_transactions(filters, as_dict=1):
WHERE gl.company = %(company)s
AND DATE(gl.posting_date) >= %(from_date)s
AND DATE(gl.posting_date) <= %(to_date)s
ORDER BY 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict, as_utf8=1)
{}
ORDER BY 'Belegdatum', gl.voucher_no""".format(filter_by_voucher), filters, as_dict=as_dict)
return gl_entries
@ -160,7 +164,7 @@ def get_customers(filters):
and ccl.company = par.company
WHERE par.company = %(company)s
AND par.parenttype = 'Customer'""", filters, as_dict=1, as_utf8=1)
AND par.parenttype = 'Customer'""", filters, as_dict=1)
def get_suppliers(filters):
@ -217,7 +221,7 @@ def get_suppliers(filters):
and con.is_primary_contact = '1'
WHERE par.company = %(company)s
AND par.parenttype = 'Supplier'""", filters, as_dict=1, as_utf8=1)
AND par.parenttype = 'Supplier'""", filters, as_dict=1)
def get_account_names(filters):
@ -281,24 +285,24 @@ def get_datev_csv(data, filters, csv_class):
def get_header(filters, csv_class):
coa = frappe.get_value("Company", filters.get("company"), "chart_of_accounts")
coa_used = "SKR04" if "SKR04" in coa else ("SKR03" if "SKR03" in coa else "")
coa_used = "04" if "SKR04" in coa else ("03" if "SKR03" in coa else "")
header = [
# DATEV format
# "DTVF" = created by DATEV software,
# "EXTF" = created by other software
# "DTVF" = created by DATEV software,
# "EXTF" = created by other software
'"EXTF"',
# version of the DATEV format
# 141 = 1.41,
# 510 = 5.10,
# 720 = 7.20
# 141 = 1.41,
# 510 = 5.10,
# 720 = 7.20
'700',
csv_class.DATA_CATEGORY,
'"%s"' % csv_class.FORMAT_NAME,
# Format version (regarding format name)
csv_class.FORMAT_VERSION,
# Generated on
datetime.datetime.now().strftime("%Y%m%d%H%M%S"),
datetime.datetime.now().strftime("%Y%m%d%H%M%S") + '000',
# Imported on -- stays empty
'',
# Origin. Any two symbols, will be replaced by "SV" on import.
@ -328,13 +332,21 @@ def get_header(filters, csv_class):
# R = Diktatkürzel
'',
# S = Buchungstyp
# 1 = Transaction batch (Finanzbuchführung),
# 2 = Annual financial statement (Jahresabschluss)
# 1 = Transaction batch (Finanzbuchführung),
# 2 = Annual financial statement (Jahresabschluss)
'1' if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
# T = Rechnungslegungszweck
'',
# 0 oder leer = vom Rechnungslegungszweck unabhängig
# 50 = Handelsrecht
# 30 = Steuerrecht
# 64 = IFRS
# 40 = Kalkulatorik
# 11 = Reserviert
# 12 = Reserviert
'0',
# U = Festschreibung
'',
# TODO: Filter by Accounting Period. In export for closed Accounting Period, this will be "1"
'0',
# V = Default currency, for example, "EUR"
'"%s"' % frappe.get_value("Company", filters.get("company"), "default_currency"),
# reserviert

View File

@ -498,13 +498,27 @@ QUERY_REPORT_COLUMNS = [
},
{
"label": "Beleginfo - Art 1",
"fieldname": "Beleginfo - Art 2",
"fieldtype": "Data",
"fieldname": "Beleginfo - Art 1",
"fieldtype": "Link",
"options": "DocType"
},
{
"label": "Beleginfo - Inhalt 1",
"fieldname": "Beleginfo - Inhalt 1",
"fieldtype": "Dynamic Link",
"options": "Beleginfo - Art 1"
},
{
"label": "Beleginfo - Art 2",
"fieldname": "Beleginfo - Art 2",
"fieldtype": "Link",
"options": "DocType"
},
{
"label": "Beleginfo - Inhalt 2",
"fieldname": "Beleginfo - Inhalt 2",
"fieldtype": "Data",
"fieldtype": "Dynamic Link",
"options": "Beleginfo - Art 2"
}
]

View File

@ -54,8 +54,8 @@ class Gstr1Report(object):
return self.columns, self.data
def get_data(self):
if self.filters.get("type_of_business") == "B2C Small":
self.get_b2cs_data()
if self.filters.get("type_of_business") in ("B2C Small", "B2C Large"):
self.get_b2c_data()
else:
for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
invoice_details = self.invoices.get(inv)
@ -69,7 +69,7 @@ class Gstr1Report(object):
if taxable_value:
self.data.append(row)
def get_b2cs_data(self):
def get_b2c_data(self):
b2cs_output = {}
for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
@ -84,7 +84,10 @@ class Gstr1Report(object):
"rate": "",
"taxable_value": 0,
"cess_amount": 0,
"type": ""
"type": "",
"invoice_number": invoice_details.get("invoice_number"),
"posting_date": invoice_details.get("posting_date"),
"invoice_value": invoice_details.get("base_grand_total"),
})
row = b2cs_output.get((rate, place_of_supply, ecommerce_gstin))
@ -164,7 +167,7 @@ class Gstr1Report(object):
frappe.throw(_("Please set B2C Limit in GST Settings."))
if self.filters.get("type_of_business") == "B2C Large":
conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2)
conditions += """ and ifnull(SUBSTR(place_of_supply, 1, 2),'') != ifnull(SUBSTR(company_gstin, 1, 2),'')
and grand_total > {0} and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit))
elif self.filters.get("type_of_business") == "B2C Small":
@ -581,6 +584,11 @@ def get_b2b_json(res, gstin):
if not gst_in: continue
for number, invoice in iteritems(res[gst_in]):
if not invoice[0]["place_of_supply"]:
frappe.throw(_("""{0} not entered in Invoice {1}.
Please update and try again""").format(frappe.bold("Place Of Supply"),
frappe.bold(invoice[0]['invoice_number'])))
inv_item = get_basic_invoice_detail(invoice[0])
inv_item["pos"] = "%02d" % int(invoice[0]["place_of_supply"].split('-')[0])
inv_item["rchrg"] = invoice[0]["reverse_charge"]
@ -606,6 +614,9 @@ def get_b2cs_json(data, gstin):
out = []
for d in data:
if not d.get("place_of_supply"):
frappe.throw(_("""{0} not entered in some invoices.
Please update and try again""").format(frappe.bold("Place Of Supply")))
pos = d.get('place_of_supply').split('-')[0]
tax_details = {}
@ -642,6 +653,10 @@ def get_b2cs_json(data, gstin):
def get_b2cl_json(res, gstin):
out = []
for pos in res:
if not pos:
frappe.throw(_("""{0} not entered in some invoices.
Please update and try again""").format(frappe.bold("Place Of Supply")))
b2cl_item, inv = {"pos": "%02d" % int(pos.split('-')[0]), "inv": []}, []
for row in res[pos]:

View File

@ -268,9 +268,11 @@ def make_quotation(source_name, target_doc=None):
target_doc.run_method("set_other_charges")
target_doc.run_method("calculate_taxes_and_totals")
price_list = frappe.get_value("Customer", source_name, 'default_price_list')
price_list, currency = frappe.db.get_value("Customer", {'name': source_name}, ['default_price_list', 'default_currency'])
if price_list:
target_doc.selling_price_list = price_list
if currency:
target_doc.currency = currency
return target_doc

View File

@ -664,7 +664,8 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.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

@ -121,8 +121,8 @@ def get_columns(filters):
},
{
"label": _("Billed Amount"),
"fieldname": "rate",
"options": "billed_amount",
"fieldtype": "currency",
"fieldname": "billed_amount",
"width": 120
},
{

View File

@ -413,15 +413,20 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
*/
set_batch_number: function(cdt, cdn) {
const doc = frappe.get_doc(cdt, cdn);
if (doc && doc.has_batch_no) {
if (doc && doc.has_batch_no && doc.warehouse) {
this._set_batch_number(doc);
}
},
_set_batch_number: function(doc) {
let args = {'item_code': doc.item_code, 'warehouse': doc.warehouse, 'qty': flt(doc.qty) * flt(doc.conversion_factor)};
if (doc.has_serial_no && doc.serial_no) {
args['serial_no'] = doc.serial_no
}
return frappe.call({
method: 'erpnext.stock.doctype.batch.batch.get_batch_no',
args: {'item_code': doc.item_code, 'warehouse': doc.warehouse, 'qty': flt(doc.qty) * flt(doc.conversion_factor)},
args: args,
callback: function(r) {
if(r.message) {
frappe.model.set_value(doc.doctype, doc.name, 'batch_no', r.message);

View File

@ -41,8 +41,7 @@
"charts": [
{
"chart_name": "Bank Balance",
"label": "All Your Money",
"size": "Full"
"label": "Bank Balance"
}
],
"creation": "2020-01-23 13:46:38.833076",
@ -55,7 +54,7 @@
"idx": 0,
"is_standard": 1,
"label": "Getting Started",
"modified": "2020-03-12 16:30:37.821762",
"modified": "2020-03-23 11:20:49.161823",
"modified_by": "Administrator",
"module": "Setup",
"name": "Getting Started",
@ -82,6 +81,16 @@
"is_query_report": 0,
"link_to": "Sales Invoice",
"type": "DocType"
},
{
"is_query_report": 0,
"link_to": "dashboard",
"type": "Page"
},
{
"is_query_report": 0,
"link_to": "leaderboard",
"type": "Page"
}
]
}

View File

@ -157,6 +157,7 @@
{
"fieldname": "parent_company",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"in_list_view": 1,
"label": "Parent Company",
"options": "Company"
@ -277,6 +278,7 @@
"depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Existing Company\"",
"fieldname": "existing_company",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Existing Company ",
"no_copy": 1,
"options": "Company"
@ -728,7 +730,7 @@
"image_field": "company_logo",
"is_tree": 1,
"links": [],
"modified": "2020-03-18 18:09:53.534211",
"modified": "2020-03-21 18:09:53.534211",
"modified_by": "Administrator",
"module": "Setup",
"name": "Company",

View File

@ -13,12 +13,16 @@ install_docs = [
]
def get_warehouse_account_map(company=None):
if not frappe.flags.warehouse_account_map or frappe.flags.in_test:
company_warehouse_account_map = company and frappe.flags.setdefault('warehouse_account_map', {}).get(company)
warehouse_account_map = frappe.flags.warehouse_account_map
if not warehouse_account_map or not company_warehouse_account_map or frappe.flags.in_test:
warehouse_account = frappe._dict()
filters = {}
if company:
filters['company'] = company
frappe.flags.setdefault('warehouse_account_map', {}).setdefault(company, {})
for d in frappe.get_all('Warehouse',
fields = ["name", "account", "parent_warehouse", "company", "is_group"],
@ -30,10 +34,12 @@ def get_warehouse_account_map(company=None):
if d.account:
d.account_currency = frappe.db.get_value('Account', d.account, 'account_currency', cache=True)
warehouse_account.setdefault(d.name, d)
frappe.flags.warehouse_account_map = warehouse_account
return frappe.flags.warehouse_account_map
if company:
frappe.flags.warehouse_account_map[company] = warehouse_account
else:
frappe.flags.warehouse_account_map = warehouse_account
return frappe.flags.warehouse_account_map.get(company) or frappe.flags.warehouse_account_map
def get_warehouse_account(warehouse, warehouse_account=None):
account = warehouse.account

View File

@ -122,8 +122,11 @@ class Batch(Document):
self.expiry_date = add_days(self.manufacturing_date, shelf_life_in_days)
if has_expiry_date and not self.expiry_date:
frappe.msgprint(_('Expiry date is mandatory for selected item.'))
frappe.throw(_("Set item's shelf life in days, to set expiry based on manufacturing date plus shelf-life."))
frappe.throw(msg=_("Please set {0} for Batched Item {1}, which is used to set {2} on Submit.") \
.format(frappe.bold("Shelf Life in Days"),
frappe.utils.get_link_to_form("Item", self.item),
frappe.bold("Batch Expiry Date")),
title=_("Expiry Date Mandatory"))
def get_name_from_naming_series(self):
"""

View File

@ -343,7 +343,8 @@
{
"fieldname": "shelf_life_in_days",
"fieldtype": "Int",
"label": "Shelf Life In Days"
"label": "Shelf Life In Days",
"mandatory_depends_on": "eval:doc.has_batch_no && doc.has_expiry_date"
},
{
"default": "2099-12-31",
@ -1045,7 +1046,7 @@
"image_field": "image",
"links": [],
"max_attachments": 1,
"modified": "2020-01-02 19:13:59.295963",
"modified": "2020-03-24 16:14:36.950677",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",

View File

@ -741,14 +741,12 @@ class Item(WebsiteGenerator):
defaults = frappe.defaults.get_defaults() or {}
# To check default warehouse is belong to the default company
if defaults.get("default_warehouse") and frappe.db.exists("Warehouse",
if defaults.get("default_warehouse") and defaults.company and frappe.db.exists("Warehouse",
{'name': defaults.default_warehouse, 'company': defaults.company}):
warehouse = defaults.default_warehouse
self.append("item_defaults", {
"company": defaults.get("company"),
"default_warehouse": warehouse
})
self.append("item_defaults", {
"company": defaults.get("company"),
"default_warehouse": defaults.default_warehouse
})
def update_variants(self):
if self.flags.dont_update_variants or \

View File

@ -8,6 +8,7 @@ from frappe.utils import flt
from frappe.model.meta import get_field_precision
from frappe.model.document import Document
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
from erpnext.accounts.doctype.account.account import get_account_currency
class LandedCostVoucher(Document):
def get_items_from_purchase_receipts(self):
@ -43,6 +44,7 @@ class LandedCostVoucher(Document):
else:
self.validate_applicable_charges_for_item()
self.validate_purchase_receipts()
self.validate_expense_accounts()
self.set_total_taxes_and_charges()
def check_mandatory(self):
@ -71,6 +73,14 @@ class LandedCostVoucher(Document):
frappe.throw(_("Row {0}: Cost center is required for an item {1}")
.format(item.idx, item.item_code))
def validate_expense_accounts(self):
company_currency = erpnext.get_company_currency(self.company)
for account in self.taxes:
if get_account_currency(account.expense_account) != company_currency:
frappe.throw(msg=_(""" Row {0}: Expense account currency should be same as company's default currency.
Please select expense account with account currency as {1}""")
.format(account.idx, frappe.bold(company_currency)), title=_("Invalid Account Currency"))
def set_total_taxes_and_charges(self):
self.total_taxes_and_charges = sum([flt(d.amount) for d in self.get("taxes")])

View File

@ -523,12 +523,15 @@ def get_delivery_note_serial_no(item_code, qty, delivery_note):
return serial_nos
@frappe.whitelist()
def auto_fetch_serial_number(qty, item_code, warehouse, batch_no=None):
serial_numbers = frappe.get_list("Serial No", filters={
def auto_fetch_serial_number(qty, item_code, warehouse, batch_nos=None):
import json
filters = {
"item_code": item_code,
"warehouse": warehouse,
"batch_no": batch_no,
"delivery_document_no": "",
"sales_invoice": ""
}, limit=qty, order_by="creation")
}
if batch_nos: filters["batch_no"] = ["in", json.loads(batch_nos)]
serial_numbers = frappe.get_list("Serial No", filters=filters, limit=qty, order_by="creation")
return [item['name'] for item in serial_numbers]

View File

@ -310,12 +310,12 @@ frappe.ui.form.on('Stock Entry', {
method: "erpnext.stock.get_item_details.get_serial_no",
args: {"args": args},
callback: function(r) {
if (!r.exe){
if (!r.exe && r.message){
frappe.model.set_value(cdt, cdn, "serial_no", r.message);
}
if (callback) {
callback();
if (callback) {
callback();
}
}
}
});
@ -623,10 +623,15 @@ frappe.ui.form.on('Stock Entry Detail', {
if(r.message) {
var d = locals[cdt][cdn];
$.each(r.message, function(k, v) {
frappe.model.set_value(cdt, cdn, k, v); // qty and it's subsequent fields weren't triggered
if (v) {
frappe.model.set_value(cdt, cdn, k, v); // qty and it's subsequent fields weren't triggered
}
});
refresh_field("items");
erpnext.stock.select_batch_and_serial_no(frm, d);
if (!d.serial_no) {
erpnext.stock.select_batch_and_serial_no(frm, d);
}
}
}
});

View File

@ -298,13 +298,8 @@ class StockEntry(StockController):
if validate_for_manufacture:
if d.bom_no:
d.s_warehouse = None
if not d.t_warehouse:
frappe.throw(_("Target warehouse is mandatory for row {0}").format(d.idx))
elif self.pro_doc and (cstr(d.t_warehouse) != self.pro_doc.fg_warehouse and cstr(d.t_warehouse) != self.pro_doc.scrap_warehouse):
frappe.throw(_("Target warehouse in row {0} must be same as Work Order").format(d.idx))
else:
d.t_warehouse = None
if not d.s_warehouse:

View File

@ -1,4 +1,5 @@
{
"actions": [],
"autoname": "hash",
"creation": "2013-03-29 18:22:12",
"doctype": "DocType",
@ -479,8 +480,7 @@
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project",
"read_only": 1
"options": "Project"
},
{
"fieldname": "po_detail",
@ -494,7 +494,8 @@
],
"idx": 1,
"istable": 1,
"modified": "2019-08-20 14:01:02.319754",
"links": [],
"modified": "2020-03-19 12:34:09.836295",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry Detail",

View File

@ -29,7 +29,13 @@ frappe.query_reports["Stock Ledger"] = {
"fieldname":"warehouse",
"label": __("Warehouse"),
"fieldtype": "Link",
"options": "Warehouse"
"options": "Warehouse",
"get_query": function() {
const company = frappe.query_report.get_filter_value('company');
return {
filters: { 'company': company }
}
}
},
{
"fieldname":"item_code",

View File

@ -18,7 +18,7 @@
"is_standard": 1,
"login_required": 1,
"max_attachment_size": 0,
"modified": "2019-12-10 13:48:19.894186",
"modified": "2020-03-06 05:24:05.749664",
"modified_by": "Administrator",
"module": "Support",
"name": "issues",
@ -58,7 +58,7 @@
"options": "Open\nReplied\nHold\nClosed",
"read_only": 1,
"reqd": 0,
"show_in_filter": 0
"show_in_filter": 1
},
{
"allow_read_on_all_link_options": 0,

View File

@ -7,6 +7,8 @@ import frappe
def create_test_contact_and_address():
frappe.db.sql('delete from tabContact')
frappe.db.sql('delete from `tabContact Email`')
frappe.db.sql('delete from `tabContact Phone`')
frappe.db.sql('delete from tabAddress')
frappe.db.sql('delete from `tabDynamic Link`')

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe
import frappe.share
from frappe import _
from frappe.utils import cstr, now_datetime, cint, flt, get_time
from frappe.utils import cstr, now_datetime, cint, flt, get_time, get_link_to_form
from erpnext.controllers.status_updater import StatusUpdater
from six import string_types
@ -123,8 +123,11 @@ class TransactionBase(StatusUpdater):
ref_rate = frappe.db.get_value(ref_dt + " Item", d.get(ref_link_field), "rate")
if abs(flt(d.rate - ref_rate, d.precision("rate"))) >= .01:
frappe.throw(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4}) ")
frappe.msgprint(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4}) ")
.format(d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate))
frappe.throw(_("To allow different rates, disable the {0} checkbox in {1}.")
.format(frappe.bold("Maintain Same Rate Throughout Sales Cycle"),
get_link_to_form("Selling Settings", "Selling Settings", frappe.bold("Selling Settings"))))
def get_link_filters(self, for_doctype):
if hasattr(self, "prev_link_mapper") and self.prev_link_mapper.get(for_doctype):