From 7021402a45c5e7dcc20ba7421150ce3172d1fdc1 Mon Sep 17 00:00:00 2001 From: "hello@openetech.com" Date: Wed, 16 Oct 2019 23:38:51 +0530 Subject: [PATCH] [feat] #19334 --- .../v12_0/set_permission_einvoicing.py | 12 + .../import_supplier_invoice/__init__.py | 0 .../import_supplier_invoice.js | 21 + .../import_supplier_invoice.json | 81 ++++ .../import_supplier_invoice.py | 383 ++++++++++++++++++ .../test_import_supplier_invoice.py | 10 + erpnext/regional/italy/setup.py | 25 ++ erpnext/regional/italy/utils.py | 2 + .../purchase_einvoice/__init__.py | 0 .../purchase_einvoice/purchase_einvoice.json | 23 ++ 10 files changed, 557 insertions(+) create mode 100644 erpnext/patches/v12_0/set_permission_einvoicing.py create mode 100644 erpnext/regional/doctype/import_supplier_invoice/__init__.py create mode 100644 erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.js create mode 100644 erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.json create mode 100644 erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py create mode 100644 erpnext/regional/doctype/import_supplier_invoice/test_import_supplier_invoice.py create mode 100644 erpnext/regional/print_format/purchase_einvoice/__init__.py create mode 100644 erpnext/regional/print_format/purchase_einvoice/purchase_einvoice.json diff --git a/erpnext/patches/v12_0/set_permission_einvoicing.py b/erpnext/patches/v12_0/set_permission_einvoicing.py new file mode 100644 index 0000000000..c01f34a70d --- /dev/null +++ b/erpnext/patches/v12_0/set_permission_einvoicing.py @@ -0,0 +1,12 @@ +import frappe +from frappe.permissions import add_permission, update_permission_property + +def execute(): + company = frappe.get_all('Company', filters = {'country': 'Italy'}) + + if not company: + return + + add_permission('Import Supplier Invoice', 'Accounts Manager', 0) + update_permission_property('Import Supplier Invoice', 'Accounts Manager', 0, 'write', 1) + update_permission_property('Import Supplier Invoice', 'Accounts Manager', 0, 'create', 1) \ No newline at end of file diff --git a/erpnext/regional/doctype/import_supplier_invoice/__init__.py b/erpnext/regional/doctype/import_supplier_invoice/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.js b/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.js new file mode 100644 index 0000000000..efd55db4de --- /dev/null +++ b/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.js @@ -0,0 +1,21 @@ +// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +// License: GNU General Public License v3. See license.txt + +frappe.ui.form.on('Import Supplier Invoice', { + onload: function(frm) { + frappe.realtime.on("import_invoice_update", function (data) { + frm.dashboard.show_progress(data.title, (data.count / data.total) * 100, data.message); + if (data.count == data.total) { + window.setTimeout(title => frm.dashboard.hide_progress(title), 1500, data.title); + } + }); + + frm.set_query("tax_account", function() { + return { + filters: { + account_type: 'Tax' + } + } + }); + } +}); \ No newline at end of file diff --git a/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.json b/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.json new file mode 100644 index 0000000000..6d28eac341 --- /dev/null +++ b/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.json @@ -0,0 +1,81 @@ +{ + "creation": "2019-10-15 12:33:21.845329", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "company", + "item_code", + "supplier_group", + "tax_account", + "column_break_5", + "zip_file", + "import_invoices", + "status" + ], + "fields": [ + { + "fieldname": "company", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Company", + "options": "Company", + "reqd": 1 + }, + { + "fieldname": "item_code", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item Code", + "options": "Item", + "reqd": 1 + }, + { + "fieldname": "supplier_group", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Supplier Group", + "options": "Supplier Group", + "reqd": 1 + }, + { + "fieldname": "tax_account", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Tax Account", + "options": "Account", + "reqd": 1 + }, + { + "fieldname": "column_break_5", + "fieldtype": "Column Break" + }, + { + "fieldname": "zip_file", + "fieldtype": "Attach", + "label": "Zip File" + }, + { + "description": "Click on Import Invoices button once the zip file has been attached to the document. Any errors related to processing will be shown in the Error Log.", + "fieldname": "import_invoices", + "fieldtype": "Button", + "label": "Import Invoices", + "options": "process_file_data" + }, + { + "fieldname": "status", + "fieldtype": "Data", + "label": "Status", + "read_only": 1 + } + ], + "modified": "2019-10-16 02:00:00.538268", + "modified_by": "Administrator", + "module": "Regional", + "name": "Import Supplier Invoice", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py b/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py new file mode 100644 index 0000000000..3b43fe7771 --- /dev/null +++ b/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py @@ -0,0 +1,383 @@ +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals + +from decimal import Decimal +import json +import re +import traceback +import zipfile +import frappe +from frappe import _ +from frappe.model.document import Document +from frappe.custom.doctype.custom_field.custom_field import create_custom_field +from frappe.utils.data import format_datetime +from bs4 import BeautifulSoup as bs +from frappe.utils import cint, flt, today, nowdate, add_days, get_files_path +import dateutil +from frappe.utils.file_manager import save_file + +class ImportSupplierInvoice(Document): + + def autoname(self): + if not self.name: + self.name = "Import Invoice on " + format_datetime(self.creation) + + def import_xml_data(self): + import_file = frappe.get_doc("File", {"file_url": self.zip_file}) + self.publish("File Import", _("Processing XML Files"), 1, 3) + pi_count = 0 + with zipfile.ZipFile(get_full_path(self.zip_file)) as zf: + file_count = 0 + for file_name in zf.namelist(): + items = [] + taxes = [] + terms = [] + encoded_content = zf.read(file_name) + try: + content = encoded_content.decode("utf-8-sig") + except UnicodeDecodeError: + content = encoded_content.decode("utf-16") + file_content = bs(content, "xml") + + for line in file_content.find_all("DatiTrasmissione"): + destination_code = line.CodiceDestinatario.text + + for line in file_content.find_all("DatiGeneraliDocumento"): + document_type = line.TipoDocumento.text + bill_date = dateutil.parser.parse(line.Data.text).strftime("%Y-%m-%d") + invoice_no = line.Numero.text + if len(invoice_no) != 0: + for line in file_content.find_all("CedentePrestatore"): + tax_id = line.DatiAnagrafici.IdPaese.text + line.DatiAnagrafici.IdCodice.text + if line.find("CodiceFiscale"): + fiscal_code = line.DatiAnagrafici.CodiceFiscale.text + else: + fiscal_code = "" + if line.find("RegimeFiscale"): + fiscal_regime = line.DatiAnagrafici.RegimeFiscale.text + else: + fiscal_regime = "" + if line.find("Denominazione"): + supplier = line.DatiAnagrafici.Anagrafica.Denominazione.text + if line.find("Nome"): + supplier = line.DatiAnagrafici.Anagrafica.Nome.text + " " + line.DatiAnagrafici.Anagrafica.Cognome.text + address_line1 = line.Sede.Indirizzo.text + city = line.Sede.Comune.text + if line.find("Provincia"): + province = line.Sede.Provincia.text + else: + province = "" + pin_code = line.Sede.CAP.text + country = get_country(line.Sede.Nazione.text) + + for line in file_content.find_all("DettaglioLinee"): + if line.find("PrezzoUnitario") and line.find("PrezzoTotale"): + unit_rate = float(line.PrezzoUnitario.text) or float(0) + line_total = float(line.PrezzoTotale.text) or float(0) + + if (unit_rate == 0.0): + qty = float(1) + uom = "nos" + rate = tax_rate = 0 + else: + if (line_total / unit_rate) == 1.0: + qty = float(1) + uom = "nos" + else: + if line.find("Quantita"): + qty = float(line.Quantita.text) or float(0) + if line.find("UnitaMisura"): + uom = create_uom(line.UnitaMisura.text) + else: + uom = "nos" + + if (unit_rate < 0 and line_total < 0): + qty *= -1 + return_invoice = 1 + else: + return_invoice = 0 + + rate = unit_rate + if line.find("AliquotaIVA"): + tax_rate = float(line.AliquotaIVA.text) + + line_str = re.sub('[^A-Za-z0-9]+', '-', line.Descrizione.text) + item_name = line_str[0:140] + items.append({ + "item_code": self.item_code, + "item_name": item_name, + "description": line_str, + "qty": float(qty), + "uom": uom, + "rate": rate, + "conversion_factor": float(1), + "tax_rate": tax_rate + }) + + for line in file_content.find_all("DatiRiepilogo"): + if line.find("AliquotaIVA"): + if line.find("EsigibilitaIVA"): + descr = line.EsigibilitaIVA.text + else: + descr = "None" + taxes.append({ + "charge_type": "Actual", + "account_head": self.tax_account, + "tax_rate": float(line.AliquotaIVA.text) or float(0), + "description": descr, + "tax_amount": float(line.Imposta.text) if len(line.find("Imposta"))!=0 else float(0) + }) + + mop_dict = {'MP01':"MP01-Contanti", 'MP02':"MP02-Assegno", 'MP03':"MP03-Assegno circolare", 'MP04':"MP04-Contanti presso Tesoreria", + 'MP05':"MP05-Bonifico", 'MP06': "MP06-Vaglia cambiario", 'MP07': "MP07-Bollettino bancario", 'MP08': "MP08-Carta di pagamento", + 'MP09':"MP09-RID", 'MP10': "MP10-RID utenze", 'MP11': "MP11-RID veloce", 'MP12':"MP12-RIBA", 'MP13':"MP13-MAV", + 'MP14':"MP14-Quietanza erario", 'MP15':"MP15-Giroconto su conti di contabilità speciale", 'MP16':"MP16-Domiciliazione bancaria", + 'MP17': "MP17-Domiciliazione postale", 'MP18': "MP18-Bollettino di c/c postale", 'MP19': "MP19-SEPA Direct Debit", + 'MP20': "MP20-SEPA Direct Debit CORE", 'MP21': "MP21-SEPA Direct Debit B2B", 'MP22':"MP22-Trattenuta su somme già riscosse"} + + for line in file_content.find_all("DettaglioPagamento"): + mop_code = mop_dict.get(line.ModalitaPagamento.text) + + if line.find("DataScadenzaPagamento"): + due_date = dateutil.parser.parse(line.DataScadenzaPagamento.text).strftime("%Y-%m-%d") + else: + due_date = today() + terms.append({ + "mode_of_payment_code": mop_code, + "bank_account_iban": line.IBAN.text if line.find("IBAN") else "", + "due_date": due_date, + "payment_amount": line.ImportoPagamento.text + }) + + supplier_name = create_supplier(supplier = supplier, supplier_group = self.supplier_group, + tax_id = tax_id, fiscal_code = fiscal_code, + fiscal_regime = fiscal_regime) + + address = create_address(supplier_name = supplier_name, address_line1 = address_line1, + city = city, province = province, + pin_code = pin_code, country = country) + + pi_name = create_purchase_invoice(company = self.company, + supplier_name = supplier_name, + bill_no = invoice_no, + document_type = document_type, + bill_date = bill_date, + is_return = return_invoice, + destination_code = destination_code, + items = items, + taxes = taxes, + terms = terms, + file_name = file_name) + file_count += 1 + if pi_name: + pi_count += 1 + file_save = save_file(file_name, encoded_content, "Purchase Invoice", pi_name, folder=None, decode=False, is_private=0, df=None) + + if pi_count == file_count: + self.status = "File Import Completed" + self.publish("File Import", _("XML Files Processed"), 2, 3) + else: + self.status = "Partially Completed - Check Error Log" + self.publish("File Import", _("XML Files Processed"), 2, 3) + + self.save() + self.publish("File Import", _("XML Files Processed"), 3, 3) + + def process_file_data(self): + self.status = "Processing File Data" + self.save() + frappe.enqueue_doc(self.doctype, self.name, "import_xml_data", queue="long", timeout=3600) + + def publish(self, title, message, count, total): + frappe.publish_realtime("import_invoice_update", {"title": title, "message": message, "count": count, "total": total}) + +def create_supplier(**args): + + args = frappe._dict(args) + existing_supplier_name = frappe.db.get_value("Supplier", + filters={"tax_id": args.tax_id}, fieldname="name") + if existing_supplier_name: + pass + else: + existing_supplier_name = frappe.db.get_value("Supplier", + filters={"name": args.supplier}, fieldname="name") + + if existing_supplier_name: + filters = [ + ["Dynamic Link", "link_doctype", "=", "Supplier"], + ["Dynamic Link", "link_name", "=", args.existing_supplier_name], + ["Dynamic Link", "parenttype", "=", "Contact"] + ] + + existing_contacts = frappe.get_list("Contact", filters) + + if existing_contacts: + pass + else: + new_contact = frappe.new_doc("Contact") + new_contact.first_name = args.supplier + new_contact.append('links', { + "link_doctype": "Supplier", + "link_name": existing_supplier_name + }) + new_contact.insert() + + return existing_supplier_name + else: + + new_supplier = frappe.new_doc("Supplier") + new_supplier.supplier_name = args.supplier + new_supplier.supplier_group = args.supplier_group + new_supplier.tax_id = args.tax_id + new_supplier.fiscal_code = args.fiscal_code + new_supplier.fiscal_regime = args.fiscal_regime + new_supplier.save() + + new_contact = frappe.new_doc("Contact") + new_contact.first_name = args.supplier + new_contact.append('links', { + "link_doctype": "Supplier", + "link_name": new_supplier.name + }) + + new_contact.insert() + + return new_supplier.name + +def create_address(**args): + + args = frappe._dict(args) + filters = [ + ["Dynamic Link", "link_doctype", "=", "Supplier"], + ["Dynamic Link", "link_name", "=", args.supplier_name], + ["Dynamic Link", "parenttype", "=", "Address"] + ] + + existing_address = frappe.get_list("Address", filters) + + if args.address_line1: + make_address = frappe.new_doc("Address") + make_address.address_line1 = args.address_line1 + + if args.city: + make_address.city = args.city + else: + make_address.city = "Not Provided" + + if args.province: + make_address.state_code = args.province + + if args.pincode: + make_address.pincode = args.pincode + + if args.country: + make_address.country = args.country + + for address in existing_address: + address_doc = frappe.get_doc("Address", address["name"]) + if (address_doc.address_line1 == make_address.address_line1 and + address_doc.pincode == make_address.pincode): + return address + + make_address.append("links", { + "link_doctype": "Supplier", + "link_name": args.supplier_name + }) + make_address.address_type = "Billing" + make_address.insert() + return make_address.name + else: + return None + +def create_purchase_invoice(**args): + + args = frappe._dict(args) + pi = frappe.get_doc({ + "doctype": "Purchase Invoice", + "company": args.company, + "naming_series": "PINV-", + "supplier": args.supplier_name, + "is_return": args.is_return, + "posting_date": today(), + "bill_no": args.bill_no, + "bill_date": args.bill_date, + "destination_code": args.destination_code, + "document_type": args.document_type, + "items": args["items"], + "taxes": args["taxes"] + }) + + try: + pi.insert(ignore_permissions=True) + calc_total = 0 + adj = 0 + for term in args.terms: + calc_total += float(term["payment_amount"]) + if float(calc_total - float(pi.grand_total)) != 0: + adj = calc_total - float(pi.grand_total) + pi.payment_schedule = [] + for term in args.terms: + pi.append('payment_schedule',{"mode_of_payment_code": term["mode_of_payment_code"], + "bank_account_iban": term["bank_account_iban"], + "due_date": term["due_date"], + "payment_amount": float(term["payment_amount"]) - adj }) + adj = 0 + pi.imported_grand_total = calc_total + pi.save() + return pi.name + except Exception as e: + frappe.log_error(message=e, title="Create Purchase Invoice: " + args.bill_no + "File Name: " + args.file_name) + return None + +def get_country(code): + + existing_country_name = frappe.db.get_value("Country", + filters={"code": code}, fieldname="name") + if existing_country_name: + return existing_country_name + else: + frappe.throw(_("Country Code in File does not match with country code set up in the system")) + +def create_uom(uom): + + existing_uom = frappe.db.get_value("UOM", + filters={"uom_name": uom}, fieldname="uom_name") + if existing_uom: + return existing_uom + else: + new_uom = frappe.new_doc("UOM") + new_uom.uom_name = uom + new_uom.save() + return new_uom.uom_name + +def check_bill_no(invoice_no): + + existing_bill_no = frappe.db.get_value("Purchase Invoice", + filters={"bill_no": invoice_no, "docstatus": 1}, fieldname="name") + if existing_bill_no: + return existing_bill_no + else: + return None + +def get_full_path(file_name): + """Returns file path from given file name""" + file_path = file_name + + if "/" not in file_path: + file_path = "/files/" + file_path + + if file_path.startswith("/private/files/"): + file_path = get_files_path(*file_path.split("/private/files/", 1)[1].split("/"), is_private=1) + + elif file_path.startswith("/files/"): + file_path = get_files_path(*file_path.split("/files/", 1)[1].split("/")) + + elif file_path.startswith("http"): + pass + + elif not self.file_url: + frappe.throw(_("There is some problem with the file url: {0}").format(file_path)) + + return file_path \ No newline at end of file diff --git a/erpnext/regional/doctype/import_supplier_invoice/test_import_supplier_invoice.py b/erpnext/regional/doctype/import_supplier_invoice/test_import_supplier_invoice.py new file mode 100644 index 0000000000..d1caf77fc2 --- /dev/null +++ b/erpnext/regional/doctype/import_supplier_invoice/test_import_supplier_invoice.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +# import frappe +import unittest + +class TestImportSupplierInvoice(unittest.TestCase): + pass diff --git a/erpnext/regional/italy/setup.py b/erpnext/regional/italy/setup.py index 1526d6f62f..2d0ad66b0a 100644 --- a/erpnext/regional/italy/setup.py +++ b/erpnext/regional/italy/setup.py @@ -155,6 +155,31 @@ def make_custom_fields(update=True): fetch_from="country.code"), dict(fieldname='state_code', label='State Code', fieldtype='Data', insert_after='state', print_hide=1) + ], + 'Purchase Invoice': [ + dict(fieldname='document_type', label='Document Type', + fieldtype='Data', insert_after='company', print_hide=1, read_only=1 + ), + dict(fieldname='destination_code', label='Destination Code', + fieldtype='Data', insert_after='company', print_hide=1, read_only=1 + ), + dict(fieldname='imported_grand_total', label='Imported Grand Total', + fieldtype='Data', insert_after='update_auto_repeat_reference', print_hide=1, read_only=1 + ) + ], + 'Purchase Taxes and Charges': [ + dict(fieldname='tax_rate', label='Tax Rate', + fieldtype='Data', insert_after='parenttype', print_hide=1, read_only=0 + ) + ], + 'Supplier': [ + dict(fieldname='fiscal_code', label='Fiscal Code', + fieldtype='Data', insert_after='tax_id', print_hide=1, read_only=1 + ), + dict(fieldname='fiscal_regime', label='Fiscal Regime', + fieldtype='Select', insert_after='fiscal_code', print_hide=1, read_only=1, + options= "\nRF01\nRF02\nRF04\nRF05\nRF06\nRF07\nRF08\nRF09\nRF10\nRF11\nRF12\nRF13\nRF14\nRF15\nRF16\nRF17\nRF18\nRF19" + ) ] } diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py index bc8d00d8b8..2af72f8e27 100644 --- a/erpnext/regional/italy/utils.py +++ b/erpnext/regional/italy/utils.py @@ -13,6 +13,8 @@ from erpnext.regional.italy import state_codes def update_itemised_tax_data(doc): if not doc.taxes: return + if doc.doctype == "Purchase Invoice": return + itemised_tax = get_itemised_tax(doc.taxes) for row in doc.items: diff --git a/erpnext/regional/print_format/purchase_einvoice/__init__.py b/erpnext/regional/print_format/purchase_einvoice/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/regional/print_format/purchase_einvoice/purchase_einvoice.json b/erpnext/regional/print_format/purchase_einvoice/purchase_einvoice.json new file mode 100644 index 0000000000..88f31dd130 --- /dev/null +++ b/erpnext/regional/print_format/purchase_einvoice/purchase_einvoice.json @@ -0,0 +1,23 @@ +{ + "align_labels_right": 0, + "creation": "2019-10-16 00:47:08.877767", + "custom_format": 0, + "disabled": 1, + "doc_type": "Purchase Invoice", + "docstatus": 0, + "doctype": "Print Format", + "font": "Default", + "format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"
\\t\\t\\t\\t

Purchase Invoice
{{ doc.name }}\\t\\t\\t\\t

\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n
\\nCedente/prestatore (fornitore)\\n\\nCessionario/committente (cliente)\\n
\\n

Identificstivo fiscale ai fini IVA: {{frappe.db.get_value(\\\"Supplier\\\", doc.supplier, \\\"tax_id\\\")}}

\\n

Codice fiscale: {{frappe.db.get_value(\\\"Supplier\\\", doc.supplier, \\\"fiscal_code\\\")}}

\\n

Denominazione: {{frappe.db.get_value(\\\"Supplier\\\", doc.supplier, \\\"supplier_name\\\")}}

\\n

Regime fiscale: {{frappe.db.get_value(\\\"Supplier\\\", doc.supplier, \\\"fiscal_regime\\\")}}

\\n

Indrizo: {{frappe.db.get_value(\\\"Address\\\", doc.supplier_address, \\\"address_line1\\\")}}

\\n

Commune: {{frappe.db.get_value(\\\"Address\\\", doc.supplier_address, \\\"city\\\")}} Provincia: {{frappe.db.get_value(\\\"Address\\\", doc.supplier_address, \\\"state_code\\\")}}

\\n

Cap: {{(frappe.db.get_value(\\\"Address\\\", doc.supplier_address, \\\"pincode\\\")) or \\\" \\\"}} Nazione: {{frappe.db.get_value(\\\"Address\\\", doc.supplier_address, \\\"country\\\")}}

\\n
\\n

Identificstivo fiscale ai fini IVA: {{frappe.db.get_value(\\\"Company\\\", doc.company, \\\"tax_id\\\")}}

\\n

Codice fiscale: {{frappe.db.get_value(\\\"Company\\\", doc.company, \\\"fiscal_code\\\")}}

\\n

Denominazione: {{doc.company}}

\\n

Indrizo: {{frappe.db.get_value(\\\"Address\\\", doc.shipping_address, \\\"address_line1\\\")}}

\\n

Commune: {{frappe.db.get_value(\\\"Address\\\", doc.shipping_address, \\\"city\\\")}} Provincia: {{frappe.db.get_value(\\\"Address\\\", doc.shipping_address, \\\"state_code\\\")}}

\\n

Cap: {{frappe.db.get_value(\\\"Address\\\", doc.shipping_address, \\\"pincode\\\")}} Nazione: {{frappe.db.get_value(\\\"Address\\\", doc.shipping_address, \\\"country\\\")}}

\\n
\\n
\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n
\\nTipologla\\n\\nArt. 73\\n\\nNumero documento\\n\\nData documento\\n\\nCodice destinatario\\n
\\n{{doc.document_type or \\\" \\\"}}\\n\\n{{\\\" \\\"}}\\n\\n{{doc.bill_no or \\\" \\\"}}\\n\\n{{doc.get_formatted(\\\"bill_date\\\") or \\\" \\\"}}\\n\\n{{doc.destination_code or \\\" \\\"}}\\n
\\n
\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n{%- for row in doc.items -%}\\n\\n\\n\\n\\n\\n\\n\\n{%- endfor -%}\\n\\n
\\nDescrizione\\n\\nQuantita\\n\\nPrezzo unitario\\n\\nUM\\n\\n%IVA\\n\\nPrezzo totale\\n
\\n{{row.description or \\\" \\\"}}\\n\\n{{row.get_formatted(\\\"qty\\\", doc)}}\\n\\n{{row.get_formatted(\\\"rate\\\", doc)}}\\n\\n{{row.get_formatted(\\\"uom\\\", doc)}}\\n\\n{{row.get_formatted(\\\"tax_rate\\\", doc)}}\\n\\n{{row.get_formatted(\\\"amount\\\", doc)}}\\n
\\n
\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n{%- for row in doc.taxes -%}\\n\\n\\n\\n\\n\\n\\n\\n{%- endfor -%}\\n\\n
\\nesigibilita immediata / riferimenti normativi\\n\\n%IVA\\n\\nSpese accessorie\\n\\nArr.\\n\\nTotale imponibile\\n\\nTotale Imposta\\n
\\n{% if 'None' in row.description %}\\n {{ \\\" \\\" }}\\n{% else %}\\n{{row.description}}\\n{% endif %}\\n\\n{{row.get_formatted(\\\"tax_rate\\\", doc)}}\\n\\n{{\\\"0,00\\\"}}\\n\\n{{\\\" \\\"}}\\n\\n{{doc.get_formatted(\\\"base_net_total\\\")}}\\n\\n{{row.get_formatted(\\\"tax_amount\\\", doc)}}\\n
\\n
\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n
\\nImporto bolio\\n\\nSconto/Magglorazione\\n\\nArr.\\n\\nTotale documento\\n
\\n{{\\\" \\\"}}\\n\\n{{\\\" \\\"}}\\n\\n{{\\\" \\\"}}\\n\\n{{doc.get_formatted(\\\"base_grand_total\\\")}}\\n
\\n
\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n{%- for row in doc.payment_schedule -%}\\n\\n\\n\\n\\n\\n\\n{%- endfor -%}\\n\\n
\\nModalita pagamento\\n\\nIBAN\\n\\nInstituto\\n\\nData scadenza\\n\\nImporto\\n
\\n{{row.get_formatted(\\\"mode_of_payment_code\\\",doc)}}\\n\\n{{row.get_formatted(\\\"bank_account_iban\\\",doc)}}\\n\\n{{\\\" \\\"}}\\n\\n{{row.get_formatted(\\\"due_date\\\",doc)}}\\n\\n{{row.get_formatted(\\\"payment_amount\\\",doc)}}\\n
\"}]", + "idx": 0, + "line_breaks": 0, + "modified": "2019-10-16 23:32:37.709344", + "modified_by": "Administrator", + "module": "Regional", + "name": "Purchase eInvoice", + "owner": "Administrator", + "print_format_builder": 1, + "print_format_type": "Jinja", + "raw_printing": 0, + "show_section_headings": 0, + "standard": "Yes" +} \ No newline at end of file