Update for new Transaction

This commit is contained in:
Cédric Krier committed 2010-09-07 20:43:03 +02:00
1 parent 4d64fe5c92
commit 24fae3284a
2 files changed
+125 -164

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@ Installing trytond_sale_opportunity
Prerequisites
-------------
* Python 2.4 or later (http://www.python.org/)
* Python 2.5 or later (http://www.python.org/)
* trytond (http://www.tryton.org/)
* trytond_party (http://www.tryton.org/)
* trytond_company (http://www.tryton.org/)
+124 -163
View File
@@ -1,11 +1,13 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
"Sales extension for managing leads and opportunities"
from __future__ import with_statement
import datetime
from trytond.model import ModelView, ModelSQL, ModelWorkflow, fields
from trytond.wizard import Wizard
from trytond.backend import FIELDS
from trytond.pyson import Equal, Eval, Not, In, If, Get, PYSONEncoder
from trytond.transaction import Transaction
STATES = [
('lead', 'Lead'),
@@ -21,6 +23,7 @@ _STATES_STOP = {
'readonly': In(Eval('state'), ['converted', 'lost', 'cancelled']),
}
class SaleOpportunity(ModelWorkflow, ModelSQL, ModelView):
'Sale Opportunity'
_name = "sale.opportunity"
@@ -98,79 +101,70 @@ class SaleOpportunity(ModelWorkflow, ModelSQL, ModelView):
'button_lead': True,
})
def default_state(self, cursor, user, context=None):
def default_state(self):
return 'lead'
def default_start_date(self, cursor, user, context=None):
def default_start_date(self):
date_obj = self.pool.get('ir.date')
return date_obj.today(cursor, user, context=context)
return date_obj.today()
def default_probability(self, cursor, user, context=None):
def default_probability(self):
return 50
def default_company(self, cursor, user, context=None):
if context is None:
context = {}
return context.get('company', False)
def default_company(self):
return Transaction().context.get('company') or False
def default_employee(self, cursor, user_id, context=None):
def default_employee(self):
user_obj = self.pool.get('res.user')
employee_obj = self.pool.get('company.employee')
if context is None:
context = {}
employee_id = None
if context.get('employee'):
employee_id = context['employee']
employee_id = False
if Transaction().context.get('employee'):
employee_id = Transaction().context['employee']
else:
user = user_obj.browse(cursor, user_id, user_id, context=context)
user = user_obj.browse(Transaction().user)
if user.employee:
employee_id = user.employee.id
if employee_id:
return employee_id
return False
return employee_id
def default_payment_term(self, cursor, user, context=None):
def default_payment_term(self):
payment_term_obj = self.pool.get('account.invoice.payment_term')
payment_term_ids = payment_term_obj.search(cursor, user,
self.payment_term.domain, context=context)
payment_term_ids = payment_term_obj.search(self.payment_term.domain)
if len(payment_term_ids) == 1:
return payment_term_ids[0]
return False
def default_warehouse(self, cursor, user, context=None):
def default_warehouse(self):
location_obj = self.pool.get('stock.location')
location_ids = location_obj.search(cursor, user,
self.warehouse.domain, context=context)
location_ids = location_obj.search(self.warehouse.domain)
if len(location_ids) == 1:
return location_ids[0]
return False
def get_currency(self, cursor, user, ids, name, context=None):
def get_currency(self, ids, name):
res = {}
for opportunity in self.browse(cursor, user, ids, context=context):
for opportunity in self.browse(ids):
res[opportunity.id] = opportunity.company.currency.id
return res
def get_currency_digits(self, cursor, user, ids, name, context=None):
def get_currency_digits(self, ids, name):
res = {}
for opportunity in self.browse(cursor, user, ids, context=context):
for opportunity in self.browse(ids):
res[opportunity.id] = opportunity.company.currency.digits
return res
def on_change_company(self, cursor, user, values, context=None):
def on_change_company(self, values):
company_obj = self.pool.get('company.company')
res = {}
if values.get('company'):
company = company_obj.browse(cursor, user, values['company'],
context=context)
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, cursor, user, values, context=None):
def on_change_party(self, values):
party_obj = self.pool.get('party.party')
payment_term_obj = self.pool.get('account.invoice.payment_term')
@@ -178,47 +172,38 @@ class SaleOpportunity(ModelWorkflow, ModelSQL, ModelView):
'payment_term': False,
}
if vals.get('party'):
party = party_obj.browse(cursor, user, vals['party'],
context=context)
party = party_obj.browse(vals['party'])
if party.payment_term:
res['payment_term'] = party.payment_term.id
if not res['payment_term']:
res['payment_term'] = self.default_payment_term(cursor, user,
context=context)
res['payment_term'] = self.default_payment_term()
if res['payment_term']:
res['payment_term.rec_name'] = payment_term_obj.browse(cursor, user,
res['payment_term'], context=context).rec_name
res['payment_term.rec_name'] = payment_term_obj.browse(
res['payment_term']).rec_name
return res
def set_end_date(self, cursor, user, opportunity_id, state, context=None):
def set_end_date(self, opportunity_id, state):
"""
This will fill the end_date for a lead/opportunity and change the state
:param cursor: the database cursor
:param user: the user id
:param opportunity_id: the id of the opportunity
:param state: the target state
:param context: the context
"""
date_obj = self.pool.get('ir.date')
self.write(cursor, user, opportunity_id, {
'end_date': date_obj.today(cursor, user, context=context),
self.write(opportunity_id, {
'end_date': date_obj.today(),
'state': state,
}, context=context)
})
def button_lead(self, cursor, user, ids, context=None):
self.workflow_trigger_create(cursor, user, ids, context=context)
def button_lead(self, ids):
self.workflow_trigger_create(ids)
return True
def _get_sale_line_opportunity_line(self, cursor, user, opportunity,
context=None):
def _get_sale_line_opportunity_line(self, opportunity):
'''
Return sale line values for each opportunity line
:param cursor: the database cursor
:param user: the user id
:param opportunity: the BrowseRecord of opportunity
:param context: the context
:return: a dictionary with opportunity line id as key
and a dictionary of sale line values as value
@@ -226,19 +211,16 @@ class SaleOpportunity(ModelWorkflow, ModelSQL, ModelView):
line_obj = self.pool.get('sale.opportunity.line')
res = {}
for line in opportunity.lines:
val = line_obj.get_sale_line(cursor, user, line, context=context)
val = line_obj.get_sale_line(line)
if val:
res[line.id] = val
return res
def _get_sale_opportunity(self, cursor, user, opportunity, context=None):
def _get_sale_opportunity(self, opportunity):
'''
Return sale values for an opportunity
:param cursor: the database cursor
:param user: the user id
:param opportunity: the BrowseRecord of the opportunity
:param context: the context
:return: a dictionary with sale fields as key and sale values as value
'''
@@ -255,45 +237,35 @@ class SaleOpportunity(ModelWorkflow, ModelSQL, ModelView):
}
return res
def create_sale(self, cursor, user, opportunity_id, context=None):
def create_sale(self, opportunity_id):
'''
Create a sale for the opportunity
:param cursor: the database cursor
:param user: the user id
:param opportunity_id: the id of the opportunity
:param context: the context
'''
sale_obj = self.pool.get('sale.sale')
sale_line_obj = self.pool.get('sale.line')
line_obj = self.pool.get('sale.opportunity.line')
if context is None:
context = {}
opportunity = self.browse(opportunity_id)
opportunity = self.browse(cursor, user, opportunity_id,
context=context)
values = self._get_sale_opportunity(opportunity)
sale_line_values = self._get_sale_line_opportunity_line(opportunity)
values = self._get_sale_opportunity(cursor, user, opportunity,
context=context)
sale_line_values = self._get_sale_line_opportunity_line(cursor, user,
opportunity, context=context)
ctx = context.copy()
ctx['user'] = user
sale_id = sale_obj.create(cursor, 0, values, context=ctx)
with Transaction().set_user(0, set_context=True):
sale_id = sale_obj.create(values)
for line_id, values in sale_line_values.iteritems():
values['sale'] = sale_id
sale_line_id = sale_line_obj.create(cursor, 0, values,
context=ctx)
line_obj.write(cursor, user, line_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,
}, context=context)
})
self.write(cursor, user, opportunity_id, {
self.write(opportunity_id, {
'sale': sale_id,
}, context=context)
})
return sale_id
SaleOpportunity()
@@ -325,34 +297,30 @@ class SaleOpportunityLine(ModelSQL, ModelView):
super(SaleOpportunityLine, self).__init__()
self._order.insert(0, ('sequence', 'ASC'))
def on_change_with_unit_digits(self, cursor, user, vals, context=None):
def on_change_with_unit_digits(self, vals):
uom_obj = self.pool.get('product.uom')
if vals.get('unit'):
uom = uom_obj.browse(cursor, user, vals['unit'],
context=context)
uom = uom_obj.browse(vals['unit'])
return uom.digits
return 2
def get_unit_digits(self, cursor, user, ids, name, context=None):
def get_unit_digits(self, ids, name):
res = {}
for line in self.browse(cursor, user, ids, context=context):
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, cursor, user, vals, context=None):
def on_change_product(self, vals):
product_obj = self.pool.get('product.product')
if context is None:
context = {}
if not vals.get('product'):
return {}
res = {}
product = product_obj.browse(cursor, user, vals['product'],
context=context)
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]:
@@ -361,14 +329,11 @@ class SaleOpportunityLine(ModelSQL, ModelView):
res['unit_digits'] = product.sale_uom.digits
return res
def get_sale_line(self, cursor, user, line, context=None):
def get_sale_line(self, line):
'''
Return sale line values for opportunity line
:param cursor: the database cursor
:param user: the user id
:param line: the BrowseRecord of the line
:param context: the context
:return: a dictionary with sale line fields as key
and sale line values as value
@@ -380,13 +345,13 @@ class SaleOpportunityLine(ModelSQL, ModelView):
'unit': line.unit.id,
'product': line.product.id,
}
res.update(sale_line_obj.on_change_product(cursor, user, {
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,
}, context=context))
}))
return res
SaleOpportunityLine()
@@ -394,15 +359,13 @@ SaleOpportunityLine()
class One2ManyHistory(fields.One2Many):
def get(self, cursor, user, ids, model, name, values=None,
context=None):
def get(self, ids, model, name, values=None):
opportunity2id = {}
histories = model.browse(cursor, user, ids, context=context)
histories = model.browse(ids)
opportunity2id = dict((history.opportunity.id, history.id) for
history in histories)
res = super(One2ManyHistory, self).get(cursor, user,
opportunity2id.keys(), model, name, values=values,
context=context)
res = super(One2ManyHistory, self).get(opportunity2id.keys(), model,
name, values=values)
return dict((opportunity2id[i], j) for i, j in res.iteritems())
@@ -441,7 +404,7 @@ class SaleOpportunityHistory(ModelSQL, ModelView):
super(SaleOpportunityHistory, self).__init__()
self._order.insert(0, ('date', 'DESC'))
def _table_query_fields(self, context=None):
def _table_query_fields(self):
opportunity_obj = self.pool.get('sale.opportunity')
table = '%s__history' % opportunity_obj._table
return [
@@ -453,7 +416,7 @@ class SaleOpportunityHistory(ModelSQL, ModelView):
if name not in ('id', 'opportunity', 'date', 'user')
and not hasattr(field, 'set')]
def _table_query_group(self, context=None):
def _table_query_group(self):
opportunity_obj = self.pool.get('sale.opportunity')
table = '%s__history' % opportunity_obj._table
return [
@@ -464,18 +427,18 @@ class SaleOpportunityHistory(ModelSQL, ModelView):
if name not in ('id', 'opportunity', 'date', 'user')
and not hasattr(field, 'set')]
def table_query(self, context=None):
def table_query(self):
opportunity_obj = self.pool.get('sale.opportunity')
return (('SELECT ' + \
(', '.join(self._table_query_fields(context=context))) + \
(', '.join(self._table_query_fields())) + \
' FROM "%s__history" '
'GROUP BY ' + \
(', '.join(self._table_query_group(context=context)))) % \
(', '.join(self._table_query_group()))) % \
opportunity_obj._table, [])
def read(self, cursor, user, ids, fields_names=None, context=None):
res = super(SaleOpportunityHistory, self).read(cursor, user, ids,
fields_names=fields_names, context=context)
def read(self, ids, fields_names=None):
res = super(SaleOpportunityHistory, self).read(ids,
fields_names=fields_names)
# Remove microsecond from timestamp
for values in res:
@@ -510,24 +473,22 @@ class SaleOpportunityEmployee(ModelSQL, ModelView):
conversion_amount_rate = fields.Function(fields.Float(
'Conversion Amount Rate', help='In %'), 'get_conversion_amount_rate')
def _converted_state(self, context=None):
def _converted_state(self):
return ['converted']
def _lost_state(self, context=None):
def _lost_state(self):
return ['lost']
def table_query(self, context=None):
def table_query(self):
opportunity_obj = self.pool.get('sale.opportunity')
if context is None:
context = {}
clause = ' '
args = [True]
if context.get('start_date'):
if Transaction().context.get('start_date'):
clause += 'AND start_date >= %s '
args.append(context['start_date'])
if context.get('end_date'):
args.append(Transaction().context['start_date'])
if Transaction().context.get('end_date'):
clause += 'AND start_date <= %s '
args.append(context['end_date'])
args.append(Transaction().context['end_date'])
return ('SELECT DISTINCT(employee) AS id, '
'MAX(create_uid) AS create_uid, '
'MAX(create_date) AS create_date, '
@@ -537,44 +498,44 @@ class SaleOpportunityEmployee(ModelSQL, ModelView):
'company, '
'COUNT(1) AS number, '
'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x
for x in self._converted_state(context=context)) + ') '
for x in self._converted_state()) + ') '
'THEN 1 ELSE 0 END) AS converted, '
'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x
for x in self._lost_state(context=context)) + ') '
for x in self._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(context=context)) + ') '
for x in self._converted_state()) + ') '
'THEN amount ELSE 0 END) AS converted_amount '
'FROM "' + opportunity_obj._table + '" '
'WHERE %s ' \
+ clause + \
'GROUP BY employee, company', args)
def get_conversion_rate(self, cursor, user, ids, name, context=None):
def get_conversion_rate(self, ids, name):
res = {}
for record in self.browse(cursor, user, ids, context=context):
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_currency(self, cursor, user, ids, name, context=None):
def get_currency(self, ids, name):
res = {}
for record in self.browse(cursor, user, ids, context=context):
for record in self.browse(ids):
res[record.id] = record.company.currency.id
return res
def get_currency_digits(self, cursor, user, ids, name, context=None):
def get_currency_digits(self, ids, name):
res = {}
for record in self.browse(cursor, user, ids, context=context):
for record in self.browse(ids):
res[record.id] = record.company.currency.digits
return res
def get_conversion_amount_rate(self, cursor, user, ids, name, context=None):
def get_conversion_amount_rate(self, ids, name):
res = {}
for record in self.browse(cursor, user, ids, context=context):
for record in self.browse(ids):
if record.amount:
res[record.id] = (float(record.converted_amount) /
float(record.amount) * 100.0)
@@ -618,12 +579,12 @@ class OpenSaleOpportunityEmployee(Wizard):
},
}
def _action_open(self, cursor, user, data, context=None):
def _action_open(self, data):
model_data_obj = self.pool.get('ir.model.data')
act_window_obj = self.pool.get('ir.action.act_window')
act_window_id = model_data_obj.get_id(cursor, user, 'sale_opportunity',
'act_opportunity_employee_form', context=context)
res = act_window_obj.read(cursor, user, act_window_id, context=context)
act_window_id = model_data_obj.get_id('sale_opportunity',
'act_opportunity_employee_form')
res = act_window_obj.read(act_window_id)
res['pyson_context'] = PYSONEncoder().encode({
'start_date': data['form']['start_date'],
'end_date': data['form']['end_date'],
@@ -665,13 +626,13 @@ class SaleOpportunityMonthly(ModelSQL, ModelView):
self._order.insert(0, ('year', 'DESC'))
self._order.insert(1, ('month', 'DESC'))
def _converted_state(self, context=None):
def _converted_state(self):
return ['converted']
def _lost_state(self, context=None):
def _lost_state(self):
return ['lost']
def table_query(self, context=None):
def table_query(self):
opportunity_obj = self.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]
@@ -691,49 +652,49 @@ class SaleOpportunityMonthly(ModelSQL, ModelView):
'company, '
'COUNT(1) AS number, '
'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x
for x in self._converted_state(context=context)) + ') '
for x in self._converted_state()) + ') '
'THEN 1 ELSE 0 END) AS converted, '
'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x
for x in self._lost_state(context=context)) + ') '
for x in self._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(context=context)) + ') '
for x in self._converted_state()) + ') '
'THEN amount ELSE 0 END) AS converted_amount '
'FROM "' + opportunity_obj._table + '" '
'GROUP BY year, month, company) AS "' + self._table + '"',
[])
def get_conversion_rate(self, cursor, user, ids, name, context=None):
def get_conversion_rate(self, ids, name):
res = {}
for record in self.browse(cursor, user, ids, context=context):
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_year_month(self, cursor, user, ids, name, context=None):
def get_year_month(self, ids, name):
res = {}
for record in self.browse(cursor, user, ids, context=context):
for record in self.browse(ids):
res[record.id] = '%s-%s' % (record.year, int(record.month))
return res
def get_currency(self, cursor, user, ids, name, context=None):
def get_currency(self, ids, name):
res = {}
for record in self.browse(cursor, user, ids, context=context):
for record in self.browse(ids):
res[record.id] = record.company.currency.id
return res
def get_currency_digits(self, cursor, user, ids, name, context=None):
def get_currency_digits(self, ids, name):
res = {}
for record in self.browse(cursor, user, ids, context=context):
for record in self.browse(ids):
res[record.id] = record.company.currency.digits
return res
def get_conversion_amount_rate(self, cursor, user, ids, name, context=None):
def get_conversion_amount_rate(self, ids, name):
res = {}
for record in self.browse(cursor, user, ids, context=context):
for record in self.browse(ids):
if record.amount:
res[record.id] = (float(record.converted_amount) /
float(record.amount) * 100.0)
@@ -776,13 +737,13 @@ class SaleOpportunityEmployeeMonthly(ModelSQL, ModelView):
self._order.insert(1, ('month', 'DESC'))
self._order.insert(2, ('employee', 'ASC'))
def _converted_state(self, context=None):
def _converted_state(self):
return ['converted']
def _lost_state(self, context=None):
def _lost_state(self):
return ['lost']
def table_query(self, context=None):
def table_query(self):
opportunity_obj = self.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]
@@ -805,43 +766,43 @@ class SaleOpportunityEmployeeMonthly(ModelSQL, ModelView):
'company, '
'COUNT(1) AS number, '
'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x
for x in self._converted_state(context=context)) + ') '
for x in self._converted_state()) + ') '
'THEN 1 ELSE 0 END) AS converted, '
'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x
for x in self._lost_state(context=context)) + ') '
for x in self._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(context=context)) + ') '
for x in self._converted_state()) + ') '
'THEN amount ELSE 0 END) AS converted_amount '
'FROM "' + opportunity_obj._table + '" '
'GROUP BY year, month, employee, company) '
'AS "' + self._table + '"', [])
def get_conversion_rate(self, cursor, user, ids, name, context=None):
def get_conversion_rate(self, ids, name):
res = {}
for record in self.browse(cursor, user, ids, context=context):
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_currency(self, cursor, user, ids, name, context=None):
def get_currency(self, ids, name):
res = {}
for record in self.browse(cursor, user, ids, context=context):
for record in self.browse(ids):
res[record.id] = record.company.currency.id
return res
def get_currency_digits(self, cursor, user, ids, name, context=None):
def get_currency_digits(self, ids, name):
res = {}
for record in self.browse(cursor, user, ids, context=context):
for record in self.browse(ids):
res[record.id] = record.company.currency.digits
return res
def get_conversion_amount_rate(self, cursor, user, ids, name, context=None):
def get_conversion_amount_rate(self, ids, name):
res = {}
for record in self.browse(cursor, user, ids, context=context):
for record in self.browse(ids):
if record.amount:
res[record.id] = (float(record.converted_amount) /
float(record.amount) * 100.0)