From 7a50367e840ac4eedd195e8682d20387178cac35 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Thu, 29 Nov 2012 11:12:28 +0100 Subject: [PATCH] [IMP] account: optimized the account invoice analysis report to lower the response time. Removed the fields due_delay and delay_to_pay that were the reasons of the bad performances besides being a bit useless and having wrong values computed bzr revid: qdp-launchpad@openerp.com-20121129101228-6cxv07svxnbabfr0 --- addons/account/account_invoice.py | 4 +- .../account/report/account_invoice_report.py | 219 +++++++----------- .../report/account_invoice_report_view.xml | 4 +- addons/product/product.py | 2 +- 4 files changed, 93 insertions(+), 136 deletions(-) diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index 6804d5116f1..8d13ec9dc8f 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -1381,8 +1381,8 @@ class account_invoice_line(osv.osv): 'origin': fields.char('Source Document', size=256, help="Reference of the document that produced this invoice."), 'sequence': fields.integer('Sequence', help="Gives the sequence of this line when displaying the invoice."), 'invoice_id': fields.many2one('account.invoice', 'Invoice Reference', ondelete='cascade', select=True), - 'uos_id': fields.many2one('product.uom', 'Unit of Measure', ondelete='set null'), - 'product_id': fields.many2one('product.product', 'Product', ondelete='set null'), + 'uos_id': fields.many2one('product.uom', 'Unit of Measure', ondelete='set null', select=True), + 'product_id': fields.many2one('product.product', 'Product', ondelete='set null', select=True), 'account_id': fields.many2one('account.account', 'Account', required=True, domain=[('type','<>','view'), ('type', '<>', 'closed')], help="The income or expense account related to the selected product."), 'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price')), 'price_subtotal': fields.function(_amount_line, string='Subtotal', type="float", diff --git a/addons/account/report/account_invoice_report.py b/addons/account/report/account_invoice_report.py index 68eaedb20a6..d1f78ab7b0f 100644 --- a/addons/account/report/account_invoice_report.py +++ b/addons/account/report/account_invoice_report.py @@ -98,150 +98,109 @@ class account_invoice_report(osv.osv): 'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account',readonly=True), 'residual': fields.float('Total Residual', readonly=True), 'user_currency_residual': fields.function(_compute_amounts_in_user_currency, string="Total Residual", type='float', digits_compute=dp.get_precision('Account'), multi="_compute_amounts"), - 'delay_to_pay': fields.float('Avg. Delay To Pay', readonly=True, group_operator="avg"), - 'due_delay': fields.float('Avg. Due Delay', readonly=True, group_operator="avg"), } _order = 'date desc' def _select(self): select_str = """ - SELECT min(ail.id) as id, - ai.date_invoice as date, - to_char(ai.date_invoice, 'YYYY') as year, - to_char(ai.date_invoice, 'MM') as month, - to_char(ai.date_invoice, 'YYYY-MM-DD') as day, - ail.product_id, - ai.partner_id as partner_id, - ai.payment_term as payment_term, - ai.period_id as period_id, - (case when u.uom_type not in ('reference') then - (select name from product_uom where uom_type='reference' and active and category_id=u.category_id LIMIT 1) - else - u.name - end) as uom_name, - ai.currency_id as currency_id, - ai.journal_id as journal_id, - ai.fiscal_position as fiscal_position, - ai.user_id as user_id, - ai.company_id as company_id, - count(ail.*) as nbr, - ai.type as type, - ai.state, - pt.categ_id, - ai.date_due as date_due, - ai.account_id as account_id, - ail.account_id as account_line_id, - ai.partner_bank_id as partner_bank_id, - sum(case when ai.type in ('out_refund','in_invoice') then - -ail.quantity / u.factor - else - ail.quantity / u.factor - end) as product_qty, - - sum(case when ai.type in ('out_refund','in_invoice') then - -ail.price_subtotal - else - ail.price_subtotal - end) / cr.rate as price_total, - - (case when ai.type in ('out_refund','in_invoice') then - sum(-ail.price_subtotal) - else - sum(ail.price_subtotal) - end) / (CASE WHEN sum(ail.quantity/u.factor) <> 0 - THEN - (case when ai.type in ('out_refund','in_invoice') - then sum(-ail.quantity/u.factor) - else sum(ail.quantity/u.factor) end) - ELSE 1 - END) - / cr.rate as price_average, - - cr.rate as currency_rate, - sum((select extract(epoch from avg(date_trunc('day',aml.date_created)-date_trunc('day',l.create_date)))/(24*60*60)::decimal(16,2) - from account_move_line as aml - left join account_invoice as a ON (a.move_id=aml.move_id) - left join account_invoice_line as l ON (a.id=l.invoice_id) - where a.id=ai.id)) as delay_to_pay, - sum((select extract(epoch from avg(date_trunc('day',a.date_due)-date_trunc('day',a.date_invoice)))/(24*60*60)::decimal(16,2) - from account_move_line as aml - left join account_invoice as a ON (a.move_id=aml.move_id) - left join account_invoice_line as l ON (a.id=l.invoice_id) - where a.id=ai.id)) as due_delay, - (case when ai.type in ('out_refund','in_invoice') then - -ai.residual - else - ai.residual - end)/ (CASE WHEN - (select count(l.id) from account_invoice_line as l - left join account_invoice as a ON (a.id=l.invoice_id) - where a.id=ai.id) <> 0 - THEN - (select count(l.id) from account_invoice_line as l - left join account_invoice as a ON (a.id=l.invoice_id) - where a.id=ai.id) - ELSE 1 - END) / cr.rate as residual + SELECT sub.id, sub.date, sub.year, sub.month, sub.day, sub.product_id, sub.partner_id, + sub.payment_term, sub.period_id, sub.uom_name, sub.currency_id, sub.journal_id, + sub.fiscal_position, sub.user_id, sub.company_id, sub.nbr, sub.type, sub.state, + sub.categ_id, sub.date_due, sub.account_id, sub.account_line_id, sub.partner_bank_id, + sub.product_qty, sub.price_total / cr.rate as price_total, sub.price_average /cr.rate as price_average, + cr.rate as currency_rate, sub.residual / cr.rate as residual, sub.section_id + FROM ( + SELECT min(ail.id) AS id, + ai.date_invoice AS date, + to_char(ai.date_invoice::timestamp with time zone, 'YYYY'::text) AS year, + to_char(ai.date_invoice::timestamp with time zone, 'MM'::text) AS month, + to_char(ai.date_invoice::timestamp with time zone, 'YYYY-MM-DD'::text) AS day, + ail.product_id, ai.partner_id, ai.payment_term, ai.period_id, + CASE + WHEN u.uom_type::text <> 'reference'::text + THEN ( SELECT product_uom.name + FROM product_uom + WHERE product_uom.uom_type::text = 'reference'::text + AND product_uom.active + AND product_uom.category_id = u.category_id LIMIT 1) + ELSE u.name + END AS uom_name, + ai.currency_id, ai.journal_id, ai.fiscal_position, ai.user_id, ai.company_id, + count(ail.*) 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(CASE + WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text]) + THEN (- ail.quantity) / u.factor + ELSE ail.quantity / u.factor + END) AS product_qty, + SUM(CASE + WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text]) + THEN - ail.price_subtotal + ELSE ail.price_subtotal + END) AS price_total, + CASE + WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text]) + THEN SUM(- ail.price_subtotal) + ELSE SUM(ail.price_subtotal) + END / CASE + WHEN SUM(ail.quantity / u.factor) <> 0::numeric + THEN CASE + WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text]) + THEN SUM((- ail.quantity) / u.factor) + ELSE SUM(ail.quantity / u.factor) + END + ELSE 1::numeric + END AS price_average, + CASE + WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text]) + THEN - ai.residual + ELSE ai.residual + END / CASE + WHEN (( SELECT count(l.id) AS count + FROM account_invoice_line l + LEFT JOIN account_invoice a ON a.id = l.invoice_id + WHERE a.id = ai.id)) <> 0 + THEN ( SELECT count(l.id) AS count + FROM account_invoice_line l + LEFT JOIN account_invoice a ON a.id = l.invoice_id + WHERE a.id = ai.id) + ELSE 1::bigint + END::numeric AS residual, + ai.section_id + FROM account_invoice_line ail + JOIN account_invoice ai ON ai.id = ail.invoice_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.uos_id + GROUP BY ail.product_id, ai.date_invoice, ai.id, + to_char(ai.date_invoice::timestamp with time zone, 'YYYY'::text), + to_char(ai.date_invoice::timestamp with time zone, 'MM'::text), + to_char(ai.date_invoice::timestamp with time zone, 'YYYY-MM-DD'::text), + ai.partner_id, ai.payment_term, ai.period_id, u.name, ai.currency_id, ai.journal_id, + ai.fiscal_position, ai.user_id, ai.company_id, ai.type, ai.state, pt.categ_id, + ai.date_due, ai.account_id, ail.account_id, ai.partner_bank_id, ai.residual, + ai.amount_total, u.uom_type, u.category_id, ai.section_id + ) AS sub + JOIN res_currency_rate cr ON (cr.currency_id = sub.currency_id) + WHERE + cr.id IN (SELECT id + FROM res_currency_rate cr2 + WHERE (cr2.currency_id = sub.currency_id) + AND ((sub.date IS NOT NULL AND cr.name <= sub.date) + OR (sub.date IS NULL AND cr.name <= NOW())) + ORDER BY name DESC LIMIT 1); """ return select_str - def _where(self): - where_str = """ - WHERE cr.id in (select id from res_currency_rate cr2 where (cr2.currency_id = ai.currency_id) - and ((ai.date_invoice is not null and cr.name <= ai.date_invoice) or (ai.date_invoice is null and cr.name <= NOW())) order by name desc limit 1) - """ - return where_str - - def _from(self): - from_str = """ - FROM account_invoice_line as ail - left join account_invoice as ai ON (ai.id=ail.invoice_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.uos_id), - res_currency_rate cr - """ - return from_str - - def _group_by(self): - group_by_str = """ - GROUP BY ail.product_id, - ai.date_invoice, - ai.id, - cr.rate, - to_char(ai.date_invoice, 'YYYY'), - to_char(ai.date_invoice, 'MM'), - to_char(ai.date_invoice, 'YYYY-MM-DD'), - ai.partner_id, - ai.payment_term, - ai.period_id, - u.name, - ai.currency_id, - ai.journal_id, - ai.fiscal_position, - ai.user_id, - ai.company_id, - ai.type, - ai.state, - pt.categ_id, - ai.date_due, - ai.account_id, - ail.account_id, - ai.partner_bank_id, - ai.residual, - ai.amount_total, - u.uom_type, - u.category_id - """ - return group_by_str def init(self, cr): # self._table = account_invoice_report tools.drop_view_if_exists(cr, self._table) - cr.execute("CREATE or REPLACE VIEW %s as (%s %s %s %s)" % ( + cr.execute("CREATE or REPLACE VIEW %s as (%s %s)" % ( self._table, - self._select(), self._from(), self._where(), self._group_by())) + self._select())) account_invoice_report() diff --git a/addons/account/report/account_invoice_report_view.xml b/addons/account/report/account_invoice_report_view.xml index 289db376e5d..66e17560bde 100644 --- a/addons/account/report/account_invoice_report_view.xml +++ b/addons/account/report/account_invoice_report_view.xml @@ -30,8 +30,6 @@ - - @@ -93,7 +91,7 @@ tree,graph {'search_default_period':1,'search_default_current':1, 'search_default_year': 1, 'search_default_category_product':1, 'search_default_customer':1, 'group_by':[], 'group_by_no_leaf':1,} - From this report, you can have an overview of the amount invoiced to your customer as well as payment delays. The tool search can also be used to personalise your Invoices reports and so, match this analysis to your needs. + From this report, you can have an overview of the amount invoiced to your customer. The tool search can also be used to personalise your Invoices reports and so, match this analysis to your needs. diff --git a/addons/product/product.py b/addons/product/product.py index 1333c9581a7..fb28f85b10f 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -546,7 +546,7 @@ class product_product(osv.osv): 'default_code' : fields.char('Internal Reference', size=64, select=True), 'active': fields.boolean('Active', help="If unchecked, it will allow you to hide the product without removing it."), 'variants': fields.char('Variants', size=64), - 'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True, ondelete="cascade"), + 'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True, ondelete="cascade", select=True), 'ean13': fields.char('EAN13 Barcode', size=13, help="International Article Number used for product identification."), 'packaging' : fields.one2many('product.packaging', 'product_id', 'Logistical Units', help="Gives the different ways to package the same product. This has no impact on the picking order and is mainly used if you use the EDI module."), 'price_extra': fields.float('Variant Price Extra', digits_compute=dp.get_precision('Product Price')),