219 lines
9.9 KiB
Python
219 lines
9.9 KiB
Python
from odoo import api, fields, models
|
|
|
|
from odoo.addons.l10n_gr_edi.models.preferred_classification import (
|
|
CLASSIFICATION_CATEGORY_SELECTION,
|
|
CLASSIFICATION_MAP,
|
|
CLASSIFICATION_TYPE_SELECTION,
|
|
CLASSIFICATION_VAT_SELECTION,
|
|
TAX_EXEMPTION_CATEGORY_SELECTION,
|
|
TYPES_WITH_SEND_EXPENSE,
|
|
)
|
|
from odoo.tools.sql import column_exists, create_column
|
|
|
|
|
|
class AccountMoveLine(models.Model):
|
|
_inherit = 'account.move.line'
|
|
|
|
l10n_gr_edi_available_cls_category = fields.Char(compute='_compute_l10n_gr_edi_available_cls_category')
|
|
l10n_gr_edi_available_cls_type = fields.Char(compute='_compute_l10n_gr_edi_available_cls_type')
|
|
l10n_gr_edi_available_cls_vat = fields.Char(compute='_compute_l10n_gr_edi_available_cls_type')
|
|
l10n_gr_edi_need_exemption_category = fields.Boolean(compute='_compute_l10n_gr_edi_need_exemption_category', default=False)
|
|
|
|
l10n_gr_edi_detail_type = fields.Selection(
|
|
selection=[('1', '1'), ('2', '2')],
|
|
string='Detail Type',
|
|
compute='_compute_l10n_gr_edi_detail_type',
|
|
store=True,
|
|
readonly=False,
|
|
)
|
|
l10n_gr_edi_cls_category = fields.Selection(
|
|
selection=CLASSIFICATION_CATEGORY_SELECTION,
|
|
string='myDATA Category',
|
|
compute='_compute_l10n_gr_edi_cls_category',
|
|
store=True,
|
|
readonly=False,
|
|
)
|
|
l10n_gr_edi_cls_type = fields.Selection(
|
|
selection=CLASSIFICATION_TYPE_SELECTION,
|
|
string='myDATA Type',
|
|
compute='_compute_l10n_gr_edi_cls_type',
|
|
store=True,
|
|
readonly=False,
|
|
)
|
|
l10n_gr_edi_cls_vat = fields.Selection(
|
|
selection=CLASSIFICATION_VAT_SELECTION,
|
|
string='VAT Classification',
|
|
compute='_compute_l10n_gr_edi_cls_vat',
|
|
store=True,
|
|
readonly=False,
|
|
)
|
|
l10n_gr_edi_tax_exemption_category = fields.Selection(
|
|
selection=TAX_EXEMPTION_CATEGORY_SELECTION,
|
|
string='Tax Exemption Category',
|
|
compute='_compute_l10n_gr_edi_tax_exemption_category',
|
|
store=True,
|
|
readonly=False,
|
|
)
|
|
|
|
def _auto_init(self):
|
|
"""
|
|
Create all compute-stored fields here to avoid MemoryError when initializing on large databases.
|
|
"""
|
|
for column_name, column_type in (
|
|
('l10n_gr_edi_detail_type', 'varchar'),
|
|
('l10n_gr_edi_cls_category', 'varchar'),
|
|
('l10n_gr_edi_cls_type', 'varchar'),
|
|
('l10n_gr_edi_cls_vat', 'varchar'),
|
|
('l10n_gr_edi_tax_exemption_category', 'varchar'),
|
|
):
|
|
if not column_exists(self.env.cr, 'account_move_line', column_name):
|
|
create_column(self.env.cr, 'account_move_line', column_name, column_type)
|
|
|
|
return super()._auto_init()
|
|
|
|
@api.depends('move_id.l10n_gr_edi_inv_type')
|
|
def _compute_l10n_gr_edi_detail_type(self):
|
|
self.l10n_gr_edi_detail_type = False
|
|
|
|
@api.depends(
|
|
'move_id.l10n_gr_edi_inv_type',
|
|
'move_id.l10n_gr_edi_correlation_id',
|
|
'l10n_gr_edi_detail_type',
|
|
)
|
|
def _compute_l10n_gr_edi_available_cls_category(self):
|
|
for line in self:
|
|
inv_type = line.move_id.l10n_gr_edi_inv_type
|
|
|
|
# we need inv_type to calculate available_cls_category
|
|
if not inv_type or (
|
|
inv_type
|
|
and CLASSIFICATION_MAP[inv_type] == 'associate'
|
|
and not line.move_id.l10n_gr_edi_correlation_id
|
|
): # associate inv_type must have a correlation_id, otherwise inv_type is considered empty
|
|
line.l10n_gr_edi_available_cls_category = False
|
|
continue
|
|
|
|
if CLASSIFICATION_MAP[inv_type] == 'associate':
|
|
inv_type = line.move_id.l10n_gr_edi_correlation_id.l10n_gr_edi_inv_type
|
|
|
|
is_income = (
|
|
line.move_type in ('out_invoice', 'out_refund')
|
|
and inv_type not in TYPES_WITH_SEND_EXPENSE
|
|
and (not line.l10n_gr_edi_detail_type or line.l10n_gr_edi_detail_type == '2')
|
|
)
|
|
|
|
line.l10n_gr_edi_available_cls_category = self.env['l10n_gr_edi.preferred_classification']._get_l10n_gr_edi_available_cls_category(
|
|
inv_type=inv_type, category_type='1' if is_income else '2')
|
|
|
|
@api.depends('l10n_gr_edi_cls_category', 'move_id.l10n_gr_edi_correlation_id')
|
|
def _compute_l10n_gr_edi_available_cls_type(self):
|
|
for line in self:
|
|
inv_type = line.move_id.l10n_gr_edi_inv_type
|
|
cls_category = line.l10n_gr_edi_cls_category
|
|
|
|
if inv_type and CLASSIFICATION_MAP[inv_type] == 'associate' and line.move_id.l10n_gr_edi_correlation_id:
|
|
inv_type = line.move_id.l10n_gr_edi_correlation_id.l10n_gr_edi_inv_type
|
|
|
|
if cls_category:
|
|
line.l10n_gr_edi_available_cls_type = self.env['l10n_gr_edi.preferred_classification']._get_l10n_gr_edi_available_cls_type(inv_type, cls_category)
|
|
line.l10n_gr_edi_available_cls_vat = self.env['l10n_gr_edi.preferred_classification']._get_l10n_gr_edi_available_cls_vat(inv_type, cls_category)
|
|
else:
|
|
line.l10n_gr_edi_available_cls_type = False
|
|
line.l10n_gr_edi_available_cls_vat = False
|
|
|
|
def _l10n_gr_edi_get_preferred_classification_id(self, with_category=False):
|
|
self.ensure_one()
|
|
if with_category: # for _compute_l10n_gr_edi_cls_type
|
|
domain = [
|
|
('l10n_gr_edi_inv_type', '=', self.move_id.l10n_gr_edi_inv_type),
|
|
('l10n_gr_edi_cls_category', '=', self.l10n_gr_edi_cls_category),
|
|
('l10n_gr_edi_cls_type', 'in', self.l10n_gr_edi_available_cls_type.split(',')),
|
|
]
|
|
else: # for _compute_l10n_gr_edi_cls_category
|
|
domain = [
|
|
('l10n_gr_edi_inv_type', '=', self.move_id.l10n_gr_edi_inv_type),
|
|
('l10n_gr_edi_cls_category', 'in', self.l10n_gr_edi_available_cls_category.split(',')),
|
|
]
|
|
|
|
preferred_id = self.env['l10n_gr_edi.preferred_classification']
|
|
# Try to get from the move's fiscal position first
|
|
if self.move_id.fiscal_position_id:
|
|
preferred_id = self.move_id.fiscal_position_id.l10n_gr_edi_preferred_classification_ids.filtered_domain(domain)[:1]
|
|
# If nothing is found, try to get preferred classification from the line's product
|
|
if not preferred_id and self.product_id:
|
|
preferred_id = self.product_id.product_tmpl_id.l10n_gr_edi_preferred_classification_ids.filtered_domain(domain)[:1]
|
|
|
|
# If by the end nothing is still found, set the default preferred classification as [ 1.1 inv-type | 1.2 category | E3_561_007 type ]
|
|
if not preferred_id:
|
|
preferred_id = self.env.ref('l10n_gr_edi.default_preferred_classification', raise_if_not_found=False)
|
|
if not preferred_id:
|
|
preferred_id = self.env['l10n_gr_edi.preferred_classification'].create([{
|
|
'l10n_gr_edi_inv_type': '1.1',
|
|
'l10n_gr_edi_cls_category': 'category1_2',
|
|
'l10n_gr_edi_cls_type': 'E3_561_007',
|
|
}])
|
|
# Save the newly made preferred cls so that we don't have to create a new one everytime.
|
|
self.env['ir.model.data'].create([{
|
|
'name': 'default_preferred_classification',
|
|
'module': 'l10n_gr_edi',
|
|
'model': 'l10n_gr_edi.preferred_classification',
|
|
'res_id': preferred_id.id,
|
|
'noupdate': True,
|
|
}])
|
|
|
|
return preferred_id
|
|
|
|
@api.depends(
|
|
'move_id.l10n_gr_edi_inv_type',
|
|
'l10n_gr_edi_available_cls_category',
|
|
'product_id',
|
|
)
|
|
def _compute_l10n_gr_edi_cls_category(self):
|
|
for line in self:
|
|
if not line.l10n_gr_edi_available_cls_category:
|
|
line.l10n_gr_edi_cls_category = False
|
|
elif preferred_id := line._l10n_gr_edi_get_preferred_classification_id():
|
|
line.l10n_gr_edi_cls_category = preferred_id.l10n_gr_edi_cls_category
|
|
elif line.l10n_gr_edi_cls_category and line.l10n_gr_edi_cls_category in line.l10n_gr_edi_available_cls_category:
|
|
line.l10n_gr_edi_cls_category = line.l10n_gr_edi_cls_category
|
|
else:
|
|
line.l10n_gr_edi_cls_category = False
|
|
|
|
@api.depends(
|
|
'move_id.l10n_gr_edi_inv_type',
|
|
'l10n_gr_edi_available_cls_type',
|
|
'product_id',
|
|
)
|
|
def _compute_l10n_gr_edi_cls_type(self):
|
|
for line in self:
|
|
if not line.l10n_gr_edi_available_cls_type:
|
|
line.l10n_gr_edi_cls_type = False
|
|
elif preferred_id := line._l10n_gr_edi_get_preferred_classification_id(with_category=True):
|
|
line.l10n_gr_edi_cls_type = preferred_id.l10n_gr_edi_cls_type
|
|
elif line.l10n_gr_edi_cls_type and line.l10n_gr_edi_cls_type in line.l10n_gr_edi_available_cls_type:
|
|
line.l10n_gr_edi_cls_type = line.l10n_gr_edi_cls_type
|
|
else:
|
|
line.l10n_gr_edi_cls_type = False
|
|
|
|
@api.depends('l10n_gr_edi_available_cls_vat')
|
|
def _compute_l10n_gr_edi_cls_vat(self):
|
|
self.l10n_gr_edi_cls_vat = False
|
|
|
|
@api.depends('tax_ids')
|
|
def _compute_l10n_gr_edi_need_exemption_category(self):
|
|
for line in self:
|
|
taxes = line.tax_ids.flatten_taxes_hierarchy()
|
|
line.l10n_gr_edi_need_exemption_category = len(taxes) == 1 and taxes.amount == 0
|
|
|
|
@api.depends('tax_ids')
|
|
def _compute_l10n_gr_edi_tax_exemption_category(self):
|
|
for line in self:
|
|
taxes = line.tax_ids.flatten_taxes_hierarchy()
|
|
if line.move_id.country_code == 'GR' and len(taxes) == 1 and taxes.amount == 0:
|
|
if line.l10n_gr_edi_tax_exemption_category:
|
|
line.l10n_gr_edi_tax_exemption_category = line.l10n_gr_edi_tax_exemption_category
|
|
else:
|
|
line.l10n_gr_edi_tax_exemption_category = taxes.l10n_gr_edi_default_tax_exemption_category or '1'
|
|
else:
|
|
line.l10n_gr_edi_tax_exemption_category = False
|