Migration to python-sql

review1001002
This commit is contained in:
Cédric Krier committed 2013-09-06 22:34:41 +02:00
1 parent 1ad00af550
commit f16e5d5b5f
3 files changed
+130 -129

No files matched your search

+1
View File
@@ -6,6 +6,7 @@ Prerequisites
* Python 2.6 or later (http://www.python.org/)
* trytond (http://www.tryton.org/)
* python-sql (http://code.google.com/p/python-sql/)
* trytond_party (http://www.tryton.org/)
* trytond_company (http://www.tryton.org/)
* trytond_product (http://www.tryton.org/)
+128 -128
View File
@@ -3,9 +3,14 @@
"Sales extension for managing leads and opportunities"
import datetime
import time
from sql import Column, Literal
from sql.aggregate import Min, Max, Count, Sum
from sql.conditionals import Coalesce, Case
from sql.functions import Extract
from trytond.model import ModelView, ModelSQL, Workflow, fields
from trytond.wizard import Wizard, StateView, StateAction, Button
from trytond.backend import FIELDS, TableHandler
from trytond import backend
from trytond.pyson import Equal, Eval, Not, In, If, Get, PYSONEncoder
from trytond.transaction import Transaction
from trytond.pool import Pool
@@ -99,6 +104,9 @@ class SaleOpportunity(Workflow, ModelSQL, ModelView):
@classmethod
def __register__(cls, module_name):
cursor = Transaction().cursor
TableHandler = backend.get('TableHandler')
sql_table = cls.__table__()
reference_exists = True
if TableHandler.table_exist(cursor, cls._table):
table = TableHandler(cursor, cls, module_name)
@@ -110,8 +118,10 @@ class SaleOpportunity(Workflow, ModelSQL, ModelView):
# required
table.not_null_action('party', action='remove')
if not reference_exists:
cursor.execute('UPDATE "' + cls._table + '" SET reference=id WHERE '
'reference IS NULL')
cursor.execute(*sql_table.update(
columns=[sql_table.reference],
values=[sql_table.id],
where=sql_table.reference == None))
table.not_null_action('reference', action='add')
@@ -361,9 +371,7 @@ class SaleOpportunityLine(ModelSQL, ModelView):
_rec_name = "product"
_history = True
opportunity = fields.Many2One('sale.opportunity', 'Opportunity')
sequence = fields.Integer('Sequence',
order_field='(%(table)s.sequence IS NULL) %(order)s, '
'%(table)s.sequence %(order)s')
sequence = fields.Integer('Sequence')
product = fields.Many2One('product.product', 'Product', required=True,
domain=[('salable', '=', True)], on_change=['product', 'unit'])
quantity = fields.Float('Quantity', required=True,
@@ -384,6 +392,7 @@ class SaleOpportunityLine(ModelSQL, ModelView):
@classmethod
def __register__(cls, module_name):
TableHandler = backend.get('TableHandler')
cursor = Transaction().cursor
table = TableHandler(cursor, cls, module_name)
@@ -392,6 +401,11 @@ class SaleOpportunityLine(ModelSQL, ModelView):
# Migration from 2.4: drop required on sequence
table.not_null_action('sequence', action='remove')
@staticmethod
def order_sequence(tables):
table, _ = tables[None]
return [table.sequence == None, table.sequence]
def on_change_with_unit_digits(self, name=None):
if self.unit:
return self.unit.digits
@@ -462,41 +476,35 @@ class SaleOpportunityHistory(ModelSQL, ModelView):
super(SaleOpportunityHistory, cls).__setup__()
cls._order.insert(0, ('date', 'DESC'))
@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,
('MIN(COALESCE("%s".write_date, "%s".create_date)) AS date'
% (table, table)),
('COALESCE("%s".write_uid, "%s".create_uid) AS user'
% (table, table)),
] + ['"%s"."%s"' % (table, name)
for name, field in cls._fields.iteritems()
if name not in ('id', 'opportunity', 'date', 'user')
and not hasattr(field, 'set')]
@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 cls._fields.iteritems()
if (name not in ('id', 'opportunity', 'date', 'user')
and not hasattr(field, 'set'))]
@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, [])
opportunity_history = Opportunity.__table_history__()
columns = [
Min(Column(opportunity_history, '__id')).as_('id'),
opportunity_history.id.as_('opportunity'),
Min(Coalesce(opportunity_history.write_date,
opportunity_history.create_date)).as_('date'),
Coalesce(opportunity_history.write_uid,
opportunity_history.create_uid).as_('user'),
]
group_by = [
opportunity_history.id,
Coalesce(opportunity_history.write_uid,
opportunity_history.create_uid),
]
for name, field in cls._fields.iteritems():
if name in ('id', 'opportunity', 'date', 'user'):
continue
try:
field.sql_type()
except NotImplementedError:
continue
column = Column(opportunity_history, name)
columns.append(column.as_(name))
group_by.append(column)
return opportunity_history.select(*columns, group_by=group_by)
def get_lines(self, name):
Line = Pool().get('sale.opportunity.line')
@@ -555,35 +563,33 @@ class SaleOpportunityEmployee(ModelSQL, ModelView):
@classmethod
def table_query(cls):
Opportunity = Pool().get('sale.opportunity')
clause = ' '
args = [True]
opportunity = Opportunity.__table__()
where = Literal(True)
if Transaction().context.get('start_date'):
clause += 'AND start_date >= %s '
args.append(Transaction().context['start_date'])
where &= (opportunity.start_date >=
Transaction().context['start_date'])
if Transaction().context.get('end_date'):
clause += 'AND start_date <= %s '
args.append(Transaction().context['end_date'])
return ('SELECT DISTINCT(employee) AS id, '
'MAX(create_uid) AS create_uid, '
'MAX(create_date) AS create_date, '
'MAX(write_uid) AS write_uid, '
'MAX(write_date) AS write_date, '
'employee, '
'company, '
'COUNT(1) AS number, '
'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x
for x in cls._converted_state()) + ') '
'THEN 1 ELSE 0 END) AS converted, '
'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x
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 cls._converted_state()) + ') '
'THEN amount ELSE 0 END) AS converted_amount '
'FROM "' + Opportunity._table + '" '
'WHERE %s ' + clause +
'GROUP BY employee, company', args)
where &= (opportunity.start_date <=
Transaction().context['end_date'])
return opportunity.select(
opportunity.employee.as_('id'),
Max(opportunity.create_uid).as_('create_uid'),
Max(opportunity.create_date).as_('create_date'),
Max(opportunity.write_uid).as_('write_uid'),
Max(opportunity.write_date).as_('write_date'),
opportunity.employee,
opportunity.company,
Count(Literal(1)).as_('number'),
Sum(Case((opportunity.state.in_(cls._converted_state()),
Literal(1)), else_=Literal(0))).as_('converted'),
Sum(Case((opportunity.state.in_(cls._lost_state()),
Literal(1)), else_=Literal(0))).as_('lost'),
Sum(opportunity.amount).as_('amount'),
Sum(Case((opportunity.state.in_(cls._converted_state()),
opportunity.amount),
else_=Literal(0))).as_('converted_amount'),
where=where,
group_by=(opportunity.employee, opportunity.company))
def get_conversion_rate(self, name):
if self.number:
@@ -671,36 +677,33 @@ class SaleOpportunityMonthly(ModelSQL, ModelView):
@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, '
'number, converted, lost, amount, converted_amount '
'FROM ('
'SELECT EXTRACT(MONTH FROM start_date) + '
'EXTRACT(YEAR FROM start_date) * 100 AS id, '
'MAX(create_uid) AS create_uid, '
'MAX(create_date) AS create_date, '
'MAX(write_uid) AS write_uid, '
'MAX(write_date) AS write_date, '
'EXTRACT(YEAR FROM start_date) AS year, '
'EXTRACT(MONTH FROM start_date) AS month, '
'company, '
'COUNT(1) AS number, '
'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x
for x in cls._converted_state()) + ') '
'THEN 1 ELSE 0 END) AS converted, '
'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x
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 cls._converted_state()) + ') '
'THEN amount ELSE 0 END) AS converted_amount '
'FROM "' + Opportunity._table + '" '
'GROUP BY year, month, company) AS "' + cls._table + '"',
[])
opportunity = Opportunity.__table__()
type_id = cls.id.sql_type().base
type_year = cls.year.sql_type().base
year_column = Extract('YEAR', opportunity.start_date
).cast(type_year).as_('year')
month_column = Extract('MONTH', opportunity.start_date).as_('month')
return opportunity.select(
Max(Extract('MONTH', opportunity.start_date)
+ Extract('YEAR', opportunity.start_date) * 100
).cast(type_id).as_('id'),
Max(opportunity.create_uid).as_('create_uid'),
Max(opportunity.create_date).as_('create_date'),
Max(opportunity.write_uid).as_('write_uid'),
Max(opportunity.write_date).as_('write_date'),
year_column,
month_column,
opportunity.company,
Count(Literal(1)).as_('number'),
Sum(Case((opportunity.state.in_(cls._converted_state()),
Literal(1)), else_=Literal(0))).as_('converted'),
Sum(Case((opportunity.state.in_(cls._lost_state()),
Literal(1)), else_=Literal(0))).as_('lost'),
Sum(opportunity.amount).as_('amount'),
Sum(Case((opportunity.state.in_(cls._converted_state()),
opportunity.amount),
else_=Literal(0))).as_('converted_amount'),
group_by=(year_column, month_column, opportunity.company))
def get_conversion_rate(self, name):
if self.number:
@@ -766,39 +769,36 @@ class SaleOpportunityEmployeeMonthly(ModelSQL, ModelView):
@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, '
'employee, company, number, converted, lost, amount, '
'converted_amount '
'FROM ('
'SELECT EXTRACT(MONTH FROM start_date) + '
'EXTRACT(YEAR FROM start_date) * 100 + '
'employee * 1000000 AS id, '
'MAX(create_uid) AS create_uid, '
'MAX(create_date) AS create_date, '
'MAX(write_uid) AS write_uid, '
'MAX(write_date) AS write_date, '
'EXTRACT(YEAR FROM start_date) AS year, '
'EXTRACT(MONTH FROM start_date) AS month, '
'employee, '
'company, '
'COUNT(1) AS number, '
'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x
for x in cls._converted_state()) + ') '
'THEN 1 ELSE 0 END) AS converted, '
'SUM(CASE WHEN state IN (' + ','.join("'%s'" % x
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 cls._converted_state()) + ') '
'THEN amount ELSE 0 END) AS converted_amount '
'FROM "' + Opportunity._table + '" '
'GROUP BY year, month, employee, company) '
'AS "' + cls._table + '"', [])
opportunity = Opportunity.__table__()
type_id = cls.id.sql_type().base
type_year = cls.year.sql_type().base
year_column = Extract('YEAR', opportunity.start_date
).cast(type_year).as_('year')
month_column = Extract('MONTH', opportunity.start_date).as_('month')
return opportunity.select(
Max(Extract('MONTH', opportunity.start_date)
+ Extract('YEAR', opportunity.start_date) * 100
+ opportunity.employee * 1000000
).cast(type_id).as_('id'),
Max(opportunity.create_uid).as_('create_uid'),
Max(opportunity.create_date).as_('create_date'),
Max(opportunity.write_uid).as_('write_uid'),
Max(opportunity.write_date).as_('write_date'),
year_column,
month_column,
opportunity.employee,
opportunity.company,
Count(Literal(1)).as_('number'),
Sum(Case((opportunity.state.in_(cls._converted_state()),
Literal(1)), else_=Literal(0))).as_('converted'),
Sum(Case((opportunity.state.in_(cls._lost_state()),
Literal(1)), else_=Literal(0))).as_('lost'),
Sum(opportunity.amount).as_('amount'),
Sum(Case((opportunity.state.in_(cls._converted_state()),
opportunity.amount),
else_=Literal(0))).as_('converted_amount'),
group_by=(year_column, month_column, opportunity.employee,
opportunity.company))
def get_conversion_rate(self, name):
if self.number:
+1 -1
View File
@@ -21,7 +21,7 @@ major_version, minor_version, _ = info.get('version', '0.0.1').split('.', 2)
major_version = int(major_version)
minor_version = int(minor_version)
requires = []
requires = ['python-sql']
for dep in info.get('depends', []):
if not re.match(r'(ir|res|webdav)(\W|$)', dep):
requires.append('trytond_%s >= %s.%s, < %s.%s' %