diff --git a/intrastat_product/__openerp__.py b/intrastat_product/__openerp__.py
index 33c2510..77209d7 100644
--- a/intrastat_product/__openerp__.py
+++ b/intrastat_product/__openerp__.py
@@ -32,6 +32,7 @@
'depends': [
'intrastat_base',
'product_harmonized_system',
+ 'stock_picking_invoice_link',
'sale_stock',
'purchase',
],
diff --git a/intrastat_product/models/account_invoice.py b/intrastat_product/models/account_invoice.py
index 5c5da02..0a26870 100644
--- a/intrastat_product/models/account_invoice.py
+++ b/intrastat_product/models/account_invoice.py
@@ -44,12 +44,20 @@ class AccountInvoice(models.Model):
'res.country', string='Origin/Destination Country',
ondelete='restrict')
intrastat_country = fields.Boolean(
- related='src_dest_country_id.intrastat',
+ compute='_compute_intrastat_country',
store=True, string='Intrastat Country', readonly=True)
intrastat = fields.Char(
string='Intrastat Declaration',
related='company_id.intrastat', readonly=True)
+ @api.multi
+ @api.depends('src_dest_country_id', 'partner_id.country_id')
+ def _compute_intrastat_country(self):
+ for inv in self:
+ country = inv.src_dest_country_id \
+ or inv.partner_id.country_id
+ inv.intrastat_country = country.intrastat
+
@api.model
def _default_intrastat_transaction(self):
""" placeholder for localisation modules """
diff --git a/intrastat_product/models/intrastat_product_declaration.py b/intrastat_product/models/intrastat_product_declaration.py
index 82f7c23..7631959 100644
--- a/intrastat_product/models/intrastat_product_declaration.py
+++ b/intrastat_product/models/intrastat_product_declaration.py
@@ -158,9 +158,8 @@ class IntrastatProductDeclaration(models.Model):
num_decl_lines = fields.Integer(
compute='_compute_numbers', string='Number of Declaration Lines',
store=True, track_visibility='onchange')
- total_amount = fields.Float(
- compute='_compute_numbers', digits=dp.get_precision('Account'),
- string='Total Fiscal Amount', store=True,
+ total_amount = fields.Integer(
+ compute='_compute_numbers', string='Total Fiscal Amount', store=True,
help="Total fiscal amount in company currency of the declaration.")
currency_id = fields.Many2one(
'res.currency', related='company_id.currency_id', readonly=True,
@@ -269,7 +268,7 @@ class IntrastatProductDeclaration(models.Model):
note = "\n" + _(
"Missing unit of measure on the line with %d "
"product(s) '%s' on invoice '%s'."
- ) % (line_qty, product.name, invoice.number)
+ ) % (line_qty, product.name_get()[0][1], invoice.number)
note += "\n" + _(
"Please adjust this line manually.")
self._note += note
@@ -330,8 +329,8 @@ class IntrastatProductDeclaration(models.Model):
else:
note = "\n" + _(
"Conversion from unit of measure '%s' to 'Kg' "
- "is not implemented yet."
- ) % source_uom.name
+ "is not implemented yet. It is needed for product '%s'."
+ ) % (source_uom.name, product.name_get()[0][1])
note += "\n" + _(
"Please correct the unit of measure settings and "
"regenerate the lines or adjust the impacted lines "
@@ -351,30 +350,44 @@ class IntrastatProductDeclaration(models.Model):
def _get_region(self, inv_line):
"""
- Logic copied from standard addons
+ For supplier invoices/refunds: if the invoice line is linked
+ to a stock move, use the destination stock location ;
+ otherwise, get the PO (which is linked to a stock location)
+ and then get the warehouse.
+ It is important to take into account the following scenario:
+ I order a qty of 50 kg and my suppliers delivers and invoices 52 kg
+ (quite common in some industries where the order qty cannot be exact
+ due to some operational constraints) ; in this case, I have a qty of
+ 2 kg which is not linked to a PO, but it is linked to a stock move.
- If purchase, comes from purchase order, linked to a location,
- which is linked to the warehouse.
+ For customer invoices/refunds: if the invoice line is linked to a
+ stock move, use the source stock location ;
+ otherwise, get the sale order, which is linked to the warehouse.
- If sales, the sale order is linked to the warehouse.
- If sales, from a delivery order, linked to a location,
- which is linked to the warehouse.
+ If none found, get the company's default intrastat region.
- If none found, get the company one.
"""
region = False
if inv_line.invoice_id.type in ('in_invoice', 'in_refund'):
- po_lines = self.env['purchase.order.line'].search(
- [('invoice_lines', 'in', inv_line.id)])
- if po_lines:
- po = po_lines.order_id
- region = po.location_id.get_intrastat_region()
+ if inv_line.move_line_ids:
+ region = inv_line.move_line_ids[0].location_dest_id.\
+ get_intrastat_region()
+ else:
+ po_lines = self.env['purchase.order.line'].search(
+ [('invoice_lines', 'in', inv_line.id)])
+ if po_lines:
+ po = po_lines.order_id
+ region = po.location_id.get_intrastat_region()
elif inv_line.invoice_id.type in ('out_invoice', 'out_refund'):
- so_lines = self.env['sale.order.line'].search(
- [('invoice_lines', 'in', inv_line.id)])
- if so_lines:
- so = so_lines.order_id
- region = so.warehouse_id.region_id
+ if inv_line.move_line_ids:
+ region = inv_line.move_line_ids[0].location_id.\
+ get_intrastat_region()
+ else:
+ so_lines = self.env['sale.order.line'].search(
+ [('invoice_lines', 'in', inv_line.id)])
+ if so_lines:
+ so = so_lines.order_id
+ region = so.warehouse_id.region_id
if not region:
if self.company_id.intrastat_region_id:
region = self.company_id.intrastat_region_id
@@ -411,20 +424,32 @@ class IntrastatProductDeclaration(models.Model):
def _handle_invoice_accessory_cost(
self, invoice, lines_current_invoice,
- total_inv_accessory_costs_cc, total_inv_product_cc):
+ total_inv_accessory_costs_cc, total_inv_product_cc,
+ total_inv_weight):
"""
- Affect accessory costs pro-rata of the value.
+ Affect accessory costs pro-rata of the value
+ (or pro-rata of the weight is the goods of the invoice
+ have no value)
This method allows to implement a different logic
in the localization modules.
E.g. in Belgium accessory cost should not be added.
"""
- if total_inv_accessory_costs_cc and total_inv_product_cc:
- for ac_line_vals in lines_current_invoice:
- ac_line_vals['amount_accessory_cost_company_currency'] = (
- total_inv_accessory_costs_cc *
- ac_line_vals['amount_company_currency'] /
- total_inv_product_cc)
+ if total_inv_accessory_costs_cc:
+ if total_inv_product_cc:
+ # pro-rata of the value
+ for ac_line_vals in lines_current_invoice:
+ ac_line_vals['amount_accessory_cost_company_currency'] = (
+ total_inv_accessory_costs_cc *
+ ac_line_vals['amount_company_currency'] /
+ total_inv_product_cc)
+ else:
+ # pro-rata of the weight
+ for ac_line_vals in lines_current_invoice:
+ ac_line_vals['amount_accessory_cost_company_currency'] = (
+ total_inv_accessory_costs_cc *
+ ac_line_vals['weight'] /
+ total_inv_weight)
def _prepare_invoice_domain(self):
start_date = date(self.year, self.month, 1)
@@ -441,6 +466,14 @@ class IntrastatProductDeclaration(models.Model):
domain.append(('type', 'in', ('out_invoice', 'out_refund')))
return domain
+ def _is_product(self, invoice_line):
+ if (
+ invoice_line.product_id and
+ invoice_line.product_id.type in ('product', 'consu')):
+ return True
+ else:
+ return False
+
def _gather_invoices(self):
lines = []
@@ -454,6 +487,7 @@ class IntrastatProductDeclaration(models.Model):
lines_current_invoice = []
total_inv_accessory_costs_cc = 0.0 # in company currency
total_inv_product_cc = 0.0 # in company currency
+ total_inv_weight = 0.0
for inv_line in invoice.invoice_line:
if (
@@ -474,18 +508,12 @@ class IntrastatProductDeclaration(models.Model):
'of invoice %s. Reason: qty = 0'
% (inv_line.name, inv_line.quantity, invoice.number))
continue
- if not inv_line.price_subtotal:
- _logger.info(
- 'Skipping invoice line %s qty %s '
- 'of invoice %s. Reason: price_subtotal = 0'
- % (inv_line.name, inv_line.quantity, invoice.number))
- continue
partner_country = self._get_partner_country(inv_line)
if not partner_country:
_logger.info(
- 'Skipping invoice line %s qty %s'
- 'of invoice %s. Reason: not partner_country'
+ 'Skipping invoice line %s qty %s '
+ 'of invoice %s. Reason: no partner_country'
% (inv_line.name, inv_line.quantity, invoice.number))
continue
@@ -501,9 +529,7 @@ class IntrastatProductDeclaration(models.Model):
if inv_line.hs_code_id:
hs_code = inv_line.hs_code_id
- elif (
- inv_line.product_id and
- inv_line.product_id.type in ('product', 'consu')):
+ elif inv_line.product_id and self._is_product(inv_line):
hs_code = inv_line.product_id.product_tmpl_id.\
get_hs_code_recursively()
if not hs_code:
@@ -526,6 +552,7 @@ class IntrastatProductDeclaration(models.Model):
weight, suppl_unit_qty = self._get_weight_and_supplunits(
inv_line, hs_code)
+ total_inv_weight += weight
amount_company_currency = self._get_amount(inv_line)
total_inv_product_cc += amount_company_currency
@@ -564,9 +591,24 @@ class IntrastatProductDeclaration(models.Model):
self._handle_invoice_accessory_cost(
invoice, lines_current_invoice,
- total_inv_accessory_costs_cc, total_inv_product_cc)
+ total_inv_accessory_costs_cc, total_inv_product_cc,
+ total_inv_weight)
- lines += lines_current_invoice
+ for line_vals in lines_current_invoice:
+ if (
+ not line_vals['amount_company_currency'] and
+ not
+ line_vals['amount_accessory_cost_company_currency']):
+ inv_line = self.env['account.invoice.line'].browse(
+ line_vals['invoice_line_id'])
+ _logger.info(
+ 'Skipping invoice line %s qty %s '
+ 'of invoice %s. Reason: price_subtotal = 0 '
+ 'and accessory costs = 0'
+ % (inv_line.name, inv_line.quantity,
+ inv_line.invoice_id.number))
+ continue
+ lines.append(line_vals)
return lines
diff --git a/intrastat_product/models/stock_warehouse.py b/intrastat_product/models/stock_warehouse.py
index 27b269c..90509b8 100644
--- a/intrastat_product/models/stock_warehouse.py
+++ b/intrastat_product/models/stock_warehouse.py
@@ -40,9 +40,9 @@ class StockLocation(models.Model):
locations = self.search(
[('parent_left', '<=', self.parent_left),
('parent_right', '>=', self.parent_right)])
- warehouses = self.search(
- [('lot_stock_id', 'in', [x.id for x in locations]),
- ('region_id', '!=', False)])
+ warehouses = self.env['stock.warehouse'].search([
+ ('lot_stock_id', 'in', [x.id for x in locations]),
+ ('region_id', '!=', False)])
if warehouses:
return warehouses[0].region_id
return None
diff --git a/intrastat_product/security/ir.model.access.csv b/intrastat_product/security/ir.model.access.csv
index 4b06ab2..bd1ca7c 100644
--- a/intrastat_product/security/ir.model.access.csv
+++ b/intrastat_product/security/ir.model.access.csv
@@ -7,6 +7,7 @@ access_intrastat_transport_mode_read,Read access on Intrastat Transport Modes to
access_intrastat_transport_mode_full,Full access on Intrastat Transport Modes to Finance manager,model_intrastat_transport_mode,account.group_account_manager,1,1,1,1
access_intrastat_region_read,Read access on Intrastat Regions,model_intrastat_region,,1,0,0,0
access_intrastat_region_full,Full access on Intrastat Regions,model_intrastat_region,account.group_account_manager,1,1,1,1
+access_hs_code_financial_mgr_full,Full access on H.S. Code to financial mgr,product_harmonized_system.model_hs_code,account.group_account_manager,1,1,1,1
access_intrastat_product_declaration,Full access on Intrastat Product Declarations to Accountant,model_intrastat_product_declaration,account.group_account_user,1,1,1,1
access_intrastat_product_computation_line,Full access on Intrastat Product Computation Lines to Accountant,model_intrastat_product_computation_line,account.group_account_user,1,1,1,1
access_intrastat_product_declaration_line,Full access on Intrastat Product Declaration Lines to Accountant,model_intrastat_product_declaration_line,account.group_account_user,1,1,1,1
diff --git a/intrastat_product/views/intrastat_product_declaration.xml b/intrastat_product/views/intrastat_product_declaration.xml
index 52e0693..6805b58 100644
--- a/intrastat_product/views/intrastat_product_declaration.xml
+++ b/intrastat_product/views/intrastat_product_declaration.xml
@@ -188,6 +188,8 @@
+