Active Record

This commit is contained in:
Cédric Krier
2012-09-24 22:18:14 +02:00
parent 0474bdf24b
commit c2f3b2d93f
2 changed files with 309 additions and 390 deletions
+16
View File
@@ -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')
+293 -390
View File
@@ -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