# -*- coding: utf-8 -*- from odoo import tools from odoo import models, fields, api class AccountInvoiceReport(models.Model): _name = "account.invoice.report" _description = "Invoices Statistics" _auto = False _rec_name = 'date' @api.multi @api.depends('currency_id', 'date', 'price_total', 'price_average', 'residual') def _compute_amounts_in_user_currency(self): """Compute the amounts in the currency of the user """ context = dict(self._context or {}) user_currency_id = self.env.user.company_id.currency_id currency_rate_id = self.env['res.currency.rate'].search([ ('rate', '=', 1), '|', ('company_id', '=', self.env.user.company_id.id), ('company_id', '=', False)], limit=1) base_currency_id = currency_rate_id.currency_id ctx = context.copy() for record in self: ctx['date'] = record.date record.user_currency_price_total = base_currency_id.with_context(ctx).compute(record.price_total, user_currency_id) record.user_currency_price_average = base_currency_id.with_context(ctx).compute(record.price_average, user_currency_id) record.user_currency_residual = base_currency_id.with_context(ctx).compute(record.residual, user_currency_id) date = fields.Date(readonly=True) product_id = fields.Many2one('product.product', string='Product', readonly=True) product_qty = fields.Float(string='Product Quantity', readonly=True) uom_name = fields.Char(string='Reference Unit of Measure', readonly=True) payment_term_id = fields.Many2one('account.payment.term', string='Payment Terms', oldname='payment_term', readonly=True) fiscal_position_id = fields.Many2one('account.fiscal.position', oldname='fiscal_position', string='Fiscal Position', readonly=True) currency_id = fields.Many2one('res.currency', string='Currency', readonly=True) categ_id = fields.Many2one('product.category', string='Product Category', readonly=True) journal_id = fields.Many2one('account.journal', string='Journal', readonly=True) partner_id = fields.Many2one('res.partner', string='Partner', readonly=True) commercial_partner_id = fields.Many2one('res.partner', string='Partner Company', help="Commercial Entity") company_id = fields.Many2one('res.company', string='Company', readonly=True) user_id = fields.Many2one('res.users', string='Salesperson', readonly=True) price_total = fields.Float(string='Total Without Tax', readonly=True) user_currency_price_total = fields.Float(string="Total Without Tax", compute='_compute_amounts_in_user_currency', digits=0) price_average = fields.Float(string='Average Price', readonly=True, group_operator="avg") user_currency_price_average = fields.Float(string="Average Price", compute='_compute_amounts_in_user_currency', digits=0) currency_rate = fields.Float(string='Currency Rate', readonly=True, group_operator="avg") nbr = fields.Integer(string='# of Lines', readonly=True) # TDE FIXME master: rename into nbr_lines type = fields.Selection([ ('out_invoice', 'Customer Invoice'), ('in_invoice', 'Vendor Bill'), ('out_refund', 'Customer Refund'), ('in_refund', 'Vendor Refund'), ], readonly=True) state = fields.Selection([ ('draft', 'Draft'), ('proforma', 'Pro-forma'), ('proforma2', 'Pro-forma'), ('open', 'Open'), ('paid', 'Done'), ('cancel', 'Cancelled') ], string='Invoice Status', readonly=True) date_due = fields.Date(string='Due Date', readonly=True) account_id = fields.Many2one('account.account', string='Account', readonly=True, domain=[('deprecated', '=', False)]) account_line_id = fields.Many2one('account.account', string='Account Line', readonly=True, domain=[('deprecated', '=', False)]) partner_bank_id = fields.Many2one('res.partner.bank', string='Bank Account', readonly=True) residual = fields.Float(string='Total Residual', readonly=True) user_currency_residual = fields.Float(string="Total Residual", compute='_compute_amounts_in_user_currency', digits=0) country_id = fields.Many2one('res.country', string='Country of the Partner Company') weight = fields.Float(string='Gross Weight', readonly=True) volume = fields.Float(string='Volume', readonly=True) _order = 'date desc' _depends = { 'account.invoice': [ 'account_id', 'amount_total_company_signed', 'commercial_partner_id', 'company_id', 'currency_id', 'date_due', 'date_invoice', 'fiscal_position_id', 'journal_id', 'partner_bank_id', 'partner_id', 'payment_term_id', 'residual', 'state', 'type', 'user_id', ], 'account.invoice.line': [ 'account_id', 'invoice_id', 'price_subtotal', 'product_id', 'quantity', 'uom_id', 'account_analytic_id', ], 'product.product': ['product_tmpl_id'], 'product.template': ['categ_id'], 'product.uom': ['category_id', 'factor', 'name', 'uom_type'], 'res.currency.rate': ['currency_id', 'name'], 'res.partner': ['country_id'], } def _select(self): select_str = """ SELECT sub.id, sub.date, sub.product_id, sub.partner_id, sub.country_id, sub.account_analytic_id, sub.payment_term_id, sub.uom_name, sub.currency_id, sub.journal_id, sub.fiscal_position_id, sub.user_id, sub.company_id, sub.nbr, sub.type, sub.state, sub.weight, sub.volume, sub.categ_id, sub.date_due, sub.account_id, sub.account_line_id, sub.partner_bank_id, sub.product_qty, sub.price_total as price_total, sub.price_average as price_average, COALESCE(cr.rate, 1) as currency_rate, sub.residual as residual, sub.commercial_partner_id as commercial_partner_id """ return select_str def _sub_select(self): select_str = """ SELECT ail.id AS id, ai.date_invoice AS date, ail.product_id, ai.partner_id, ai.payment_term_id, ail.account_analytic_id, u2.name AS uom_name, ai.currency_id, ai.journal_id, ai.fiscal_position_id, ai.user_id, ai.company_id, 1 AS nbr, ai.type, ai.state, pt.categ_id, ai.date_due, ai.account_id, ail.account_id AS account_line_id, ai.partner_bank_id, SUM ((invoice_type.sign * ail.quantity) / u.factor * u2.factor) AS product_qty, SUM(ail.price_subtotal_signed * invoice_type.sign) AS price_total, SUM(ABS(ail.price_subtotal_signed)) / CASE WHEN SUM(ail.quantity / u.factor * u2.factor) <> 0::numeric THEN SUM(ail.quantity / u.factor * u2.factor) ELSE 1::numeric END AS price_average, ai.residual_company_signed / (SELECT count(*) FROM account_invoice_line l where invoice_id = ai.id) * count(*) * invoice_type.sign AS residual, ai.commercial_partner_id as commercial_partner_id, partner.country_id, SUM(pr.weight * (invoice_type.sign*ail.quantity) / u.factor * u2.factor) AS weight, SUM(pr.volume * (invoice_type.sign*ail.quantity) / u.factor * u2.factor) AS volume """ return select_str def _from(self): from_str = """ FROM account_invoice_line ail JOIN account_invoice ai ON ai.id = ail.invoice_id JOIN res_partner partner ON ai.commercial_partner_id = partner.id LEFT JOIN product_product pr ON pr.id = ail.product_id left JOIN product_template pt ON pt.id = pr.product_tmpl_id LEFT JOIN product_uom u ON u.id = ail.uom_id LEFT JOIN product_uom u2 ON u2.id = pt.uom_id JOIN ( -- Temporary table to decide if the qty should be added or retrieved (Invoice vs Refund) SELECT id,(CASE WHEN ai.type::text = ANY (ARRAY['in_refund'::character varying::text, 'in_invoice'::character varying::text]) THEN -1 ELSE 1 END) AS sign FROM account_invoice ai ) AS invoice_type ON invoice_type.id = ai.id """ return from_str def _group_by(self): group_by_str = """ GROUP BY ail.id, ail.product_id, ail.account_analytic_id, ai.date_invoice, ai.id, ai.partner_id, ai.payment_term_id, u2.name, u2.id, ai.currency_id, ai.journal_id, ai.fiscal_position_id, ai.user_id, ai.company_id, ai.type, invoice_type.sign, ai.state, pt.categ_id, ai.date_due, ai.account_id, ail.account_id, ai.partner_bank_id, ai.residual_company_signed, ai.amount_total_company_signed, ai.commercial_partner_id, partner.country_id """ return group_by_str @api.model_cr def init(self): # self._table = account_invoice_report tools.drop_view_if_exists(self.env.cr, self._table) self.env.cr.execute("""CREATE or REPLACE VIEW %s as ( WITH currency_rate AS (%s) %s FROM ( %s %s %s ) AS sub LEFT JOIN currency_rate cr ON (cr.currency_id = sub.currency_id AND cr.company_id = sub.company_id AND cr.date_start <= COALESCE(sub.date, NOW()) AND (cr.date_end IS NULL OR cr.date_end > COALESCE(sub.date, NOW()))) )""" % ( self._table, self.env['res.currency']._select_companies_rates(), self._select(), self._sub_select(), self._from(), self._group_by()))