Dre4m Shell
Server IP : 127.0.0.2  /  Your IP : 18.218.2.200
Web Server : Apache/2.4.18 (Ubuntu)
System :
User : www-data ( )
PHP Version : 7.0.33-0ubuntu0.16.04.16
Disable Function : disk_free_space,disk_total_space,diskfreespace,dl,exec,fpaththru,getmyuid,getmypid,highlight_file,ignore_user_abord,leak,listen,link,opcache_get_configuration,opcache_get_status,passthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,php_uname,phpinfo,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix,_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_times,posix_ttyname,posix_uname,pclose,popen,proc_open,proc_close,proc_get_status,proc_nice,proc_terminate,shell_exec,source,show_source,system,virtual
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /opt/odoo/addons/l10n_be_intrastat/wizard/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME SHELL ]     

Current File : /opt/odoo/addons/l10n_be_intrastat/wizard/xml_decl.py
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

import base64
import xml.etree.ElementTree as ET
from collections import namedtuple

from odoo import api, exceptions, fields, models, _

INTRASTAT_XMLNS = 'http://www.onegate.eu/2010-01-01'


class XmlDeclaration(models.TransientModel):
    """
    Intrastat XML Declaration
    """
    _name = "l10n_be_intrastat_xml.xml_decl"
    _description = 'Intrastat XML Declaration'

    def _default_get_month(self):
        return fields.Date.from_string(fields.Date.context_today(self)).strftime('%m')

    def _default_get_year(self):
        return fields.Date.from_string(fields.Date.context_today(self)).strftime('%Y')

    name = fields.Char(string='File Name', default='intrastat.xml')
    month = fields.Selection([('01', 'January'), ('02', 'February'), ('03', 'March'),
                               ('04', 'April'), ('05', 'May'), ('06', 'June'), ('07', 'July'),
                               ('08', 'August'), ('09', 'September'), ('10', 'October'),
                               ('11', 'November'), ('12', 'December')], string='Month', required=True, default=_default_get_month)
    year = fields.Char(size=4, required=True, default=_default_get_year)
    company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.user.company_id)
    arrivals = fields.Selection([('be-exempt', 'Exempt'),
                                  ('be-standard', 'Standard'),
                                  ('be-extended', 'Extended')],
                                 required=True, default='be-standard')
    dispatches = fields.Selection([('be-exempt', 'Exempt'),
                                  ('be-standard', 'Standard'),
                                  ('be-extended', 'Extended')],
                                   required=True, default='be-standard')
    file_save = fields.Binary(string='Intrastat Report File', readonly=True)
    state = fields.Selection([('draft', 'Draft'), ('download', 'Download')], default='draft')

    @api.model
    def _company_warning(self, translated_msg):
        """ Raise a error with custom message, asking user to configure company settings """
        raise exceptions.RedirectWarning(
            translated_msg, self.env.ref('base.action_res_company_form').id, _('Go to company configuration screen'))

    @api.multi
    def create_xml(self):
        """Creates xml that is to be exported and sent to estate for partner vat intra.
        :return: Value for next action.
        :rtype: dict
        """
        self.ensure_one()
        company = self.company_id
        if not (company.partner_id and company.partner_id.country_id and
                company.partner_id.country_id.id):
            self._company_warning(_('The country of your company is not set, '
                  'please make sure to configure it first.'))
        if not company.company_registry:
            self._company_warning(_('The registry number of your company is not set, '
                  'please make sure to configure it first.'))
        if len(self.year) != 4:
            raise exceptions.Warning(_('Year must be 4 digits number (YYYY)'))

        #Create root declaration
        decl = ET.Element('DeclarationReport')
        decl.set('xmlns', INTRASTAT_XMLNS)

        #Add Administration elements
        admin = ET.SubElement(decl, 'Administration')
        fromtag = ET.SubElement(admin, 'From')
        fromtag.text = company.company_registry
        fromtag.set('declarerType', 'KBO')
        ET.SubElement(admin, 'To').text = "NBB"
        ET.SubElement(admin, 'Domain').text = "SXX"
        if self.arrivals == 'be-standard':
            decl.append(self.sudo()._get_lines(dispatchmode=False, extendedmode=False))
        elif self.arrivals == 'be-extended':
            decl.append(self.sudo()._get_lines(dispatchmode=False, extendedmode=True))
        if self.dispatches == 'be-standard':
            decl.append(self.sudo()._get_lines(dispatchmode=True, extendedmode=False))
        elif self.dispatches == 'be-extended':
            decl.append(self.sudo()._get_lines(dispatchmode=True, extendedmode=True))

        #Get xml string with declaration
        data_file = ET.tostring(decl, encoding='UTF-8', method='xml')

        #change state of the wizard
        self.write({'name': 'intrastat_%s%s.xml' % (self.year, self.month),
                    'file_save': base64.encodestring(data_file),
                    'state': 'download'})
        return {
            'name': _('Save'),
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'l10n_be_intrastat_xml.xml_decl',
            'type': 'ir.actions.act_window',
            'target': 'new',
            'res_id': self.id,
        }

    @api.multi
    def _get_lines(self, dispatchmode=False, extendedmode=False):
        company = self.company_id
        IntrastatRegion = self.env['l10n_be_intrastat.region']

        if dispatchmode:
            mode1 = 'out_invoice'
            mode2 = 'in_refund'
            declcode = "29"
        else:
            mode1 = 'in_invoice'
            mode2 = 'out_refund'
            declcode = "19"

        decl = ET.Element('Report')
        if not extendedmode:
            decl.set('code', 'EX%sS' % declcode)
        else:
            decl.set('code', 'EX%sE' % declcode)
        decl.set('date', '%s-%s' % (self.year, self.month))
        datas = ET.SubElement(decl, 'Data')
        if not extendedmode:
            datas.set('form', 'EXF%sS' % declcode)
        else:
            datas.set('form', 'EXF%sE' % declcode)
        datas.set('close', 'true')
        intrastatkey = namedtuple("intrastatkey",
                                  ['EXTRF', 'EXCNT', 'EXTTA', 'EXREG',
                                   'EXGO', 'EXTPC', 'EXDELTRM'])
        entries = {}

        query = """
            SELECT
                inv_line.id
            FROM
                account_invoice_line inv_line
                JOIN account_invoice inv ON inv_line.invoice_id=inv.id
                LEFT JOIN res_country ON res_country.id = inv.intrastat_country_id
                LEFT JOIN res_partner ON res_partner.id = inv.partner_id
                LEFT JOIN res_country countrypartner ON countrypartner.id = res_partner.country_id
                JOIN product_product ON inv_line.product_id=product_product.id
                JOIN product_template ON product_product.product_tmpl_id=product_template.id
            WHERE
                inv.state IN ('open','paid')
                AND inv.company_id=%s
                AND not product_template.type='service'
                AND (res_country.intrastat=true OR (inv.intrastat_country_id is NULL
                                                    AND countrypartner.intrastat=true))
                AND ((res_country.code IS NOT NULL AND not res_country.code=%s)
                     OR (res_country.code is NULL AND countrypartner.code IS NOT NULL
                     AND not countrypartner.code=%s))
                AND inv.type IN (%s, %s)
                AND to_char(inv.date_invoice, 'YYYY')=%s
                AND to_char(inv.date_invoice, 'MM')=%s
            """

        self.env.cr.execute(query, (company.id, company.partner_id.country_id.code,
                            company.partner_id.country_id.code, mode1, mode2,
                            self.year, self.month))
        lines = self.env.cr.fetchall()
        invoicelines_ids = [rec[0] for rec in lines]
        invoicelines = self.env['account.invoice.line'].browse(invoicelines_ids)

        for inv_line in invoicelines:

            #Check type of transaction
            if inv_line.intrastat_transaction_id:
                extta = inv_line.intrastat_transaction_id.code
            else:
                extta = "1"
            #Check country
            if inv_line.invoice_id.intrastat_country_id:
                excnt = inv_line.invoice_id.intrastat_country_id.code
            else:
                excnt = inv_line.invoice_id.partner_id.country_id.code

            #Check region
            #If purchase, comes from purchase order, linked to a location,
            #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 one.
            exreg = None
            if inv_line.invoice_id.type in ('in_invoice', 'in_refund'):
                #comes from purchase
                po_lines = self.env['purchase.order.line'].search([('invoice_lines', 'in', inv_line.id)], limit=1)
                if po_lines:
                    if self._is_situation_triangular(company, po_line=po_lines):
                        continue
                    location = self.env['stock.location'].browse(po_lines.order_id._get_destination_location())
                    region_id = self.env['stock.warehouse'].get_regionid_from_locationid(location)
                    if region_id:
                        exreg = IntrastatRegion.browse(region_id).code
            elif inv_line.invoice_id.type in ('out_invoice', 'out_refund'):
                #comes from sales
                so_lines = self.env['sale.order.line'].search([('invoice_lines', 'in', inv_line.id)], limit=1)
                if so_lines:
                    if self._is_situation_triangular(company, so_line=so_lines):
                        continue
                    saleorder = so_lines.order_id
                    if saleorder and saleorder.warehouse_id and saleorder.warehouse_id.region_id:
                        exreg = IntrastatRegion.browse(saleorder.warehouse_id.region_id.id).code

            if not exreg:
                if company.region_id:
                    exreg = company.region_id.code
                else:
                    self._company_warning(_('The Intrastat Region of the selected company is not set, '
                          'please make sure to configure it first.'))

            #Check commodity codes
            intrastat_id = inv_line.product_id.get_intrastat_recursively()
            if intrastat_id:
                exgo = self.env['report.intrastat.code'].browse(intrastat_id).name
            else:
                raise exceptions.Warning(
                    _('Product "%s" has no intrastat code, please configure it') % inv_line.product_id.display_name)

            #In extended mode, 2 more fields required
            if extendedmode:
                #Check means of transport
                if inv_line.invoice_id.transport_mode_id:
                    extpc = inv_line.invoice_id.transport_mode_id.code
                elif company.transport_mode_id:
                    extpc = company.transport_mode_id.code
                else:
                    self._company_warning(_('The default Intrastat transport mode of your company '
                          'is not set, please make sure to configure it first.'))

                #Check incoterm
                if inv_line.invoice_id.incoterm_id:
                    exdeltrm = inv_line.invoice_id.incoterm_id.code
                elif company.incoterm_id:
                    exdeltrm = company.incoterm_id.code
                else:
                    self._company_warning(_('The default Incoterm of your company is not set, '
                          'please make sure to configure it first.'))
            else:
                extpc = ""
                exdeltrm = ""
            linekey = intrastatkey(EXTRF=declcode, EXCNT=excnt,
                                   EXTTA=extta, EXREG=exreg, EXGO=exgo,
                                   EXTPC=extpc, EXDELTRM=exdeltrm)
            #We have the key
            #calculate amounts
            if inv_line.price_unit and inv_line.quantity:
                amount = inv_line.price_unit * inv_line.quantity
            else:
                amount = 0
            weight = (inv_line.product_id.weight or 0.0) * \
                inv_line.uom_id._compute_quantity(inv_line.quantity, inv_line.product_id.uom_id)
            if not inv_line.product_id.uom_id.category_id:
                supply_units = inv_line.quantity
            else:
                supply_units = inv_line.quantity * inv_line.uom_id.factor
            amounts = entries.setdefault(linekey, (0, 0, 0))
            amounts = (amounts[0] + amount, amounts[1] + weight, amounts[2] + supply_units)
            entries[linekey] = amounts

        numlgn = 0
        for linekey in entries:
            amounts = entries[linekey]
            if round(amounts[0], 0) == 0:
                continue
            numlgn += 1
            item = ET.SubElement(datas, 'Item')
            self._set_Dim(item, 'EXSEQCODE', unicode(numlgn))
            self._set_Dim(item, 'EXTRF', unicode(linekey.EXTRF))
            self._set_Dim(item, 'EXCNT', unicode(linekey.EXCNT))
            self._set_Dim(item, 'EXTTA', unicode(linekey.EXTTA))
            self._set_Dim(item, 'EXREG', unicode(linekey.EXREG))
            self._set_Dim(item, 'EXTGO', unicode(linekey.EXGO))
            if extendedmode:
                self._set_Dim(item, 'EXTPC', unicode(linekey.EXTPC))
                self._set_Dim(item, 'EXDELTRM', unicode(linekey.EXDELTRM))
            self._set_Dim(item, 'EXTXVAL', unicode(round(amounts[0], 0)).replace(".", ","))
            self._set_Dim(item, 'EXWEIGHT', unicode(round(amounts[1], 0)).replace(".", ","))
            self._set_Dim(item, 'EXUNITS', unicode(round(amounts[2], 0)).replace(".", ","))

        if numlgn == 0:
            #no datas
            datas.set('action', 'nihil')
        return decl

    def _set_Dim(self, item, prop, value):
        dim = ET.SubElement(item, 'Dim')
        dim.set('prop', prop)
        dim.text = value

    def _is_situation_triangular(self, company, po_line=False, so_line=False):
        # Ignoring what is purchased and sold by us with a dropshipping route
        # outside of our country, or completely within it
        # https://www.nbb.be/doc/dq/f_pdf_ex/intra2017fr.pdf (ยง 4.x)
        dropship_pick_type = self.env.ref('stock_dropshipping.picking_type_dropship', raise_if_not_found=False)
        if not dropship_pick_type:
            return False
        stock_move_domain = [('picking_type_id', '=', dropship_pick_type.id)]

        if po_line:
            stock_move_domain.append(('purchase_line_id', '=', po_line.id))
        if so_line:
            stock_move_domain.append(('procurement_id.sale_line_id', '=', so_line.id))

        stock_move = self.env['stock.move'].search(stock_move_domain, limit=1)
        return stock_move and (
            (stock_move.partner_id.country_id.code != company.country_id.code and
                stock_move.picking_partner_id.country_id.code != company.country_id.code) or
            (stock_move.partner_id.country_id.code == company.country_id.code and
                stock_move.picking_partner_id.country_id.code == company.country_id.code))

Anon7 - 2022
AnonSec Team