summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortrisusilo48 <tri.susilo@altama.co.id>2025-01-13 11:24:08 +0700
committertrisusilo48 <tri.susilo@altama.co.id>2025-01-13 11:24:08 +0700
commitfcefddc96acc561ec13d52e734eaf04b041d4a0b (patch)
tree5214a97eb25c3790cdd5b498278d924aac1f0336
parentbef3ba4c18d585bc0980942d91b5fcb4d44427e1 (diff)
update export xml by selected invoice
-rw-r--r--indoteknik_custom/models/account_move.py32
-rw-r--r--indoteknik_custom/models/coretax_fatur.py69
-rw-r--r--indoteknik_custom/views/account_move.xml8
3 files changed, 85 insertions, 24 deletions
diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py
index 725b3c2d..42678847 100644
--- a/indoteknik_custom/models/account_move.py
+++ b/indoteknik_custom/models/account_move.py
@@ -325,3 +325,35 @@ class AccountMove(models.Model):
# if rec.statement_line_id and not rec.statement_line_id.statement_id.is_edit and rec.statement_line_id.statement_id.state == 'confirm':
# raise UserError('Bank Statement di Lock, Minta admin reconcile untuk unlock')
# return res
+
+ def validate_faktur_for_export(self):
+ invoices = self.filtered(lambda inv: not inv.is_efaktur_exported and
+ inv.state == 'posted' and
+ inv.move_type == 'out_invoice')
+
+ invalid_invoices = self - invoices
+ if invalid_invoices:
+ invalid_ids = ", ".join(str(inv.id) for inv in invalid_invoices)
+ raise UserError(_(
+ "Faktur dengan ID berikut tidak valid untuk diekspor: {}.\n"
+ "Pastikan faktur dalam status 'posted', belum diekspor, dan merupakan 'out_invoice'.".format(invalid_ids)
+ ))
+
+ return invoices
+
+ def export_faktur_to_xml(self):
+
+ valid_invoices = self.validate_faktur_for_export()
+
+ # Panggil model coretax.faktur untuk menghasilkan XML
+ coretax_faktur = self.env['coretax.faktur'].create({})
+ response = coretax_faktur.export_to_download(invoices=valid_invoices)
+
+ current_time = datetime.utcnow()
+ # Tandai faktur sebagai sudah diekspor
+ valid_invoices.write({
+ 'is_efaktur_exported': True,
+ 'date_efaktur_exported': current_time, # Set tanggal ekspor
+ })
+
+ return response
diff --git a/indoteknik_custom/models/coretax_fatur.py b/indoteknik_custom/models/coretax_fatur.py
index 32082774..00a8f5ab 100644
--- a/indoteknik_custom/models/coretax_fatur.py
+++ b/indoteknik_custom/models/coretax_fatur.py
@@ -2,6 +2,7 @@ from odoo import models, fields
import xml.etree.ElementTree as ET
from xml.dom import minidom
import base64
+import re
class CoretaxFaktur(models.Model):
_name = 'coretax.faktur'
@@ -9,68 +10,88 @@ class CoretaxFaktur(models.Model):
export_file = fields.Binary(string="Export File", )
export_filename = fields.Char(string="Export File", )
+
+ def validate_and_format_number(slef, input_number):
+ # Hapus semua karakter non-digit
+ cleaned_number = re.sub(r'\D', '', input_number)
+
+ # Hitung jumlah digit
+ digit_count = len(cleaned_number)
+
+ # Jika jumlah digit kurang dari 15, tambahkan nol di depan
+ if digit_count < 16:
+ cleaned_number = cleaned_number.zfill(16)
+
+ return cleaned_number
- def generate_xml(self):
+ def generate_xml(self, invoices=None):
# 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 = '74.226.022.7-086.000'
+ ET.SubElement(root, 'TIN').text = '0742260227086000'
# 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')], limit = 5)
+ # inv_obj = self.env['account.move']
+ # invoices = inv_obj.search([('is_efaktur_exported','=',True),
+ # ('state','=','posted'),
+ # ('efaktur_id','!=', False),
+ # ('move_type','=','out_invoice')], limit = 5)
+
for invoice in invoices:
tax_invoice = ET.SubElement(list_of_tax_invoice, 'TaxInvoice')
+ buyerTIN = self.validate_and_format_number(invoice.partner_id.npwp) if invoice.partner_id.npwp else '0000000000000000'
+ buyerIDTKU = buyerTIN.ljust(len(buyerTIN) + 6, '0') if invoice.partner_id.npwp else '000000'
# 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, 'TrxCode').text = '04'
ET.SubElement(tax_invoice, 'AddInfo')
ET.SubElement(tax_invoice, 'CustomDoc')
ET.SubElement(tax_invoice, 'RefDesc').text = invoice.name
ET.SubElement(tax_invoice, 'FacilityStamp')
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, 'BuyerTin').text = buyerTIN
+ ET.SubElement(tax_invoice, 'BuyerDocument').text = 'TIN' if invoice.partner_id.npwp else 'Other ID'
+ ET.SubElement(tax_invoice, 'BuyerCountry').text = 'IDN'
+ ET.SubElement(tax_invoice, 'BuyerDocumentNumber').text = '-'
+ ET.SubElement(tax_invoice, 'BuyerName').text = invoice.partner_id.nama_wajib_pajak or ''
+ ET.SubElement(tax_invoice, 'BuyerAdress').text = invoice.partner_id.alamat_lengkap_text or ''
ET.SubElement(tax_invoice, 'BuyerEmail').text = invoice.partner_id.email or ''
- ET.SubElement(tax_invoice, 'BuyerIDTKU').text = ''
+ ET.SubElement(tax_invoice, 'BuyerIDTKU').text = buyerIDTKU
# Tambahkan elemen ListOfGoodService
list_of_good_service = ET.SubElement(tax_invoice, 'ListOfGoodService')
for line in invoice.invoice_line_ids:
+ otherTaxBase = round(line.price_subtotal * (11/12)) if line.price_subtotal else 0
good_service = ET.SubElement(list_of_good_service, 'GoodService')
- 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, 'Opt').text = 'A'
+ ET.SubElement(good_service, '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, 'Price').text = str(round(line.price_subtotal/line.quantity, 2)) if line.price_subtotal else '0'
ET.SubElement(good_service, 'Qty').text = str(line.quantity)
- 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 = '0,11'
- ET.SubElement(good_service, 'VAT').text = str(line.price_total * 0.11)
- ET.SubElement(good_service, 'STLGRate').text = ''
- ET.SubElement(good_service, 'STLG').text = ''
+ ET.SubElement(good_service, 'TotalDiscount').text = '0'
+ ET.SubElement(good_service, 'TaxBase').text = str(round(line.price_subtotal)) if line.price_subtotal else '0'
+ ET.SubElement(good_service, 'OtherTaxBase').text = str(otherTaxBase)
+ ET.SubElement(good_service, 'VATRate').text = '12'
+ ET.SubElement(good_service, 'VAT').text = str(round(otherTaxBase * 0.12, 2))
+ ET.SubElement(good_service, 'STLGRate').text = '0'
+ ET.SubElement(good_service, 'STLG').text = '0'
# 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):
+ def export_to_download(self, invoices):
# Generate XML content
- xml_content = self.generate_xml()
+ xml_content = self.generate_xml(invoices)
# Encode content to Base64
xml_encoded = base64.b64encode(xml_content.encode('utf-8'))
diff --git a/indoteknik_custom/views/account_move.xml b/indoteknik_custom/views/account_move.xml
index 2863af57..4cc35b6d 100644
--- a/indoteknik_custom/views/account_move.xml
+++ b/indoteknik_custom/views/account_move.xml
@@ -163,5 +163,13 @@
<field name="state">code</field>
<field name="code">action = records.open_form_multi_create_reklas_penjualan()</field>
</record>
+
+ <record id="action_export_faktur" model="ir.actions.server">
+ <field name="name">Export Faktur ke XML</field>
+ <field name="model_id" ref="account.model_account_move" />
+ <field name="binding_model_id" ref="account.model_account_move" />
+ <field name="state">code</field>
+ <field name="code">action = records.export_faktur_to_xml()</field>
+ </record>
</data>
</odoo> \ No newline at end of file