From 3553599efb4046ad4788e1d2b48a3081f246c85b Mon Sep 17 00:00:00 2001 From: trisusilo48 Date: Fri, 3 Jan 2025 11:01:39 +0700 Subject: export xml faktur --- indoteknik_custom/__manifest__.py | 3 +- indoteknik_custom/models/__init__.py | 1 + indoteknik_custom/models/coretax_fatur.py | 93 ++++++++++++++++++++++++++ indoteknik_custom/security/ir.model.access.csv | 1 + indoteknik_custom/views/coretax_faktur.xml | 49 ++++++++++++++ 5 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 indoteknik_custom/models/coretax_fatur.py create mode 100644 indoteknik_custom/views/coretax_faktur.xml diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 89f62524..255fbd3d 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -8,7 +8,7 @@ 'author': 'Rafi Zadanly', 'website': '', 'images': ['assets/favicon.ico'], - 'depends': ['base', 'coupon', 'delivery', 'sale', 'sale_management', 'vit_kelurahan'], + 'depends': ['base', 'coupon', 'delivery', 'sale', 'sale_management', 'vit_kelurahan', 'vit_efaktur' ], 'data': [ 'security/ir.model.access.csv', 'views/group_partner.xml', @@ -155,6 +155,7 @@ 'report/report_invoice.xml', 'report/report_picking.xml', 'report/report_sale_order.xml', + 'views/coretax_faktur.xml', ], 'demo': [], 'css': [], diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index ad6d75dd..b698b14c 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -134,3 +134,4 @@ from . import find_page from . import approval_retur_picking from . import va_multi_approve from . import va_multi_reject +from . import coretax_fatur diff --git a/indoteknik_custom/models/coretax_fatur.py b/indoteknik_custom/models/coretax_fatur.py new file mode 100644 index 00000000..1c3af6a4 --- /dev/null +++ b/indoteknik_custom/models/coretax_fatur.py @@ -0,0 +1,93 @@ +from odoo import models, fields +import xml.etree.ElementTree as ET +from xml.dom import minidom +import base64 + +class CoretaxFaktur(models.Model): + _name = 'coretax.faktur' + _description = 'Export Faktur ke XML' + + export_file = fields.Binary(string="Export File", ) + export_filename = fields.Char(string="Export File", ) + + def generate_xml(self): + # Buat root XML + root = ET.Element('TaxInvoiceBulk', { + 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance", + 'xsi:noNamespaceSchemaLocation': "TaxInvoice.xsd" + }) + ET.SubElement(root, 'TIN').text = 'xxxxxxxxxxxxxxxx' + + # Tambahkan elemen ListOfTaxInvoice + list_of_tax_invoice = ET.SubElement(root, 'ListOfTaxInvoice') + + # Dapatkan data faktur + inv_obj = self.env['account.move'] + invoices = inv_obj.search([('is_efaktur_exported','!=',True), + ('state','=','posted'), + ('efaktur_id','!=', False), + ('move_type','=','out_invoice')]) + for invoice in invoices: + tax_invoice = ET.SubElement(list_of_tax_invoice, 'TaxInvoice') + + # Tambahkan elemen faktur + ET.SubElement(tax_invoice, 'TaxInvoiceDate').text = invoice.invoice_date.strftime('%Y-%m-%d') if invoice.invoice_date else '' + ET.SubElement(tax_invoice, 'TaxInvoiceOpt').text = 'Normal' + ET.SubElement(tax_invoice, 'TrxCode').text = '01' + ET.SubElement(tax_invoice, 'AddInfo') + ET.SubElement(tax_invoice, 'CustomDoc') + ET.SubElement(tax_invoice, 'RefDesc') + ET.SubElement(tax_invoice, 'FacilityStamp') + ET.SubElement(tax_invoice, 'SellerIDTKU').text = '0000000000000000000000' + ET.SubElement(tax_invoice, 'BuyerTin').text = 'xxxxxxxxxxxxxxxx' + ET.SubElement(tax_invoice, 'BuyerDocument').text = 'TIN' + ET.SubElement(tax_invoice, 'BuyerCountry').text = 'IND' + ET.SubElement(tax_invoice, 'BuyerEmail').text = invoice.partner_id.email or '' + ET.SubElement(tax_invoice, 'BuyerIDTKU').text = '0000000000000000000000' + + # Tambahkan elemen ListOfGoodService + list_of_good_service = ET.SubElement(tax_invoice, 'ListOfGoodService') + for line in invoice.invoice_line_ids: + good_service = ET.SubElement(list_of_good_service, 'GoodService') + ET.SubElement(good_service, 'Opt').text = 'A' + ET.SubElement(good_service, 'Code').text = '000000' + ET.SubElement(good_service, 'Name').text = line.name + ET.SubElement(good_service, 'Unit').text = 'UM.0001' + ET.SubElement(good_service, 'Price').text = str(line.price_unit) + ET.SubElement(good_service, 'Qty').text = str(line.quantity) + ET.SubElement(good_service, 'TotalDiscount').text = '100000' + ET.SubElement(good_service, 'TaxBase').text = str(line.price_subtotal) + ET.SubElement(good_service, 'OtherTaxBase').text = str(line.price_subtotal) + ET.SubElement(good_service, 'VATRate').text = '11' + ET.SubElement(good_service, 'VAT').text = str(line.price_total * 0.11) + ET.SubElement(good_service, 'STLGRate').text = '20' + ET.SubElement(good_service, 'STLG').text = '580000' + + # Pretty print XML + xml_str = ET.tostring(root, encoding='utf-8') + xml_pretty = minidom.parseString(xml_str).toprettyxml(indent=" ") + return xml_pretty + + def export_to_download(self): + # Generate XML content + xml_content = self.generate_xml() + + # Encode content to Base64 + xml_encoded = base64.b64encode(xml_content.encode('utf-8')) + + # Buat attachment untuk XML + attachment = self.env['ir.attachment'].create({ + 'name': 'Faktur_XML.xml', + 'type': 'binary', + 'datas': xml_encoded, + 'mimetype': 'application/xml', + 'store_fname': 'faktur_xml.xml', + }) + + # Kembalikan URL untuk download dengan header 'Content-Disposition' + return { + 'type': 'ir.actions.act_url', + 'url': '/web/content/{}'.format(attachment.id), + 'target': 'self', + 'params': {'download': True}, # Menambahkan parameter untuk memastikan file didownload + } diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 2375df9d..8e4d3a71 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -148,3 +148,4 @@ access_sales_order_fulfillment_v2,access.sales.order.fulfillment.v2,model_sales_ access_v_move_outstanding,access.v.move.outstanding,model_v_move_outstanding,,1,1,1,1 access_va_multi_approve,access.va.multi.approve,model_va_multi_approve,,1,1,1,1 access_va_multi_reject,access.va.multi.reject,model_va_multi_reject,,1,1,1,1 +access_coretax_faktur,access.coretax.faktur,model_coretax_faktur,,1,1,1,1 diff --git a/indoteknik_custom/views/coretax_faktur.xml b/indoteknik_custom/views/coretax_faktur.xml new file mode 100644 index 00000000..45eea23f --- /dev/null +++ b/indoteknik_custom/views/coretax_faktur.xml @@ -0,0 +1,49 @@ + + + + + Export Faktur Pajak Keluaran XML Version + ir.actions.act_window + coretax.faktur + form + new + + + + view coretax faktur + coretax.faktur + form + +
+

+ Klik tombol Export di bawah untuk mulai export Faktur Pajak Keluaran. + Data yang diexport adalah Customer Invoice yang berstatus Open dan belum diexport ke E-Faktur. +

+ +

+ Setelah proses export Faktur Pajak Keluaran selesai dilakukan, + download file ini: +

+ + + + +

+ Lalu import ke program E-Faktur DJP melalui menu Referensi - Pajak Keluaran - Import +

+ +
+
+
+
+
+ + +
+
\ No newline at end of file -- cgit v1.2.3 From 2a3adac9333c2bd5cb9f0dca3ba080cd3e6dfce8 Mon Sep 17 00:00:00 2001 From: trisusilo48 Date: Fri, 3 Jan 2025 11:31:46 +0700 Subject: automatic download --- indoteknik_custom/models/coretax_fatur.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/indoteknik_custom/models/coretax_fatur.py b/indoteknik_custom/models/coretax_fatur.py index 1c3af6a4..a0820fee 100644 --- a/indoteknik_custom/models/coretax_fatur.py +++ b/indoteknik_custom/models/coretax_fatur.py @@ -85,9 +85,10 @@ class CoretaxFaktur(models.Model): }) # Kembalikan URL untuk download dengan header 'Content-Disposition' - return { + response = { 'type': 'ir.actions.act_url', - 'url': '/web/content/{}'.format(attachment.id), + 'url': '/web/content/{}?download=true'.format(attachment.id), 'target': 'self', - 'params': {'download': True}, # Menambahkan parameter untuk memastikan file didownload } + + return response -- cgit v1.2.3 From 992f530f9da44716361b27e62458c82a8aca78e1 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Fri, 3 Jan 2025 14:43:27 +0700 Subject: push --- indoteknik_custom/models/coretax_fatur.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/indoteknik_custom/models/coretax_fatur.py b/indoteknik_custom/models/coretax_fatur.py index a0820fee..426fb737 100644 --- a/indoteknik_custom/models/coretax_fatur.py +++ b/indoteknik_custom/models/coretax_fatur.py @@ -16,17 +16,17 @@ class CoretaxFaktur(models.Model): 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance", 'xsi:noNamespaceSchemaLocation': "TaxInvoice.xsd" }) - ET.SubElement(root, 'TIN').text = 'xxxxxxxxxxxxxxxx' + ET.SubElement(root, 'TIN').text = '74.226.022.7-086.000' # Tambahkan elemen ListOfTaxInvoice list_of_tax_invoice = ET.SubElement(root, 'ListOfTaxInvoice') # Dapatkan data faktur inv_obj = self.env['account.move'] - invoices = inv_obj.search([('is_efaktur_exported','!=',True), + invoices = inv_obj.search([('is_efaktur_exported','=',True), ('state','=','posted'), ('efaktur_id','!=', False), - ('move_type','=','out_invoice')]) + ('move_type','=','out_invoice')], limit = 5) for invoice in invoices: tax_invoice = ET.SubElement(list_of_tax_invoice, 'TaxInvoice') @@ -39,7 +39,7 @@ class CoretaxFaktur(models.Model): ET.SubElement(tax_invoice, 'RefDesc') ET.SubElement(tax_invoice, 'FacilityStamp') ET.SubElement(tax_invoice, 'SellerIDTKU').text = '0000000000000000000000' - ET.SubElement(tax_invoice, 'BuyerTin').text = 'xxxxxxxxxxxxxxxx' + ET.SubElement(tax_invoice, 'BuyerTin').text = invoice.partner_id.npwp or '' ET.SubElement(tax_invoice, 'BuyerDocument').text = 'TIN' ET.SubElement(tax_invoice, 'BuyerCountry').text = 'IND' ET.SubElement(tax_invoice, 'BuyerEmail').text = invoice.partner_id.email or '' @@ -50,9 +50,9 @@ class CoretaxFaktur(models.Model): for line in invoice.invoice_line_ids: good_service = ET.SubElement(list_of_good_service, 'GoodService') ET.SubElement(good_service, 'Opt').text = 'A' - ET.SubElement(good_service, 'Code').text = '000000' + ET.SubElement(good_service, 'Code').text = line.product_id.default_code ET.SubElement(good_service, 'Name').text = line.name - ET.SubElement(good_service, 'Unit').text = 'UM.0001' + ET.SubElement(good_service, 'Unit').text = 'UM.0018' ET.SubElement(good_service, 'Price').text = str(line.price_unit) ET.SubElement(good_service, 'Qty').text = str(line.quantity) ET.SubElement(good_service, 'TotalDiscount').text = '100000' -- cgit v1.2.3 From bef3ba4c18d585bc0980942d91b5fcb4d44427e1 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Fri, 3 Jan 2025 15:27:56 +0700 Subject: push --- indoteknik_custom/models/coretax_fatur.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/indoteknik_custom/models/coretax_fatur.py b/indoteknik_custom/models/coretax_fatur.py index 426fb737..32082774 100644 --- a/indoteknik_custom/models/coretax_fatur.py +++ b/indoteknik_custom/models/coretax_fatur.py @@ -36,32 +36,32 @@ class CoretaxFaktur(models.Model): ET.SubElement(tax_invoice, 'TrxCode').text = '01' ET.SubElement(tax_invoice, 'AddInfo') ET.SubElement(tax_invoice, 'CustomDoc') - ET.SubElement(tax_invoice, 'RefDesc') + ET.SubElement(tax_invoice, 'RefDesc').text = invoice.name ET.SubElement(tax_invoice, 'FacilityStamp') - ET.SubElement(tax_invoice, 'SellerIDTKU').text = '0000000000000000000000' + ET.SubElement(tax_invoice, 'SellerIDTKU').text = '0742260227086000000000' ET.SubElement(tax_invoice, 'BuyerTin').text = invoice.partner_id.npwp or '' ET.SubElement(tax_invoice, 'BuyerDocument').text = 'TIN' ET.SubElement(tax_invoice, 'BuyerCountry').text = 'IND' ET.SubElement(tax_invoice, 'BuyerEmail').text = invoice.partner_id.email or '' - ET.SubElement(tax_invoice, 'BuyerIDTKU').text = '0000000000000000000000' + ET.SubElement(tax_invoice, 'BuyerIDTKU').text = '' # Tambahkan elemen ListOfGoodService list_of_good_service = ET.SubElement(tax_invoice, 'ListOfGoodService') for line in invoice.invoice_line_ids: good_service = ET.SubElement(list_of_good_service, 'GoodService') - ET.SubElement(good_service, 'Opt').text = 'A' + ET.SubElement(good_service, 'Opt').text = 'B' if line.product_id.type == 'service' else 'A' ET.SubElement(good_service, 'Code').text = line.product_id.default_code ET.SubElement(good_service, 'Name').text = line.name ET.SubElement(good_service, 'Unit').text = 'UM.0018' ET.SubElement(good_service, 'Price').text = str(line.price_unit) ET.SubElement(good_service, 'Qty').text = str(line.quantity) - ET.SubElement(good_service, 'TotalDiscount').text = '100000' + ET.SubElement(good_service, 'TotalDiscount').text = str(line.discount) ET.SubElement(good_service, 'TaxBase').text = str(line.price_subtotal) ET.SubElement(good_service, 'OtherTaxBase').text = str(line.price_subtotal) - ET.SubElement(good_service, 'VATRate').text = '11' + ET.SubElement(good_service, 'VATRate').text = '0,11' ET.SubElement(good_service, 'VAT').text = str(line.price_total * 0.11) - ET.SubElement(good_service, 'STLGRate').text = '20' - ET.SubElement(good_service, 'STLG').text = '580000' + ET.SubElement(good_service, 'STLGRate').text = '' + ET.SubElement(good_service, 'STLG').text = '' # Pretty print XML xml_str = ET.tostring(root, encoding='utf-8') -- cgit v1.2.3