mirror of
https://github.com/bringout/oca-ocb-l10n_me-africa.git
synced 2026-04-27 11:42:01 +02:00
Initial commit: L10N_Me Africa packages
This commit is contained in:
commit
c265268138
611 changed files with 75334 additions and 0 deletions
86
odoo-bringout-oca-ocb-l10n_sa/l10n_sa/models/account_move.py
Normal file
86
odoo-bringout-oca-ocb-l10n_sa/l10n_sa/models/account_move.py
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
import base64
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tools import float_repr, format_datetime
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
_inherit = 'account.move'
|
||||
|
||||
l10n_sa_delivery_date = fields.Date(string='Supply Date',
|
||||
default=fields.Date.context_today,
|
||||
copy=False,
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
help="""Date when the supply of the goods and services is performed.
|
||||
You can set this date to when you want ZATCA to recognize the VAT Due Liability as ZATCA will consider the earlier of this date and the Issue Date.
|
||||
In case of multiple deliveries, you should take the date of the latest one.""")
|
||||
l10n_sa_show_delivery_date = fields.Boolean(compute='_compute_show_delivery_date')
|
||||
l10n_sa_qr_code_str = fields.Char(string='Zatka QR Code', compute='_compute_qr_code_str')
|
||||
l10n_sa_confirmation_datetime = fields.Datetime(string='Confirmation Date',
|
||||
readonly=True,
|
||||
copy=False,
|
||||
help="""Date when the invoice is confirmed and posted.
|
||||
In other words, it is the date on which the invoice is generated as final document (after securing all internal approvals).""")
|
||||
|
||||
@api.depends('country_code', 'move_type')
|
||||
def _compute_show_delivery_date(self):
|
||||
for move in self:
|
||||
move.l10n_sa_show_delivery_date = move.country_code == 'SA' and move.move_type in ('out_invoice', 'out_refund')
|
||||
|
||||
@api.depends('amount_total_signed', 'amount_tax_signed', 'l10n_sa_confirmation_datetime', 'company_id', 'company_id.vat')
|
||||
def _compute_qr_code_str(self):
|
||||
""" Generate the qr code for Saudi e-invoicing. Specs are available at the following link at page 23
|
||||
https://zatca.gov.sa/ar/E-Invoicing/SystemsDevelopers/Documents/20210528_ZATCA_Electronic_Invoice_Security_Features_Implementation_Standards_vShared.pdf
|
||||
"""
|
||||
def get_qr_encoding(tag, field):
|
||||
company_name_byte_array = field.encode()
|
||||
company_name_tag_encoding = tag.to_bytes(length=1, byteorder='big')
|
||||
company_name_length_encoding = len(company_name_byte_array).to_bytes(length=1, byteorder='big')
|
||||
return company_name_tag_encoding + company_name_length_encoding + company_name_byte_array
|
||||
|
||||
for record in self:
|
||||
qr_code_str = ''
|
||||
if record.l10n_sa_confirmation_datetime and record.company_id.vat:
|
||||
seller_name_enc = get_qr_encoding(1, record.company_id.display_name)
|
||||
company_vat_enc = get_qr_encoding(2, record.company_id.vat)
|
||||
time_sa = fields.Datetime.context_timestamp(self.with_context(tz='Asia/Riyadh'), record.l10n_sa_confirmation_datetime)
|
||||
timestamp_enc = get_qr_encoding(3, time_sa.isoformat())
|
||||
totals = record._get_l10n_sa_totals()
|
||||
invoice_total_enc = get_qr_encoding(4, float_repr(abs(totals['total_amount']), 2))
|
||||
total_vat_enc = get_qr_encoding(5, float_repr(abs(totals['total_tax']), 2))
|
||||
|
||||
str_to_encode = seller_name_enc + company_vat_enc + timestamp_enc + invoice_total_enc + total_vat_enc
|
||||
qr_code_str = base64.b64encode(str_to_encode).decode()
|
||||
record.l10n_sa_qr_code_str = qr_code_str
|
||||
|
||||
def _post(self, soft=True):
|
||||
res = super()._post(soft)
|
||||
for record in self:
|
||||
if record.country_code == 'SA' and record.move_type in ('out_invoice', 'out_refund'):
|
||||
if not record.l10n_sa_show_delivery_date:
|
||||
raise UserError(_('Delivery Date cannot be empty'))
|
||||
if not record.l10n_sa_confirmation_datetime:
|
||||
record.l10n_sa_confirmation_datetime = fields.Datetime.now()
|
||||
return res
|
||||
|
||||
def get_l10n_sa_confirmation_datetime_sa_tz(self):
|
||||
self.ensure_one()
|
||||
return format_datetime(self.env, self.l10n_sa_confirmation_datetime, tz='Asia/Riyadh', dt_format='Y-MM-dd\nHH:mm:ss')
|
||||
|
||||
def _l10n_sa_reset_confirmation_datetime(self):
|
||||
self.filtered(lambda m: m.country_code == 'SA').l10n_sa_confirmation_datetime = False
|
||||
|
||||
def button_draft(self):
|
||||
self._l10n_sa_reset_confirmation_datetime()
|
||||
super().button_draft()
|
||||
|
||||
def _get_l10n_sa_totals(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'total_amount': self.amount_total_signed,
|
||||
'total_tax': self.amount_tax_signed,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue