From 6cfc6f6d8aaad56042da1026a84707e39ec55377 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 10 Nov 2015 21:36:50 +0100 Subject: [PATCH] [IMP+FIX] intrastat_product: Several things: * Add product_origin_country_id on declaration/computation lines Copy incoterms and destination country from SO to invoice when invoicing from SO We need weight even when supplementary units is used Small cleanups and enhancements * Add support for accessory costs Add default values for intrastat transaction on company Code cleanup * If rounded weight is 0, put 1 Take into account the taxes for B2C Small code cleanup * Remove field exclude_from_intrastat Re-organise view of intrastat.product.declaration * Add option intrastat_accessory_costs on company Set more fields as invisible (localisation should put them visible if they need it) Fix handling of suppl. units when hs_code is empty on invoice line (but set on product) Small usability enhancements * Include selection of type of invoice in search, for better perf Isolate domain in a _prepare method, for easier inheritance WARNING: I changed the default selection of invoice type ; adapt it in your localization m odule if necessary Add intrastat_transaction_in_refund for company (not needed for France, but may be needed elsewhere) Add a log when an invoice line is skipped * Include product code in warning msg on weight * Inspired by the PR https://github.com/akretion/account-financial-reporting/pull/8 of Luc de Meyer --- intrastat_product/__init__.py | 2 +- intrastat_product/__openerp__.py | 5 +- intrastat_product/demo/intrastat_demo.xml | 7 + intrastat_product/models/__init__.py | 3 +- intrastat_product/models/account_invoice.py | 2 +- intrastat_product/models/hs_code.py | 2 +- .../models/intrastat_product_declaration.py | 295 +++++++++++++----- intrastat_product/models/intrastat_region.py | 2 +- .../models/intrastat_transaction.py | 5 +- .../models/intrastat_transport_mode.py | 2 +- intrastat_product/models/intrastat_unit.py | 2 +- intrastat_product/models/res_company.py | 20 +- intrastat_product/models/sale_order.py | 37 +++ intrastat_product/models/stock_picking.py | 2 +- intrastat_product/models/stock_warehouse.py | 18 +- .../views/intrastat_product_declaration.xml | 185 +++++++---- intrastat_product/views/res_company.xml | 8 +- intrastat_product/views/stock_warehouse.xml | 4 +- 18 files changed, 437 insertions(+), 164 deletions(-) create mode 100644 intrastat_product/models/sale_order.py diff --git a/intrastat_product/__init__.py b/intrastat_product/__init__.py index 21ff7c2..cde864b 100644 --- a/intrastat_product/__init__.py +++ b/intrastat_product/__init__.py @@ -1,3 +1,3 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- from . import models diff --git a/intrastat_product/__openerp__.py b/intrastat_product/__openerp__.py index b9576da..33c2510 100644 --- a/intrastat_product/__openerp__.py +++ b/intrastat_product/__openerp__.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat Product module for Odoo @@ -32,7 +32,8 @@ 'depends': [ 'intrastat_base', 'product_harmonized_system', - 'stock', + 'sale_stock', + 'purchase', ], 'conflicts': ['report_intrastat'], 'data': [ diff --git a/intrastat_product/demo/intrastat_demo.xml b/intrastat_product/demo/intrastat_demo.xml index 61b1c39..cf9d66d 100644 --- a/intrastat_product/demo/intrastat_demo.xml +++ b/intrastat_product/demo/intrastat_demo.xml @@ -17,5 +17,12 @@ + + extended + extended + + + + diff --git a/intrastat_product/models/__init__.py b/intrastat_product/models/__init__.py index 66c0d7b..b62d055 100644 --- a/intrastat_product/models/__init__.py +++ b/intrastat_product/models/__init__.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- from . import account_invoice from . import hs_code from . import intrastat_product_declaration @@ -7,5 +7,6 @@ from . import intrastat_transaction from . import intrastat_transport_mode from . import intrastat_unit from . import res_company +from . import sale_order from . import stock_picking from . import stock_warehouse diff --git a/intrastat_product/models/account_invoice.py b/intrastat_product/models/account_invoice.py index 74f713a..b488466 100644 --- a/intrastat_product/models/account_invoice.py +++ b/intrastat_product/models/account_invoice.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat Product module for Odoo diff --git a/intrastat_product/models/hs_code.py b/intrastat_product/models/hs_code.py index 6e23770..a4ae30b 100644 --- a/intrastat_product/models/hs_code.py +++ b/intrastat_product/models/hs_code.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat Product module for Odoo diff --git a/intrastat_product/models/intrastat_product_declaration.py b/intrastat_product/models/intrastat_product_declaration.py index 4dfc52b..ef02f3b 100644 --- a/intrastat_product/models/intrastat_product_declaration.py +++ b/intrastat_product/models/intrastat_product_declaration.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat Product module for Odoo @@ -23,7 +23,8 @@ ############################################################################## from openerp import models, fields, api, _ -from openerp.exceptions import RedirectWarning, ValidationError, Warning +from openerp.exceptions import RedirectWarning, ValidationError +from openerp.exceptions import Warning as UserError import openerp.addons.decimal_precision as dp from datetime import datetime, date from dateutil.relativedelta import relativedelta @@ -129,13 +130,13 @@ class IntrastatProductDeclaration(models.Model): ], string='Month', required=True, default=_get_month) year_month = fields.Char( - compute='_compute_year_month', string='Month', readonly=True, - track_visibility='always', store=True, + compute='_compute_year_month', string='Period', readonly=True, + track_visibility='onchange', store=True, help="Year and month of the declaration.") type = fields.Selection( '_get_type', string='Type', required=True, states={'done': [('readonly', True)]}, - track_visibility='always', help="Select the declaration type.") + track_visibility='onchange', help="Select the declaration type.") action = fields.Selection( '_get_action', string='Action', required=True, @@ -159,8 +160,8 @@ class IntrastatProductDeclaration(models.Model): store=True, track_visibility='onchange') total_amount = fields.Float( compute='_compute_numbers', digits=dp.get_precision('Account'), - string='Total Amount', store=True, - help="Total amount in company currency of the declaration.") + 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, string='Currency') @@ -240,13 +241,23 @@ class IntrastatProductDeclaration(models.Model): return country def _get_intrastat_transaction(self, inv_line): - return inv_line.invoice_id.intrastat_transaction_id + invoice = inv_line.invoice_id + if invoice.intrastat_transaction_id: + return invoice.intrastat_transaction_id + else: + company = invoice.company_id + if invoice.type == 'out_invoice': + return company.intrastat_transaction_out_invoice + elif invoice.type == 'out_refund': + return company.intrastat_transaction_out_refund + elif invoice.type == 'in_invoice': + return company.intrastat_transaction_in_invoice - def _get_weight_and_supplunits(self, inv_line): + def _get_weight_and_supplunits(self, inv_line, hs_code): line_qty = inv_line.quantity product = inv_line.product_id invoice = inv_line.invoice_id - intrastat_unit_id = inv_line.hs_code_id.intrastat_unit_id + intrastat_unit_id = hs_code.intrastat_unit_id source_uom = inv_line.uos_id weight_uom_categ = self._uom_refs['weight_uom_categ'] kg_uom = self._uom_refs['kg_uom'] @@ -273,7 +284,7 @@ class IntrastatProductDeclaration(models.Model): ) % intrastat_unit_id.name note += "\n" + _( "Please correct the Intrastat Supplementary Unit " - "settingsand regenerate the lines or adjust the lines " + "settings and regenerate the lines or adjust the lines " "with Intrastat Code '%s' manually" ) % inv_line.hs_code_id.local_code self._note += note @@ -293,58 +304,54 @@ class IntrastatProductDeclaration(models.Model): self._note += note return weight, suppl_unit_qty - else: - if source_uom == kg_uom: - weight = line_qty - elif source_uom.category_id == weight_uom_categ: - weight = self.env['product.uom']._compute_qty_obj( - source_uom, line_qty, kg_uom) - elif source_uom.category_id == pce_uom_categ: - if not product.weight_net: - note = "\n" + _( - "Missing net weight on product '%s'." - ) % product.name - note += "\n" + _( - "Please correct the product record and regenerate " - "the lines or adjust the impacted lines manually") - self._note += note - return weight, suppl_unit_qty - if source_uom == pce_uom: - weight = product.weight_net * line_qty - else: - # Here, I suppose that, on the product, the - # weight is per PCE and not per uom_id - weight = product.weight_net * \ - self.env['product.uom']._compute_qty_obj( - source_uom, line_qty, pce_uom) - else: + if source_uom == kg_uom: + weight = line_qty + elif source_uom.category_id == weight_uom_categ: + weight = self.env['product.uom']._compute_qty_obj( + source_uom, line_qty, kg_uom) + elif source_uom.category_id == pce_uom_categ: + if not product.weight_net: note = "\n" + _( - "Conversion from unit of measure '%s' to 'Kg' " - "is not implemented yet." - ) % source_uom.name + "Missing net weight on product %s." + ) % product.name_get()[0][1] note += "\n" + _( - "Please correct the unit of measure settings and " - "regenerate the lines or adjust the impacted lines " - "manually") + "Please correct the product record and regenerate " + "the lines or adjust the impacted lines manually") self._note += note return weight, suppl_unit_qty + if source_uom == pce_uom: + weight = product.weight_net * line_qty + else: + # Here, I suppose that, on the product, the + # weight is per PCE and not per uom_id + weight = product.weight_net * \ + self.env['product.uom']._compute_qty_obj( + source_uom, line_qty, pce_uom) + else: + note = "\n" + _( + "Conversion from unit of measure '%s' to 'Kg' " + "is not implemented yet." + ) % source_uom.name + note += "\n" + _( + "Please correct the unit of measure settings and " + "regenerate the lines or adjust the impacted lines " + "manually") + self._note += note + return weight, suppl_unit_qty return weight, suppl_unit_qty def _get_amount(self, inv_line): invoice = inv_line.invoice_id - amount = inv_line.price_subtotal - if invoice.currency_id.name != 'EUR': - amount = self.env['res.currency'].with_context( - date=invoice.date_invoice).compute( - invoice.currency_id, - self.company_id.currency_id, - amount) + amount = invoice.currency_id.with_context( + date=invoice.date_invoice).compute( + inv_line.price_subtotal, + self.company_id.currency_id) return amount def _get_region(self, inv_line): """ - Logic copied from standard addons, l10n_be_intrastat module: + Logic copied from standard addons If purchase, comes from purchase order, linked to a location, which is linked to the warehouse. @@ -361,8 +368,7 @@ class IntrastatProductDeclaration(models.Model): [('invoice_lines', 'in', inv_line.id)]) if po_lines: po = po_lines.order_id - region = self.env['stock.warehouse'].get_region_from_location( - po.location_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)]) @@ -374,7 +380,6 @@ class IntrastatProductDeclaration(models.Model): region = self.company_id.intrastat_region_id return region - def _get_transport(self, inv_line): transport = inv_line.invoice_id.intrastat_transport_id \ or self.company_id.intrastat_transport_id @@ -397,80 +402,164 @@ class IntrastatProductDeclaration(models.Model): self._company_warning(msg) return incoterm + def _get_product_origin_country(self, inv_line): + return inv_line.product_id.origin_country_id + def _update_computation_line_vals(self, inv_line, line_vals): """ placeholder for localization modules """ pass - def _gather_invoices(self): - - lines = [] + def _prepare_invoice_domain(self): start_date = date(self.year, self.month, 1) end_date = start_date + relativedelta(day=1, months=+1, days=-1) - - invoices = self.env['account.invoice'].search([ + domain = [ ('date_invoice', '>=', start_date), ('date_invoice', '<=', end_date), ('state', 'in', ['open', 'paid']), ('intrastat_country', '=', True), - ('company_id', '=', self.company_id.id)]) + ('company_id', '=', self.company_id.id)] + if self.type == 'arrivals': + domain.append(('type', 'in', ('in_invoice', 'in_refund'))) + elif self.type == 'dispatches': + domain.append(('type', 'in', ('out_invoice', 'out_refund'))) + return domain + + def _gather_invoices(self): + + lines = [] + accessory_costs = self.company_id.intrastat_accessory_costs + + domain = self._prepare_invoice_domain() + invoices = self.env['account.invoice'].search(domain) for invoice in invoices: - if self.type == 'arrivals': - if invoice.type in ['out_invoice', 'in_refund']: - continue - else: - if invoice.type in ['in_invoice', 'out_refund']: - continue - + lines_current_invoice = [] + total_inv_accessory_costs_cc = 0.0 # in company currency + total_inv_product_cc = 0.0 # in company currency for inv_line in invoice.invoice_line: - intrastat = inv_line.hs_code_id - if not intrastat: + if ( + accessory_costs and + inv_line.product_id and + inv_line.product_id.is_accessory_cost): + acost = invoice.currency_id.with_context( + date=invoice.date_invoice).compute( + inv_line.price_subtotal, + self.company_id.currency_id) + total_inv_accessory_costs_cc += acost + continue + if not inv_line.quantity: + _logger.info( + 'Skipping invoice line %s qty %s ' + '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' + % (inv_line.name, inv_line.quantity, invoice.number)) + continue + + if any([ + tax.exclude_from_intrastat_if_present + for tax in inv_line.invoice_line_tax_id]): + _logger.info( + 'Skipping invoice line %s ' + 'qty %s of invoice %s. Reason: ' + 'tax.exclude_from_intrastat_if_present' + % (inv_line.name, inv_line.quantity, invoice.number)) + continue + + 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')): + hs_code = inv_line.product_id.product_tmpl_id.\ + get_hs_code_recursively() + if not hs_code: + note = "\n" + _( + "Missing H.S. code on product %s. " + "This product is present in invoice %s.") % ( + inv_line.product_id.name_get()[0][1], + inv_line.invoice_id.number) + self._note += note + continue + else: + _logger.info( + 'Skipping invoice line %s qty %s' + 'of invoice %s. Reason: no product nor hs_code' + % (inv_line.name, inv_line.quantity, invoice.number)) continue intrastat_transaction = \ self._get_intrastat_transaction(inv_line) weight, suppl_unit_qty = self._get_weight_and_supplunits( - inv_line) + inv_line, hs_code) amount_company_currency = self._get_amount(inv_line) + total_inv_product_cc += amount_company_currency + + product_origin_country = self._get_product_origin_country( + inv_line) line_vals = { 'parent_id': self.id, 'invoice_line_id': inv_line.id, 'src_dest_country_id': partner_country.id, 'product_id': inv_line.product_id.id, - 'hs_code_id': intrastat.id, + 'hs_code_id': hs_code.id, 'weight': weight, 'suppl_unit_qty': suppl_unit_qty, 'amount_company_currency': amount_company_currency, + 'amount_accessory_cost_company_currency': 0.0, 'transaction_id': intrastat_transaction.id, + 'product_origin_country_id': + product_origin_country.id or False, } # extended declaration if self._extended: transport = self._get_transport(inv_line) + region = self._get_region(inv_line) line_vals.update({ 'transport_id': transport.id, + 'region_id': region and region.id or False, }) self._update_computation_line_vals(inv_line, line_vals) - lines.append((line_vals)) + lines_current_invoice.append((line_vals)) + + # Affect accessory costs pro-rata of the value + 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) + + lines += lines_current_invoice return lines @api.multi def action_gather(self): self.ensure_one() + self.message_post(_("Generate Lines from Invoices")) self._check_generate_lines() self._note = '' self._uom_refs = { @@ -489,6 +578,7 @@ class IntrastatProductDeclaration(models.Model): self._extended = False self.computation_line_ids.unlink() + self.declaration_line_ids.unlink() lines = self._gather_invoices() if not lines: @@ -501,7 +591,8 @@ class IntrastatProductDeclaration(models.Model): self.write({'computation_line_ids': [(0, 0, x) for x in lines]}) if self._note: - note_header = '\n\n>>> ' + str(date.today()) + '\n' + note_header = '\n\n>>> ' + fields.Datetime.to_string( + fields.Datetime.context_timestamp(self, datetime.now())) + '\n' self.note = note_header + self._note + (self.note or '') result_view = self.env.ref( 'intrastat_base.intrastat_result_view_form') @@ -519,15 +610,21 @@ class IntrastatProductDeclaration(models.Model): return True @api.model + def _group_line_hashcode_fields(self, computation_line): + return { + 'country': computation_line.src_dest_country_id.id or False, + 'hs_code_id': computation_line.hs_code_id.id or False, + 'intrastat_unit': computation_line.intrastat_unit_id.id or False, + 'transaction': computation_line.transaction_id.id or False, + 'transport': computation_line.transport_id.id or False, + 'region': computation_line.region_id.id or False, + 'product_origin_country': + computation_line.product_origin_country_id.id or False, + } + def group_line_hashcode(self, computation_line): - hashcode = "%s-%s-%s-%s-%s-%s" % ( - computation_line.src_dest_country_id.id or False, - computation_line.hs_code_id.id or False, - computation_line.intrastat_unit_id.id or False, - computation_line.transaction_id.id or False, - computation_line.transport_id.id or False, - computation_line.region_id.id or False - ) + fields = self._group_line_hashcode_fields(computation_line) + hashcode = '-'.join([unicode(f) for f in fields.itervalues()]) return hashcode @api.multi @@ -535,6 +632,7 @@ class IntrastatProductDeclaration(models.Model): """ generate declaration lines """ self.ensure_one() assert self.valid, 'Computation lines are not valid' + self.message_post(_("Generate Declaration Lines")) # Delete existing declaration lines self.declaration_line_ids.unlink() # Regenerate declaration lines from computation lines @@ -557,6 +655,7 @@ class IntrastatProductDeclaration(models.Model): def generate_xml(self): """ generate the INTRASTAT Declaration XML file """ self.ensure_one() + self.message_post(_("Generate XML Declaration File")) self._check_generate_xml() self._unlink_attachments() xml_string = self._generate_xml() @@ -565,8 +664,7 @@ class IntrastatProductDeclaration(models.Model): xml_string, '%s_%s' % (self.type, self.revision)) return self._open_attach_view(attach_id) else: - raise Warning( - _("Programming Error."), + raise UserError( _("No XML File has been generated.")) @api.multi @@ -625,8 +723,8 @@ class IntrastatProductComputationLine(models.Model): string='Suppl. Unit', readonly=True, help="Intrastat Supplementary Unit") weight = fields.Float( - string='Weight (Kg)', - digits=dp.get_precision('Stock Weight')) + string='Weight', + digits=dp.get_precision('Stock Weight'), help="Net weight in Kg") suppl_unit_qty = fields.Float( string='Suppl. Unit Qty', digits=dp.get_precision('Product Unit of Measure'), @@ -637,6 +735,12 @@ class IntrastatProductComputationLine(models.Model): help="Amount in company currency to write in the declaration. " "Amount in company currency = amount in invoice currency " "converted to company currency with the rate of the invoice date.") + amount_accessory_cost_company_currency = fields.Float( + string='Accessory Costs', + digits=dp.get_precision('Account'), + help="Amount in company currency of the accessory costs related to " + "this invoice line (by default, these accessory costs are computed " + "at the pro-rata of the amount of each invoice line.") transaction_id = fields.Many2one( 'intrastat.transaction', string='Intrastat Transaction') @@ -648,6 +752,9 @@ class IntrastatProductComputationLine(models.Model): transport_id = fields.Many2one( 'intrastat.transport_mode', string='Transport Mode') + product_origin_country_id = fields.Many2one( + 'res.country', string='Country of Origin of the Product', + help="Country of origin of the product i.e. product 'made in ____'") @api.one @api.depends('transport_id') @@ -706,7 +813,7 @@ class IntrastatProductDeclarationLine(models.Model): string='Suppl. Unit', readonly=True, help="Intrastat Supplementary Unit") weight = fields.Integer( - string='Weight (Kg)') + string='Weight', help="Net weight in Kg") suppl_unit_qty = fields.Integer( string='Suppl. Unit Qty', help="Supplementary Units Quantity") @@ -726,6 +833,9 @@ class IntrastatProductDeclarationLine(models.Model): transport_id = fields.Many2one( 'intrastat.transport_mode', string='Transport Mode') + product_origin_country_id = fields.Many2one( + 'res.country', string='Country of Origin of the Product', + help="Country of origin of the product i.e. product 'made in ____'") @api.model def _prepare_grouped_fields(self, computation_line, fields_to_sum): @@ -735,7 +845,11 @@ class IntrastatProductDeclarationLine(models.Model): 'hs_code_id': computation_line.hs_code_id.id, 'transaction_id': computation_line.transaction_id.id, 'transport_id': computation_line.transport_id.id, + 'region_id': computation_line.region_id.id, 'parent_id': computation_line.parent_id.id, + 'product_origin_country_id': + computation_line.product_origin_country_id.id, + 'amount_company_currency': 0.0, } for field in fields_to_sum: vals[field] = 0.0 @@ -745,7 +859,6 @@ class IntrastatProductDeclarationLine(models.Model): fields_to_sum = [ 'weight', 'suppl_unit_qty', - 'amount_company_currency', ] return fields_to_sum @@ -757,4 +870,14 @@ class IntrastatProductDeclarationLine(models.Model): for computation_line in computation_lines: for field in fields_to_sum: vals[field] += computation_line[field] + vals['amount_company_currency'] += ( + computation_line['amount_company_currency'] + + computation_line['amount_accessory_cost_company_currency']) + # round, otherwise odoo with truncate (6.7 -> 6... instead of 7 !) + for field in fields_to_sum: + vals[field] = int(round(vals[field])) + if not vals['weight']: + vals['weight'] = 1 + vals['amount_company_currency'] = int(round( + vals['amount_company_currency'])) return vals diff --git a/intrastat_product/models/intrastat_region.py b/intrastat_product/models/intrastat_region.py index 3d1333e..9dddfdf 100644 --- a/intrastat_product/models/intrastat_region.py +++ b/intrastat_product/models/intrastat_region.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Odoo, Open Source Management Solution diff --git a/intrastat_product/models/intrastat_transaction.py b/intrastat_product/models/intrastat_transaction.py index 3734fa6..bf04d32 100644 --- a/intrastat_product/models/intrastat_transaction.py +++ b/intrastat_product/models/intrastat_transaction.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat Product module for Odoo @@ -34,7 +34,8 @@ class IntrastatTransaction(models.Model): code = fields.Char(string='Code', required=True) description = fields.Text(string='Description') display_name = fields.Char( - compute='_compute_display_name', string="Display Name", readonly=True) + compute='_compute_display_name', string="Display Name", readonly=True, + store=True) company_id = fields.Many2one( 'res.company', string='Company', default=lambda self: self.env['res.company']._company_default_get( diff --git a/intrastat_product/models/intrastat_transport_mode.py b/intrastat_product/models/intrastat_transport_mode.py index 6157459..1850497 100644 --- a/intrastat_product/models/intrastat_transport_mode.py +++ b/intrastat_product/models/intrastat_transport_mode.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat Product module for Odoo diff --git a/intrastat_product/models/intrastat_unit.py b/intrastat_product/models/intrastat_unit.py index 65a86f2..7122610 100644 --- a/intrastat_product/models/intrastat_unit.py +++ b/intrastat_product/models/intrastat_unit.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat Product module for Odoo diff --git a/intrastat_product/models/res_company.py b/intrastat_product/models/res_company.py index f3d4c9b..ccf15d2 100644 --- a/intrastat_product/models/res_company.py +++ b/intrastat_product/models/res_company.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat Product module for Odoo @@ -30,7 +30,7 @@ class ResCompany(models.Model): intrastat_incoterm_id = fields.Many2one( 'stock.incoterms', - string='Default incoterm for Intrastat', + string='Default Incoterm for Intrastat', help="International Commercial Terms are a series of " "predefined commercial terms used in international " "transactions.") @@ -48,7 +48,21 @@ class ResCompany(models.Model): compute='_compute_intrastat') intrastat_region_id = fields.Many2one( 'intrastat.region', - string='Default Intrastat region') + string='Default Intrastat Region') + intrastat_transaction_out_invoice = fields.Many2one( + 'intrastat.transaction', + string='Default Intrastat Transaction For Customer Invoice') + intrastat_transaction_out_refund = fields.Many2one( + 'intrastat.transaction', + string='Default Intrastat Transaction for Customer Refunds') + intrastat_transaction_in_invoice = fields.Many2one( + 'intrastat.transaction', + string='Default Intrastat Transaction For Supplier Invoices') + intrastat_transaction_in_refund = fields.Many2one( + 'intrastat.transaction', + string='Default Intrastat Transaction For Supplier Refunds') + intrastat_accessory_costs = fields.Boolean( + string='Include Accessory Costs in Fiscal Value of Product') @api.model def _intrastat_arrivals(self): diff --git a/intrastat_product/models/sale_order.py b/intrastat_product/models/sale_order.py new file mode 100644 index 0000000..0818460 --- /dev/null +++ b/intrastat_product/models/sale_order.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Intrastat Product module for Odoo +# Copyright (C) 2010-2015 Akretion (http://www.akretion.com) +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, api + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + @api.model + def _prepare_invoice(self, order, lines): + '''Copy destination country to invoice''' + invoice_vals = super(SaleOrder, self)._prepare_invoice( + order, lines) + invoice_vals['src_dest_country_id'] = \ + order.partner_shipping_id.country_id.id or False + invoice_vals['incoterm_id'] = order.incoterm.id or False + return invoice_vals diff --git a/intrastat_product/models/stock_picking.py b/intrastat_product/models/stock_picking.py index db97f5b..5080277 100644 --- a/intrastat_product/models/stock_picking.py +++ b/intrastat_product/models/stock_picking.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat Product module for Odoo diff --git a/intrastat_product/models/stock_warehouse.py b/intrastat_product/models/stock_warehouse.py index d766b61..27b269c 100644 --- a/intrastat_product/models/stock_warehouse.py +++ b/intrastat_product/models/stock_warehouse.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Odoo, Open Source Management Solution @@ -20,7 +20,7 @@ # ############################################################################## -from openerp import models, fields +from openerp import models, fields, api class StockWarehouse(models.Model): @@ -30,10 +30,16 @@ class StockWarehouse(models.Model): 'intrastat.region', string='Intrastat region') - def get_region_from_location(self, location): - locations = location.search( - [('parent_left', '<=', location.parent_left), - ('parent_right', '>=', location.parent_right)]) + +class StockLocation(models.Model): + _inherit = 'stock.location' + + @api.multi + def get_intrastat_region(self): + self.ensure_one() + 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)]) diff --git a/intrastat_product/views/intrastat_product_declaration.xml b/intrastat_product/views/intrastat_product_declaration.xml index 935a158..52e0693 100644 --- a/intrastat_product/views/intrastat_product_declaration.xml +++ b/intrastat_product/views/intrastat_product_declaration.xml @@ -10,7 +10,7 @@
@@ -54,62 +54,14 @@ - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -
-
+
- - - - - - - - - - - - - - - + - @@ -130,7 +82,7 @@ Intrastat Product Declaration Validated - + intrastat.product.declaration.tree intrastat.product.declaration @@ -178,5 +130,132 @@ + + intrastat.product.computation.line.form + intrastat.product.computation.line + +
+ + + + + + + + + + + + + +
+
+
+ + + intrastat.product.computation.line.tree + intrastat.product.computation.line + + + + + + + + + + + + + + + + + + + + + + intrastat.product.declaration.line.form + intrastat.product.declaration.line + +
+ + + + + + + + + + + +
+
+
+ + + intrastat.product.declaration.line.tree + intrastat.product.declaration.line + + + + + + + + + + + + + + + + + + + + diff --git a/intrastat_product/views/res_company.xml b/intrastat_product/views/res_company.xml index 263f0e0..2d61383 100644 --- a/intrastat_product/views/res_company.xml +++ b/intrastat_product/views/res_company.xml @@ -11,11 +11,15 @@ + + + + - + +
diff --git a/intrastat_product/views/stock_warehouse.xml b/intrastat_product/views/stock_warehouse.xml index 775da73..163cf0f 100644 --- a/intrastat_product/views/stock_warehouse.xml +++ b/intrastat_product/views/stock_warehouse.xml @@ -3,12 +3,12 @@ - stock.warehouse.form + intrastat.stock.warehouse.form stock.warehouse - +