blob: a03c3f0994dbba58c11776ba9225e88129ad96e8 [file] [log] [blame]
Ahmad8a425702021-09-14 14:45:23 +05001import io
2import os
Ahmadd1746ca2021-11-24 02:54:43 +01003from base64 import b64encode
Ahmad8a425702021-09-14 14:45:23 +05004
Ahmad940db712021-09-17 01:14:41 +05005import frappe
Ahmadd1746ca2021-11-24 02:54:43 +01006from frappe import _
Dany Robert276bf732021-12-07 12:11:43 +05307from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
Ahmadd1746ca2021-11-24 02:54:43 +01008from frappe.utils.data import add_to_date, get_time, getdate
Dany Robert45fce5a2021-12-07 18:29:16 +05309from pyqrcode import create as qr_create
Ahmad940db712021-09-17 01:14:41 +050010
11from erpnext import get_region
12
Ahmad8a425702021-09-14 14:45:23 +050013
Dany Robertebd41792021-12-07 12:15:58 +053014def create_qr_code(doc, method=None):
Ahmad8a425702021-09-14 14:45:23 +050015 region = get_region(doc.company)
16 if region not in ['Saudi Arabia']:
17 return
18
Dany Robert276bf732021-12-07 12:11:43 +053019 # if QR Code field not present, create it. Invoices without QR are invalid as per law.
20 if not hasattr(doc, 'ksa_einv_qr'):
21 create_custom_fields({
Dany Robertebd41792021-12-07 12:15:58 +053022 doc.doctype: [
Dany Robert276bf732021-12-07 12:11:43 +053023 dict(
24 fieldname='ksa_einv_qr',
Dany Robertf0fee562021-12-07 12:18:32 +053025 label='KSA E-Invoicing QR',
Dany Robert276bf732021-12-07 12:11:43 +053026 fieldtype='Attach Image',
27 read_only=1, no_copy=1, hidden=1
28 )
29 ]
30 })
Ahmad8a425702021-09-14 14:45:23 +050031
32 # Don't create QR Code if it already exists
Dany Robert276bf732021-12-07 12:11:43 +053033 qr_code = doc.get("ksa_einv_qr")
Ahmad8a425702021-09-14 14:45:23 +050034 if qr_code and frappe.db.exists({"doctype": "File", "file_url": qr_code}):
35 return
36
Dany Robert276bf732021-12-07 12:11:43 +053037 meta = frappe.get_meta(doc.doctype)
Ahmad940db712021-09-17 01:14:41 +050038
Dany Robert276bf732021-12-07 12:11:43 +053039 if "ksa_einv_qr" in [d.fieldname for d in meta.get_image_fields()]:
40 ''' TLV conversion for
41 1. Seller's Name
42 2. VAT Number
43 3. Time Stamp
44 4. Invoice Amount
45 5. VAT Amount
46 '''
47 tlv_array = []
48 # Sellers Name
Saqib Ansariac273912021-11-20 11:22:19 +053049
Dany Robert276bf732021-12-07 12:11:43 +053050 seller_name = frappe.db.get_value(
51 'Company',
52 doc.company,
53 'company_name_in_arabic')
Ahmad940db712021-09-17 01:14:41 +050054
Dany Robert276bf732021-12-07 12:11:43 +053055 if not seller_name:
56 frappe.throw(_('Arabic name missing for {} in the company document').format(doc.company))
Ahmad940db712021-09-17 01:14:41 +050057
Dany Robert276bf732021-12-07 12:11:43 +053058 tag = bytes([1]).hex()
59 length = bytes([len(seller_name.encode('utf-8'))]).hex()
60 value = seller_name.encode('utf-8').hex()
61 tlv_array.append(''.join([tag, length, value]))
Saqib Ansariac273912021-11-20 11:22:19 +053062
Dany Robert276bf732021-12-07 12:11:43 +053063 # VAT Number
64 tax_id = frappe.db.get_value('Company', doc.company, 'tax_id')
65 if not tax_id:
66 frappe.throw(_('Tax ID missing for {} in the company document').format(doc.company))
Ahmadd1746ca2021-11-24 02:54:43 +010067
Dany Robert276bf732021-12-07 12:11:43 +053068 tag = bytes([2]).hex()
69 length = bytes([len(tax_id)]).hex()
70 value = tax_id.encode('utf-8').hex()
71 tlv_array.append(''.join([tag, length, value]))
Ahmadd1746ca2021-11-24 02:54:43 +010072
Dany Robert276bf732021-12-07 12:11:43 +053073 # Time Stamp
74 posting_date = getdate(doc.posting_date)
75 time = get_time(doc.posting_time)
76 seconds = time.hour * 60 * 60 + time.minute * 60 + time.second
77 time_stamp = add_to_date(posting_date, seconds=seconds)
78 time_stamp = time_stamp.strftime('%Y-%m-%dT%H:%M:%SZ')
Ahmadd1746ca2021-11-24 02:54:43 +010079
Dany Robert276bf732021-12-07 12:11:43 +053080 tag = bytes([3]).hex()
81 length = bytes([len(time_stamp)]).hex()
82 value = time_stamp.encode('utf-8').hex()
83 tlv_array.append(''.join([tag, length, value]))
Ahmadd1746ca2021-11-24 02:54:43 +010084
Dany Robert276bf732021-12-07 12:11:43 +053085 # Invoice Amount
86 invoice_amount = str(doc.grand_total)
87 tag = bytes([4]).hex()
88 length = bytes([len(invoice_amount)]).hex()
89 value = invoice_amount.encode('utf-8').hex()
90 tlv_array.append(''.join([tag, length, value]))
Ahmadd1746ca2021-11-24 02:54:43 +010091
Dany Robert276bf732021-12-07 12:11:43 +053092 # VAT Amount
93 vat_amount = str(doc.total_taxes_and_charges)
Ahmadd1746ca2021-11-24 02:54:43 +010094
Dany Robert276bf732021-12-07 12:11:43 +053095 tag = bytes([5]).hex()
96 length = bytes([len(vat_amount)]).hex()
97 value = vat_amount.encode('utf-8').hex()
98 tlv_array.append(''.join([tag, length, value]))
Ahmadd1746ca2021-11-24 02:54:43 +010099
Dany Robert276bf732021-12-07 12:11:43 +0530100 # Joining bytes into one
101 tlv_buff = ''.join(tlv_array)
Ahmadd1746ca2021-11-24 02:54:43 +0100102
Dany Robert276bf732021-12-07 12:11:43 +0530103 # base64 conversion for QR Code
104 base64_string = b64encode(bytes.fromhex(tlv_buff)).decode()
Ahmadd1746ca2021-11-24 02:54:43 +0100105
Dany Robert276bf732021-12-07 12:11:43 +0530106 qr_image = io.BytesIO()
107 url = qr_create(base64_string, error='L')
108 url.png(qr_image, scale=2, quiet_zone=1)
Ahmad940db712021-09-17 01:14:41 +0500109
Dany Robert276bf732021-12-07 12:11:43 +0530110 name = frappe.generate_hash(doc.name, 5)
Saqib7511a9e2021-12-03 16:13:44 +0530111
Dany Robert276bf732021-12-07 12:11:43 +0530112 # making file
113 filename = f"QRCode-{name}.png".replace(os.path.sep, "__")
114 _file = frappe.get_doc({
115 "doctype": "File",
116 "file_name": filename,
117 "is_private": 0,
118 "content": qr_image.getvalue(),
119 "attached_to_doctype": doc.get("doctype"),
120 "attached_to_name": doc.get("name"),
121 "attached_to_field": "ksa_einv_qr"
122 })
Ahmad8a425702021-09-14 14:45:23 +0500123
Dany Robert276bf732021-12-07 12:11:43 +0530124 _file.save()
Ahmad8a425702021-09-14 14:45:23 +0500125
Dany Robert276bf732021-12-07 12:11:43 +0530126 # assigning to document
127 doc.db_set('ksa_einv_qr', _file.file_url)
128 doc.notify_update()
Ahmad8a425702021-09-14 14:45:23 +0500129
130
Dany Robert276bf732021-12-07 12:11:43 +0530131def delete_qr_code_file(doc, method=None):
Ahmad8a425702021-09-14 14:45:23 +0500132 region = get_region(doc.company)
133 if region not in ['Saudi Arabia']:
134 return
135
Dany Robert276bf732021-12-07 12:11:43 +0530136 if hasattr(doc, 'ksa_einv_qr'):
137 if doc.get('ksa_einv_qr'):
Ahmad8a425702021-09-14 14:45:23 +0500138 file_doc = frappe.get_list('File', {
Dany Robert276bf732021-12-07 12:11:43 +0530139 'file_url': doc.get('ksa_einv_qr')
Ahmad8a425702021-09-14 14:45:23 +0500140 })
141 if len(file_doc):
Deepesh Garg73c56512021-11-22 14:21:53 +0530142 frappe.delete_doc('File', file_doc[0].name)
143
Dany Robert3e974922021-12-08 08:03:30 +0530144def delete_vat_settings_for_company(doc, method=None):
Deepesh Garg73c56512021-11-22 14:21:53 +0530145 if doc.country != 'Saudi Arabia':
146 return
147
Dany Robert3e974922021-12-08 08:03:30 +0530148 if frappe.db.exists('KSA VAT Setting', doc.name):
149 frappe.delete_doc('KSA VAT Setting', doc.name)