1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
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'
_description = 'Export Faktur ke XML'
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)
total_sum = sum(int(char) for char in cleaned_number)
if total_sum == 0 :
return '0000000000000000'
# 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, 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 = '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)
for invoice in invoices:
tax_invoice = ET.SubElement(list_of_tax_invoice, 'TaxInvoice')
buyerTIN = self.validate_and_format_number(invoice.partner_id.npwp)
nitku = invoice.partner_id.nitku
formula = nitku if nitku else buyerTIN.ljust(len(buyerTIN) + 6, '0')
buyerIDTKU = formula if sum(int(char) for char in buyerTIN) > 0 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 = '04'
ET.SubElement(tax_invoice, 'AddInfo')
ET.SubElement(tax_invoice, 'CustomDoc')
ET.SubElement(tax_invoice, 'CustomDocMonthYear')
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 = buyerTIN
ET.SubElement(tax_invoice, 'BuyerDocument').text = 'TIN' if sum(int(char) for char in buyerTIN) > 0 else 'Other ID'
ET.SubElement(tax_invoice, 'BuyerCountry').text = 'IDN'
ET.SubElement(tax_invoice, 'BuyerDocumentNumber').text = '-' if sum(int(char) for char in buyerTIN) > 0 else str(invoice.partner_id.id)
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 = 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 = 'A'
ET.SubElement(good_service, 'Code').text = '000000'
ET.SubElement(good_service, 'Name').text = line.name
ET.SubElement(good_service, 'Unit').text = 'UM.0018'
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 = '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, invoices):
# Generate XML content
xml_content = self.generate_xml(invoices)
# 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'
response = {
'type': 'ir.actions.act_url',
'url': '/web/content/{}?download=true'.format(attachment.id),
'target': 'self',
}
return response
|