From 81952975a13be726f0f7dd1825d514007cd09034 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Fri, 27 Sep 2024 03:31:45 +0200 Subject: [PATCH] feat(E Invoice Import): import tax lines --- .../e_invoice_import/e_invoice_import.js | 9 +++ .../e_invoice_import/e_invoice_import.json | 11 +++- .../e_invoice_import/e_invoice_import.py | 29 +++++++++- .../doctype/e_invoice_trade_tax/__init__.py | 0 .../e_invoice_trade_tax.json | 57 +++++++++++++++++++ .../e_invoice_trade_tax.py | 26 +++++++++ 6 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 eu_einvoice/european_e_invoice/doctype/e_invoice_trade_tax/__init__.py create mode 100644 eu_einvoice/european_e_invoice/doctype/e_invoice_trade_tax/e_invoice_trade_tax.json create mode 100644 eu_einvoice/european_e_invoice/doctype/e_invoice_trade_tax/e_invoice_trade_tax.py diff --git a/eu_einvoice/european_e_invoice/doctype/e_invoice_import/e_invoice_import.js b/eu_einvoice/european_e_invoice/doctype/e_invoice_import/e_invoice_import.js index c8c0c22..8bbf10e 100644 --- a/eu_einvoice/european_e_invoice/doctype/e_invoice_import/e_invoice_import.js +++ b/eu_einvoice/european_e_invoice/doctype/e_invoice_import/e_invoice_import.js @@ -36,6 +36,15 @@ frappe.ui.form.on("E Invoice Import", { }, }; }); + + frm.set_query("tax_account", "taxes", function (doc, cdt, cdn) { + return { + filters: { + account_type: "Tax", + company: doc.company, + }, + }; + }); }, refresh: function (frm) { const attach_field = frm.fields_dict["einvoice"]; diff --git a/eu_einvoice/european_e_invoice/doctype/e_invoice_import/e_invoice_import.json b/eu_einvoice/european_e_invoice/doctype/e_invoice_import/e_invoice_import.json index 874b0f1..e6fe3ab 100644 --- a/eu_einvoice/european_e_invoice/doctype/e_invoice_import/e_invoice_import.json +++ b/eu_einvoice/european_e_invoice/doctype/e_invoice_import/e_invoice_import.json @@ -37,7 +37,8 @@ "items_section", "items", "settlement_section", - "currency" + "currency", + "taxes" ], "fields": [ { @@ -242,6 +243,12 @@ "fieldtype": "Link", "label": "Purchase Order", "options": "Purchase Order" + }, + { + "fieldname": "taxes", + "fieldtype": "Table", + "label": "Taxes", + "options": "E Invoice Trade Tax" } ], "index_web_pages_for_search": 1, @@ -252,7 +259,7 @@ "link_fieldname": "e_invoice_import" } ], - "modified": "2024-09-15 11:36:46.090400", + "modified": "2024-09-26 21:07:31.840574", "modified_by": "Administrator", "module": "European e-Invoice", "name": "E Invoice Import", diff --git a/eu_einvoice/european_e_invoice/doctype/e_invoice_import/e_invoice_import.py b/eu_einvoice/european_e_invoice/doctype/e_invoice_import/e_invoice_import.py index 5b62c40..22edaae 100644 --- a/eu_einvoice/european_e_invoice/doctype/e_invoice_import/e_invoice_import.py +++ b/eu_einvoice/european_e_invoice/doctype/e_invoice_import/e_invoice_import.py @@ -14,6 +14,7 @@ from frappe.model.mapper import get_mapped_doc if TYPE_CHECKING: + from drafthorse.models.accounting import ApplicableTradeTax from drafthorse.models.party import PostalTradeAddress, TradeParty from drafthorse.models.tradelines import LineItem from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import PurchaseInvoice @@ -29,6 +30,9 @@ class EInvoiceImport(Document): from frappe.types import DF from eu_einvoice.european_e_invoice.doctype.e_invoice_item.e_invoice_item import EInvoiceItem + from eu_einvoice.european_e_invoice.doctype.e_invoice_trade_tax.e_invoice_trade_tax import ( + EInvoiceTradeTax, + ) amended_from: DF.Link | None buyer_address_line_1: DF.Data | None @@ -53,6 +57,7 @@ class EInvoiceImport(Document): seller_tax_id: DF.Data | None supplier: DF.Link | None supplier_address: DF.Link | None + taxes: DF.Table[EInvoiceTradeTax] # end: auto-generated types def validate(self): @@ -83,8 +88,6 @@ def before_submit(self): if not (self.items and all(row.item for row in self.items)): frappe.throw(_("Please map all invoice lines to an item before submitting")) - self.create_purchase_invoice() - def get_parsed_einvoice(self) -> DrafthorseDocument: return DrafthorseDocument.parse( get_xml_bytes(Path(get_site_path(self.einvoice.lstrip("/"))).resolve()) @@ -111,6 +114,10 @@ def read_values_from_einvoice(self) -> None: for li in doc.trade.items.children: self.parse_line_item(li) + self.taxes = [] + for tax in doc.trade.settlement.trade_tax.children: + self.parse_tax(tax) + def parse_seller(self, seller: "TradeParty"): self.seller_name = str(seller.name) self.seller_tax_id = ( @@ -158,6 +165,12 @@ def parse_line_item(self, li: "LineItem"): item.tax_rate = float(li.settlement.trade_tax.rate_applicable_percent._value) item.total_amount = float(li.settlement.monetary_summation.total_amount._value) + def parse_tax(self, tax: "ApplicableTradeTax"): + t = self.append("taxes") + t.basis_amount = float(tax.basis_amount._value) + t.rate_applicable_percent = float(tax.rate_applicable_percent._value) + t.calculated_amount = float(tax.calculated_amount._value) + def guess_supplier(self): if self.supplier: return @@ -208,6 +221,9 @@ def create_purchase_invoice(source_name, target_doc=None): def post_process(source, target: "PurchaseInvoice"): target.set_missing_values() + def process_tax_row(source, target, source_parent): + target.charge_type = "Actual" + return get_mapped_doc( "E Invoice Import", source_name, @@ -233,6 +249,15 @@ def post_process(source, target: "PurchaseInvoice"): "net_rate": "rate", }, }, + "E Invoice Trade Tax": { + "doctype": "Purchase Taxes and Charges", + "field_map": { + "tax_account": "account_head", + "rate_applicable_percent": "rate", + "calculated_amount": "tax_amount", + }, + "postprocess": process_tax_row, + }, }, target_doc, post_process, diff --git a/eu_einvoice/european_e_invoice/doctype/e_invoice_trade_tax/__init__.py b/eu_einvoice/european_e_invoice/doctype/e_invoice_trade_tax/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/eu_einvoice/european_e_invoice/doctype/e_invoice_trade_tax/e_invoice_trade_tax.json b/eu_einvoice/european_e_invoice/doctype/e_invoice_trade_tax/e_invoice_trade_tax.json new file mode 100644 index 0000000..8a631c4 --- /dev/null +++ b/eu_einvoice/european_e_invoice/doctype/e_invoice_trade_tax/e_invoice_trade_tax.json @@ -0,0 +1,57 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2024-09-26 21:04:33.284269", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "basis_amount", + "rate_applicable_percent", + "calculated_amount", + "tax_account" + ], + "fields": [ + { + "fieldname": "basis_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Basis Amount", + "options": "currency", + "read_only": 1 + }, + { + "fieldname": "rate_applicable_percent", + "fieldtype": "Percent", + "in_list_view": 1, + "label": "Rate Applicable Percent", + "read_only": 1 + }, + { + "fieldname": "calculated_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Calculated Amount", + "options": "currency", + "read_only": 1 + }, + { + "fieldname": "tax_account", + "fieldtype": "Link", + "label": "Tax Account", + "options": "Account" + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2024-09-26 21:18:13.837830", + "modified_by": "Administrator", + "module": "European e-Invoice", + "name": "E Invoice Trade Tax", + "owner": "Administrator", + "permissions": [], + "sort_field": "creation", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/eu_einvoice/european_e_invoice/doctype/e_invoice_trade_tax/e_invoice_trade_tax.py b/eu_einvoice/european_e_invoice/doctype/e_invoice_trade_tax/e_invoice_trade_tax.py new file mode 100644 index 0000000..c63ad54 --- /dev/null +++ b/eu_einvoice/european_e_invoice/doctype/e_invoice_trade_tax/e_invoice_trade_tax.py @@ -0,0 +1,26 @@ +# Copyright (c) 2024, ALYF GmbH and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class EInvoiceTradeTax(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + basis_amount: DF.Currency + calculated_amount: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + rate_applicable_percent: DF.Percent + tax_account: DF.Link | None + # end: auto-generated types + + pass