From c2f3b2d93fc8c66da45c8197da2b4a261db835fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 24 Sep 2012 22:18:14 +0200 Subject: [PATCH] Active Record --- __init__.py | 16 ++ opportunity.py | 683 +++++++++++++++++++++---------------------------- 2 files changed, 309 insertions(+), 390 deletions(-) diff --git a/__init__.py b/__init__.py index 85e38eeb8f..538945e5c9 100644 --- a/__init__.py +++ b/__init__.py @@ -1,4 +1,20 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. +from trytond.pool import Pool from .opportunity import * + + +def register(): + Pool.register( + SaleOpportunity, + SaleOpportunityLine, + SaleOpportunityHistory, + SaleOpportunityEmployee, + OpenSaleOpportunityEmployeeStart, + SaleOpportunityMonthly, + SaleOpportunityEmployeeMonthly, + module='sale_opportunity', type_='model') + Pool.register( + OpenSaleOpportunityEmployee, + module='sale_opportunity', type_='wizard') diff --git a/opportunity.py b/opportunity.py index 9b75abd1ea..ac605d1e60 100644 --- a/opportunity.py +++ b/opportunity.py @@ -10,6 +10,11 @@ from trytond.pyson import Equal, Eval, Not, In, If, Get, PYSONEncoder from trytond.transaction import Transaction from trytond.pool import Pool +__all__ = ['SaleOpportunity', 'SaleOpportunityLine', + 'SaleOpportunityHistory', 'SaleOpportunityEmployee', + 'OpenSaleOpportunityEmployeeStart', 'OpenSaleOpportunityEmployee', + 'SaleOpportunityMonthly', 'SaleOpportunityEmployeeMonthly'] + STATES = [ ('lead', 'Lead'), ('opportunity', 'Opportunity'), @@ -29,11 +34,9 @@ _DEPENDS_STOP = ['state'] class SaleOpportunity(Workflow, ModelSQL, ModelView): 'Sale Opportunity' - _name = "sale.opportunity" - _description = __doc__ + __name__ = "sale.opportunity" _history = True _rec_name = 'description' - party = fields.Many2One('party.party', 'Party', required=True, select=True, on_change=['party'], states=_STATES_STOP, depends=_DEPENDS_STOP) address = fields.Many2One('party.address', 'Address', @@ -88,19 +91,20 @@ class SaleOpportunity(Workflow, ModelSQL, ModelView): 'invisible': Eval('state') != 'converted', }, depends=['state']) - def __init__(self): - super(SaleOpportunity, self).__init__() - self._order.insert(0, ('start_date', 'DESC')) - self._sql_constraints += [ + @classmethod + def __setup__(cls): + super(SaleOpportunity, cls).__setup__() + cls._order.insert(0, ('start_date', 'DESC')) + cls._sql_constraints += [ ('check_percentage', 'CHECK(probability >= 0 AND probability <= 100)', 'Probability must be between 0 and 100!') - ] - self._error_messages.update({ + ] + cls._error_messages.update({ 'delete_cancel': 'Sale Opportunity "%s" must be cancelled '\ 'before deletion!', }) - self._transitions |= set(( + cls._transitions |= set(( ('lead', 'opportunity'), ('lead', 'lost'), ('lead', 'cancelled'), @@ -111,7 +115,7 @@ class SaleOpportunity(Workflow, ModelSQL, ModelView): ('lost', 'lead'), ('cancelled', 'lead'), )) - self._buttons.update({ + cls._buttons.update({ 'lead': { 'invisible': ~Eval('state').in_( ['cancelled', 'lost', 'opportunity']), @@ -132,202 +136,185 @@ class SaleOpportunity(Workflow, ModelSQL, ModelView): }, }) - def default_state(self): + @staticmethod + def default_state(): return 'lead' - def default_start_date(self): - date_obj = Pool().get('ir.date') - return date_obj.today() + @staticmethod + def default_start_date(): + Date = Pool().get('ir.date') + return Date.today() - def default_probability(self): + @staticmethod + def default_probability(): return 50 - def default_company(self): + @staticmethod + def default_company(): return Transaction().context.get('company') - def default_employee(self): - user_obj = Pool().get('res.user') + @staticmethod + def default_employee(): + User = Pool().get('res.user') if Transaction().context.get('employee'): return Transaction().context['employee'] else: - user = user_obj.browse(Transaction().user) + user = User(Transaction().user) if user.employee: return user.employee.id - def default_payment_term(self): - payment_term_obj = Pool().get('account.invoice.payment_term') - payment_term_ids = payment_term_obj.search(self.payment_term.domain) - if len(payment_term_ids) == 1: - return payment_term_ids[0] + @classmethod + def default_payment_term(cls): + PaymentTerm = Pool().get('account.invoice.payment_term') + payment_terms = PaymentTerm.search(cls.payment_term.domain) + if len(payment_terms) == 1: + return payment_terms[0].id - def get_currency(self, ids, name): + def get_currency(self, name): + return self.company.currency.id + + def get_currency_digits(self, name): + return self.company.currency.digits + + def on_change_company(self): res = {} - for opportunity in self.browse(ids): - res[opportunity.id] = opportunity.company.currency.id + if self.company: + res['currency'] = self.company.currency.id + res['currency.rec_name'] = self.company.currency.rec_name + res['currency_digits'] = self.company.currency.digits return res - def get_currency_digits(self, ids, name): - res = {} - for opportunity in self.browse(ids): - res[opportunity.id] = opportunity.company.currency.digits - return res - - def on_change_company(self, values): - company_obj = Pool().get('company.company') - - res = {} - if values.get('company'): - company = company_obj.browse(values['company']) - res['currency'] = company.currency.id - res['currency.rec_name'] = company.currency.rec_name - res['currency_digits'] = company.currency.digits - return res - - def on_change_party(self, values): - party_obj = Pool().get('party.party') - payment_term_obj = Pool().get('account.invoice.payment_term') + def on_change_party(self): + PaymentTerm = Pool().get('account.invoice.payment_term') res = { 'payment_term': None, - } - if values.get('party'): - party = party_obj.browse(values['party']) - if party.customer_payment_term: - res['payment_term'] = party.customer_payment_term.id + } + if self.party: + if self.party.customer_payment_term: + res['payment_term'] = self.party.customer_payment_term.id + res['payment_term.rec_name'] = \ + self.party.customer_payment_term.rec_name if not res['payment_term']: res['payment_term'] = self.default_payment_term() - if res['payment_term']: - res['payment_term.rec_name'] = payment_term_obj.browse( - res['payment_term']).rec_name + res['payment_term.rec_name'] = PaymentTerm( + res['payment_term']).rec_name + print res return res - def _get_sale_line_opportunity_line(self, opportunity): + def _get_sale_line_opportunity_line(self, sale): ''' - Return sale line values for each opportunity line - - :param opportunity: the BrowseRecord of opportunity - - :return: a dictionary with opportunity line id as key - and a dictionary of sale line values as value + Return sale lines for each opportunity line ''' - line_obj = Pool().get('sale.opportunity.line') res = {} - for line in opportunity.lines: + for line in self.lines: if line.sale_line: continue - val = line_obj.get_sale_line(line) - if val: - res[line.id] = val + sale_line = line.get_sale_line(sale) + if sale_line: + res[line.id] = sale_line return res - def _get_sale_opportunity(self, opportunity): + def _get_sale_opportunity(self): ''' - Return sale values for an opportunity - - :param opportunity: the BrowseRecord of the opportunity - - :return: a dictionary with sale fields as key and sale values as value + Return sale for an opportunity ''' - res = { - 'description': opportunity.description, - 'party': opportunity.party.id, - 'payment_term': opportunity.payment_term.id, - 'company': opportunity.company.id, - 'invoice_address': opportunity.address and opportunity.address.id, - 'shipment_address': opportunity.address and opportunity.address.id, - 'currency': opportunity.company.currency.id, - 'comment': opportunity.comment, - } - return res + Sale = Pool().get('sale.sale') + with Transaction().set_user(0, set_context=True): + return Sale( + description=self.description, + party=self.party, + payment_term=self.payment_term, + company=self.company, + invoice_address=self.address, + shipment_address=self.address, + currency=self.company.currency, + comment=self.comment, + sale_date=None, + ) - def create_sale(self, opportunity): + def create_sale(self): ''' - Create a sale for the opportunity and return the sale id + Create a sale for the opportunity and return the sale ''' - pool = Pool() - sale_obj = pool.get('sale.sale') - sale_line_obj = pool.get('sale.line') - line_obj = pool.get('sale.opportunity.line') + Line = Pool().get('sale.opportunity.line') - if opportunity.sale: + if self.sale: return - values = self._get_sale_opportunity(opportunity) - sale_line_values = self._get_sale_line_opportunity_line(opportunity) + sale = self._get_sale_opportunity() + sale_lines = self._get_sale_line_opportunity_line(sale) + sale.save() - with Transaction().set_user(0, set_context=True): - sale_id = sale_obj.create(values) + for line_id, sale_line in sale_lines.iteritems(): + sale_line.sale = sale + sale_line.save() + Line.write([Line(line_id)], { + 'sale_line': sale_line.id, + }) - for line_id, values in sale_line_values.iteritems(): - values['sale'] = sale_id - with Transaction().set_user(0, set_context=True): - sale_line_id = sale_line_obj.create(values) - line_obj.write(line_id, { - 'sale_line': sale_line_id, + self.write([self], { + 'sale': sale.id, }) + return sale - self.write(opportunity.id, { - 'sale': sale_id, - }) - return sale_id - - def delete(self, ids): - if isinstance(ids, (int, long)): - ids = [ids] + @classmethod + def delete(cls, opportunities): # Cancel before delete - self.cancel(ids) - for opportunity in self.browse(ids): + cls.cancel(opportunities) + for opportunity in opportunities: if opportunity.state != 'cancel': - self.raise_user_error('delete_cancel', opportunity.rec_name) - return super(SaleOpportunity, self).delete(ids) + cls.raise_user_error('delete_cancel', opportunity.rec_name) + super(SaleOpportunity, cls).delete(opportunities) + @classmethod @ModelView.button @Workflow.transition('lead') - def lead(self, ids): + def lead(cls, opportunities): pass + @classmethod @ModelView.button @Workflow.transition('opportunity') - def opportunity(self, ids): + def opportunity(cls, opportunities): pass + @classmethod @ModelView.button @Workflow.transition('converted') - def convert(self, ids): - date_obj = Pool().get('ir.date') - self.write(ids, { - 'end_date': date_obj.today(), + def convert(cls, opportunities): + Date = Pool().get('ir.date') + cls.write(opportunities, { + 'end_date': Date.today(), }) - for opportunity in self.browse(ids): - self.create_sale(opportunity) + for opportunity in opportunities: + opportunity.create_sale() + @classmethod @ModelView.button @Workflow.transition('lost') - def lost(self, ids): - date_obj = Pool().get('ir.date') - self.write(ids, { - 'end_date': date_obj.today(), + def lost(cls, opportunities): + Date = Pool().get('ir.date') + cls.write(opportunities, { + 'end_date': Date.today(), }) + @classmethod @ModelView.button @Workflow.transition('cancelled') - def cancel(self, ids): - date_obj = Pool().get('ir.date') - self.write(ids, { - 'end_date': date_obj.today(), + def cancel(cls, opportunities): + Date = Pool().get('ir.date') + cls.write(opportunities, { + 'end_date': Date.today(), }) -SaleOpportunity() - class SaleOpportunityLine(ModelSQL, ModelView): 'Sale Opportunity Line' - _name = "sale.opportunity.line" - _description = __doc__ + __name__ = "sale.opportunity.line" _rec_name = "product" _history = True - opportunity = fields.Many2One('sale.opportunity', 'Opportunity') sequence = fields.Integer('Sequence', order_field='(%(table)s.sequence IS NULL) %(order)s, ' @@ -338,97 +325,68 @@ class SaleOpportunityLine(ModelSQL, ModelView): digits=(16, Eval('unit_digits', 2)), depends=['unit_digits']) unit = fields.Many2One('product.uom', 'Unit', required=True) unit_digits = fields.Function(fields.Integer('Unit Digits', - on_change_with=['unit']), 'get_unit_digits') + on_change_with=['unit']), 'on_change_with_unit_digits') sale_line = fields.Many2One('sale.line', 'Sale Line', readonly=True, states={ 'invisible': (Eval('_parent_opportunity', {}).get('state') != 'converted'), }) - def __init__(self): - super(SaleOpportunityLine, self).__init__() - self._order.insert(0, ('sequence', 'ASC')) + @classmethod + def __setup__(cls): + super(SaleOpportunityLine, cls).__setup__() + cls._order.insert(0, ('sequence', 'ASC')) - def init(self, module_name): + @classmethod + def __register__(cls, module_name): cursor = Transaction().cursor - table = TableHandler(cursor, self, module_name) + table = TableHandler(cursor, cls, module_name) - super(SaleOpportunityLine, self).init(module_name) + super(SaleOpportunityLine, cls).__register__(module_name) # Migration from 2.4: drop required on sequence table.not_null_action('sequence', action='remove') - def on_change_with_unit_digits(self, vals): - uom_obj = Pool().get('product.uom') - if vals.get('unit'): - uom = uom_obj.browse(vals['unit']) - return uom.digits + def on_change_with_unit_digits(self, name=None): + if self.unit: + return self.unit.digits return 2 - def get_unit_digits(self, ids, name): - res = {} - for line in self.browse(ids): - if line.unit: - res[line.id] = line.unit.digits - else: - res[line.id] = 2 - return res - - def on_change_product(self, vals): - product_obj = Pool().get('product.product') - - if not vals.get('product'): + def on_change_product(self): + if not self.product: return {} res = {} - product = product_obj.browse(vals['product']) - category = product.sale_uom.category - if not vals.get('unit') \ - or vals.get('unit') not in [x.id for x in category.uoms]: - res['unit'] = product.sale_uom.id - res['unit.rec_name'] = product.sale_uom.rec_name - res['unit_digits'] = product.sale_uom.digits + category = self.product.sale_uom.category + if (not self.unit + or self.unit not in category.uoms): + res['unit'] = self.product.sale_uom.id + res['unit.rec_name'] = self.product.sale_uom.rec_name + res['unit_digits'] = self.product.sale_uom.digits return res - def get_sale_line(self, line): + def get_sale_line(self, sale): ''' - Return sale line values for opportunity line - - :param line: the BrowseRecord of the line - - :return: a dictionary with sale line fields as key - and sale line values as value + Return sale line for opportunity line ''' - sale_line_obj = Pool().get('sale.line') - res = { - 'type': 'line', - 'quantity': line.quantity, - 'unit': line.unit.id, - 'product': line.product.id, - } - res.update(sale_line_obj.on_change_product({ - 'product': line.product.id, - 'unit': line.unit.id, - 'quantity': line.quantity, - '_parent_sale.party': line.opportunity.party.id, - '_parent_sale.currency': line.opportunity.company.currency.id, - })) - for field_name, field in sale_line_obj._columns.iteritems(): - if field._type not in ('one2many', 'many2many'): - continue - if field_name not in res: - continue - res[field_name] = [('add', res[field_name])] - return res - -SaleOpportunityLine() + SaleLine = Pool().get('sale.line') + with Transaction().set_user(0, set_context=True): + sale_line = SaleLine( + type='line', + quantity=self.quantity, + unit=self.unit, + product=self.product, + sale=sale, + description=None, + ) + for k, v in sale_line.on_change_product().iteritems(): + setattr(sale_line, k, v) + return sale_line class SaleOpportunityHistory(ModelSQL, ModelView): 'Sale Opportunity History' - _name = 'sale.opportunity.history' - _description = __doc__ - + __name__ = 'sale.opportunity.history' date = fields.DateTime('Change Date') opportunity = fields.Many2One('sale.opportunity', 'Sale Opportunity') user = fields.Many2One('res.user', 'User') @@ -454,13 +412,15 @@ class SaleOpportunityHistory(ModelSQL, ModelView): 'invisible': Not(Equal(Eval('state'), 'lost')), }, depends=['state']) - def __init__(self): - super(SaleOpportunityHistory, self).__init__() - self._order.insert(0, ('date', 'DESC')) + @classmethod + def __setup__(cls): + super(SaleOpportunityHistory, cls).__setup__() + cls._order.insert(0, ('date', 'DESC')) - def _table_query_fields(self): - opportunity_obj = Pool().get('sale.opportunity') - table = '%s__history' % opportunity_obj._table + @classmethod + def _table_query_fields(cls): + Opportunity = Pool().get('sale.opportunity') + table = '%s__history' % Opportunity._table return [ 'MIN("%s".__id) AS id' % table, '"%s".id AS opportunity' % table, @@ -469,44 +429,42 @@ class SaleOpportunityHistory(ModelSQL, ModelView): ('COALESCE("%s".write_uid, "%s".create_uid) AS user' % (table, table)), ] + ['"%s"."%s"' % (table, name) - for name, field in self._columns.iteritems() + for name, field in cls._fields.iteritems() if name not in ('id', 'opportunity', 'date', 'user') and not hasattr(field, 'set')] - def _table_query_group(self): - opportunity_obj = Pool().get('sale.opportunity') - table = '%s__history' % opportunity_obj._table + @classmethod + def _table_query_group(cls): + Opportunity = Pool().get('sale.opportunity') + table = '%s__history' % Opportunity._table return [ '"%s".id' % table, 'COALESCE("%s".write_uid, "%s".create_uid)' % (table, table), ] + ['"%s"."%s"' % (table, name) - for name, field in self._columns.iteritems() + for name, field in cls._fields.iteritems() if name not in ('id', 'opportunity', 'date', 'user') and not hasattr(field, 'set')] - def table_query(self): - opportunity_obj = Pool().get('sale.opportunity') - return (('SELECT ' + \ - (', '.join(self._table_query_fields())) + \ - ' FROM "%s__history" ' - 'GROUP BY ' + \ - (', '.join(self._table_query_group()))) % \ - opportunity_obj._table, []) + @classmethod + def table_query(cls): + Opportunity = Pool().get('sale.opportunity') + return (('SELECT ' + (', '.join(cls._table_query_fields())) + + ' FROM "%s__history" GROUP BY ' + + (', '.join(cls._table_query_group()))) + % Opportunity._table, []) - def get_lines(self, ids, name): - line_obj = Pool().get('sale.opportunity.line') - histories = self.browse(ids) - result = {} + def get_lines(self, name): + Line = Pool().get('sale.opportunity.line') # We will always have only one id per call due to datetime_field - for history in histories: - result[history.id] = line_obj.search([ - ('opportunity', '=', history.opportunity.id), - ]) - return result + lines = Line.search([ + ('opportunity', '=', self.opportunity.id), + ]) + return [l.id for l in lines] - def read(self, ids, fields_names=None): - res = super(SaleOpportunityHistory, self).read(ids, - fields_names=fields_names) + @classmethod + def read(cls, ids, fields_names=None): + res = super(SaleOpportunityHistory, cls).read(ids, + fields_names=fields_names) # Remove microsecond from timestamp for values in res: @@ -518,14 +476,10 @@ class SaleOpportunityHistory(ModelSQL, ModelView): values['date'] = values['date'].replace(microsecond=0) return res -SaleOpportunityHistory() - class SaleOpportunityEmployee(ModelSQL, ModelView): 'Sale Opportunity per Employee' - _name = 'sale.opportunity_employee' - _description = __doc__ - + __name__ = 'sale.opportunity_employee' employee = fields.Many2One('company.employee', 'Employee') number = fields.Integer('Number') converted = fields.Integer('Converted') @@ -545,14 +499,17 @@ class SaleOpportunityEmployee(ModelSQL, ModelView): conversion_amount_rate = fields.Function(fields.Float( 'Conversion Amount Rate', help='In %'), 'get_conversion_amount_rate') - def _converted_state(self): + @staticmethod + def _converted_state(): return ['converted'] - def _lost_state(self): + @staticmethod + def _lost_state(): return ['lost'] - def table_query(self): - opportunity_obj = Pool().get('sale.opportunity') + @classmethod + def table_query(cls): + Opportunity = Pool().get('sale.opportunity') clause = ' ' args = [True] if Transaction().context.get('start_date'): @@ -570,69 +527,48 @@ class SaleOpportunityEmployee(ModelSQL, ModelView): 'company, ' 'COUNT(1) AS number, ' 'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x - for x in self._converted_state()) + ') ' + for x in cls._converted_state()) + ') ' 'THEN 1 ELSE 0 END) AS converted, ' 'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x - for x in self._lost_state()) + ') ' + for x in cls._lost_state()) + ') ' 'THEN 1 ELSE 0 END) AS lost, ' 'SUM(amount) AS amount, ' 'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x - for x in self._converted_state()) + ') ' + for x in cls._converted_state()) + ') ' 'THEN amount ELSE 0 END) AS converted_amount ' - 'FROM "' + opportunity_obj._table + '" ' - 'WHERE %s ' \ - + clause + \ - 'GROUP BY employee, company', args) + 'FROM "' + Opportunity._table + '" ' + 'WHERE %s ' + clause + + 'GROUP BY employee, company', args) - def get_conversion_rate(self, ids, name): - res = {} - for record in self.browse(ids): - if record.number: - res[record.id] = (float(record.converted) - / record.number * 100.0) - else: - res[record.id] = 0.0 - return res + def get_conversion_rate(self, name): + if self.number: + return float(self.converted) / self.number * 100.0 + else: + return 0.0 - def get_currency(self, ids, name): - res = {} - for record in self.browse(ids): - res[record.id] = record.company.currency.id - return res + def get_currency(self, name): + return self.company.currency.id - def get_currency_digits(self, ids, name): - res = {} - for record in self.browse(ids): - res[record.id] = record.company.currency.digits - return res + def get_currency_digits(self, name): + return self.company.currency.digits - def get_conversion_amount_rate(self, ids, name): - res = {} - for record in self.browse(ids): - if record.amount: - res[record.id] = (float(record.converted_amount) / - float(record.amount) * 100.0) - else: - res[record.id] = 0.0 - return res - -SaleOpportunityEmployee() + def get_conversion_amount_rate(self, name): + if self.amount: + return float(self.converted_amount) / float(self.amount) * 100.0 + else: + return 0.0 class OpenSaleOpportunityEmployeeStart(ModelView): 'Open Sale Opportunity per Employee' - _name = 'sale.opportunity_employee.open.start' - _description = __doc__ + __name__ = 'sale.opportunity_employee.open.start' start_date = fields.Date('Start Date') end_date = fields.Date('End Date') -OpenSaleOpportunityEmployeeStart() - class OpenSaleOpportunityEmployee(Wizard): 'Open Sale Opportunity per Employee' - _name = 'sale.opportunity_employee.open' - + __name__ = 'sale.opportunity_employee.open' start = StateView('sale.opportunity_employee.open.start', 'sale_opportunity.opportunity_employee_open_start_view_form', [ Button('Cancel', 'end', 'tryton-cancel'), @@ -640,21 +576,17 @@ class OpenSaleOpportunityEmployee(Wizard): ]) open_ = StateAction('sale_opportunity.act_opportunity_employee_form') - def do_open_(self, session, action): + def do_open_(self, action): action['pyson_context'] = PYSONEncoder().encode({ - 'start_date': session.start.start_date, - 'end_date': session.start.end_date, + 'start_date': self.start.start_date, + 'end_date': self.start.end_date, }) return action, {} -OpenSaleOpportunityEmployee() - class SaleOpportunityMonthly(ModelSQL, ModelView): 'Sale Opportunity per Month' - _name = 'sale.opportunity_monthly' - _description = __doc__ - + __name__ = 'sale.opportunity_monthly' year = fields.Char('Year') month = fields.Integer('Month') year_month = fields.Function(fields.Char('Year-Month'), @@ -677,21 +609,25 @@ class SaleOpportunityMonthly(ModelSQL, ModelView): conversion_amount_rate = fields.Function(fields.Float( 'Conversion Amount Rate', help='In %'), 'get_conversion_amount_rate') - def __init__(self): - super(SaleOpportunityMonthly, self).__init__() - self._order.insert(0, ('year', 'DESC')) - self._order.insert(1, ('month', 'DESC')) + @classmethod + def __setup__(cls): + super(SaleOpportunityMonthly, cls).__setup__() + cls._order.insert(0, ('year', 'DESC')) + cls._order.insert(1, ('month', 'DESC')) - def _converted_state(self): + @staticmethod + def _converted_state(): return ['converted'] - def _lost_state(self): + @staticmethod + def _lost_state(): return ['lost'] - def table_query(self): - opportunity_obj = Pool().get('sale.opportunity') - type_id = FIELDS[self.id._type].sql_type(self.id)[0] - type_year = FIELDS[self.year._type].sql_type(self.year)[0] + @classmethod + def table_query(cls): + Opportunity = Pool().get('sale.opportunity') + type_id = FIELDS[cls.id._type].sql_type(cls.id)[0] + type_year = FIELDS[cls.year._type].sql_type(cls.year)[0] return ('SELECT CAST(id AS ' + type_id + ') AS id, create_uid, ' 'create_date, write_uid, write_date, ' 'CAST(year AS ' + type_year + ') AS year, month, company, ' @@ -708,65 +644,44 @@ class SaleOpportunityMonthly(ModelSQL, ModelView): 'company, ' 'COUNT(1) AS number, ' 'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x - for x in self._converted_state()) + ') ' + for x in cls._converted_state()) + ') ' 'THEN 1 ELSE 0 END) AS converted, ' 'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x - for x in self._lost_state()) + ') ' + for x in cls._lost_state()) + ') ' 'THEN 1 ELSE 0 END) AS lost, ' 'SUM(amount) AS amount, ' 'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x - for x in self._converted_state()) + ') ' + for x in cls._converted_state()) + ') ' 'THEN amount ELSE 0 END) AS converted_amount ' - 'FROM "' + opportunity_obj._table + '" ' - 'GROUP BY year, month, company) AS "' + self._table + '"', + 'FROM "' + Opportunity._table + '" ' + 'GROUP BY year, month, company) AS "' + cls._table + '"', []) - def get_conversion_rate(self, ids, name): - res = {} - for record in self.browse(ids): - if record.number: - res[record.id] = (float(record.converted) - / record.number * 100.0) - else: - res[record.id] = 0.0 - return res + def get_conversion_rate(self, name): + if self.number: + return float(self.converted) / self.number * 100.0 + else: + return 0.0 - def get_year_month(self, ids, name): - res = {} - for record in self.browse(ids): - res[record.id] = '%s-%s' % (record.year, int(record.month)) - return res + def get_year_month(self, name): + return '%s-%s' % (self.year, int(self.month)) - def get_currency(self, ids, name): - res = {} - for record in self.browse(ids): - res[record.id] = record.company.currency.id - return res + def get_currency(self, name): + return self.company.currency.id - def get_currency_digits(self, ids, name): - res = {} - for record in self.browse(ids): - res[record.id] = record.company.currency.digits - return res + def get_currency_digits(self, name): + return self.company.currency.digits - def get_conversion_amount_rate(self, ids, name): - res = {} - for record in self.browse(ids): - if record.amount: - res[record.id] = (float(record.converted_amount) / - float(record.amount) * 100.0) - else: - res[record.id] = 0.0 - return res - -SaleOpportunityMonthly() + def get_conversion_amount_rate(self, name): + if self.amount: + return float(self.converted_amount) / float(self.amount) * 100.0 + else: + return 0.0 class SaleOpportunityEmployeeMonthly(ModelSQL, ModelView): 'Sale Opportunity per Employee per Month' - _name = 'sale.opportunity_employee_monthly' - _description = __doc__ - + __name__ = 'sale.opportunity_employee_monthly' year = fields.Char('Year') month = fields.Integer('Month') employee = fields.Many2One('company.employee', 'Employee') @@ -788,22 +703,26 @@ class SaleOpportunityEmployeeMonthly(ModelSQL, ModelView): conversion_amount_rate = fields.Function(fields.Float( 'Conversion Amount Rate', help='In %'), 'get_conversion_amount_rate') - def __init__(self): - super(SaleOpportunityEmployeeMonthly, self).__init__() - self._order.insert(0, ('year', 'DESC')) - self._order.insert(1, ('month', 'DESC')) - self._order.insert(2, ('employee', 'ASC')) + @classmethod + def __setup__(cls): + super(SaleOpportunityEmployeeMonthly, cls).__setup__() + cls._order.insert(0, ('year', 'DESC')) + cls._order.insert(1, ('month', 'DESC')) + cls._order.insert(2, ('employee', 'ASC')) - def _converted_state(self): + @staticmethod + def _converted_state(): return ['converted'] - def _lost_state(self): + @staticmethod + def _lost_state(): return ['lost'] - def table_query(self): - opportunity_obj = Pool().get('sale.opportunity') - type_id = FIELDS[self.id._type].sql_type(self.id)[0] - type_year = FIELDS[self.year._type].sql_type(self.year)[0] + @classmethod + def table_query(cls): + Opportunity = Pool().get('sale.opportunity') + type_id = FIELDS[cls.id._type].sql_type(cls.id)[0] + type_year = FIELDS[cls.year._type].sql_type(cls.year)[0] return ('SELECT CAST(id AS ' + type_id + ') AS id, create_uid, ' 'create_date, write_uid, write_date, ' 'CAST(year AS ' + type_year + ') AS year, month, ' @@ -823,49 +742,33 @@ class SaleOpportunityEmployeeMonthly(ModelSQL, ModelView): 'company, ' 'COUNT(1) AS number, ' 'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x - for x in self._converted_state()) + ') ' + for x in cls._converted_state()) + ') ' 'THEN 1 ELSE 0 END) AS converted, ' 'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x - for x in self._lost_state()) + ') ' + for x in cls._lost_state()) + ') ' 'THEN 1 ELSE 0 END) AS lost, ' 'SUM(amount) AS amount, ' 'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x - for x in self._converted_state()) + ') ' + for x in cls._converted_state()) + ') ' 'THEN amount ELSE 0 END) AS converted_amount ' - 'FROM "' + opportunity_obj._table + '" ' + 'FROM "' + Opportunity._table + '" ' 'GROUP BY year, month, employee, company) ' - 'AS "' + self._table + '"', []) + 'AS "' + cls._table + '"', []) - def get_conversion_rate(self, ids, name): - res = {} - for record in self.browse(ids): - if record.number: - res[record.id] = (float(record.converted) - / record.number * 100.0) - else: - res[record.id] = 0.0 - return res + def get_conversion_rate(self, name): + if self.number: + return float(self.converted) / self.number * 100.0 + else: + return 0.0 - def get_currency(self, ids, name): - res = {} - for record in self.browse(ids): - res[record.id] = record.company.currency.id - return res + def get_currency(self, name): + return self.company.currency.id - def get_currency_digits(self, ids, name): - res = {} - for record in self.browse(ids): - res[record.id] = record.company.currency.digits - return res + def get_currency_digits(self, name): + return self.company.currency.digits - def get_conversion_amount_rate(self, ids, name): - res = {} - for record in self.browse(ids): - if record.amount: - res[record.id] = (float(record.converted_amount) / - float(record.amount) * 100.0) - else: - res[record.id] = 0.0 - return res - -SaleOpportunityEmployeeMonthly() + def get_conversion_amount_rate(self, name): + if self.amount: + return float(self.converted_amount) / float(self.amount) * 100.0 + else: + return 0.0