From 3c4a07146bfcb462ff9e4d2e1211438542a0ff03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 6 Sep 2013 22:34:40 +0200 Subject: [PATCH] Migration to python-sql review1001002 --- INSTALL | 1 + invoice.py | 34 +++++++---- sale.py | 132 ++++++++++++++++++++++++++-------------- setup.py | 2 +- tests/scenario_sale.rst | 2 +- view/sale_tree.xml | 1 - 6 files changed, 111 insertions(+), 61 deletions(-) diff --git a/INSTALL b/INSTALL index aac074e541..aba12d07f3 100644 --- a/INSTALL +++ b/INSTALL @@ -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_company (http://www.tryton.org/) * trytond_party (http://www.tryton.org/) * trytond_stock (http://www.tryton.org/) diff --git a/invoice.py b/invoice.py index b9ed091357..2449d65950 100644 --- a/invoice.py +++ b/invoice.py @@ -1,11 +1,12 @@ #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 functools import wraps +from sql import Table from trytond.model import Workflow, fields from trytond.pool import Pool, PoolMeta from trytond.transaction import Transaction -from trytond.backend import TableHandler +from trytond import backend __all__ = ['Invoice', 'InvoiceLine'] __metaclass__ = PoolMeta @@ -73,11 +74,15 @@ class Invoice: @classmethod def delete(cls, invoices): + pool = Pool() + Sale_Invoice = pool.get('sale.sale-account.invoice') + sale_invoice = Sale_Invoice.__table__() + cursor = Transaction().cursor if invoices: - Transaction().cursor.execute('SELECT id FROM sale_invoices_rel ' - 'WHERE invoice IN (' + ','.join(('%s',) * len(invoices)) + ')', - [i.id for i in invoices]) - if Transaction().cursor.fetchone(): + cursor.execute(*sale_invoice.select(sale_invoice.id, + where=sale_invoice.invoice.in_( + [i.id for i in invoices]))) + if cursor.fetchone(): cls.raise_user_error('delete_sale_invoice') super(Invoice, cls).delete(invoices) @@ -115,20 +120,23 @@ class InvoiceLine: @classmethod def __register__(cls, module_name): + TableHandler = backend.get('TableHandler') cursor = Transaction().cursor + sql_table = cls.__table__() super(InvoiceLine, cls).__register__(module_name) # Migration from 2.6: remove sale_lines - rel_table = 'sale_line_invoice_lines_rel' - if TableHandler.table_exist(cursor, rel_table): - cursor.execute('SELECT sale_line, invoice_line ' - 'FROM "' + rel_table + '"') + rel_table_name = 'sale_line_invoice_lines_rel' + if TableHandler.table_exist(cursor, rel_table_name): + rel_table = Table(rel_table_name) + cursor.execute(*rel_table.select( + rel_table.sale_line, rel_table.invoice_line)) for sale_line, invoice_line in cursor.fetchall(): - cursor.execute('UPDATE "' + cls._table + '" ' - 'SET origin = %s ' - 'WHERE id = %s', - ('sale.line,%s' % sale_line, invoice_line)) + cursor.execute(*sql_table.update( + columns=[sql_table.origin], + values=['sale.line,%s' % sale_line], + where=sql_table.id == invoice_line)) TableHandler.drop_table(cursor, 'sale.line-account.invoice.line', rel_table) diff --git a/sale.py b/sale.py index 51e40561c2..158f9f6eb8 100644 --- a/sale.py +++ b/sale.py @@ -4,11 +4,16 @@ from decimal import Decimal import datetime from itertools import groupby, chain from functools import partial +from sql import Table, Literal +from sql.functions import Overlay, Position +from sql.aggregate import Count +from sql.operators import Concat + from trytond.model import Workflow, ModelView, ModelSQL, fields from trytond.modules.company import CompanyReport from trytond.wizard import Wizard, StateAction, StateView, StateTransition, \ Button -from trytond.backend import TableHandler +from trytond import backend from trytond.pyson import If, Eval, Bool, PYSONEncoder, Id from trytond.transaction import Transaction from trytond.pool import Pool, PoolMeta @@ -229,20 +234,36 @@ class Sale(Workflow, ModelSQL, ModelView): def __register__(cls, module_name): pool = Pool() SaleLine = pool.get('sale.line') - sale_line_invoice_line_table = 'sale_line_invoice_lines_rel' + TableHandler = backend.get('TableHandler') + sale_line_invoice_line_table_name = 'sale_line_invoice_lines_rel' Move = pool.get('stock.move') cursor = Transaction().cursor + model_data = Table('ir_model_data') + model_field = Table('ir_model_field') + sql_table = cls.__table__() + # Migration from 1.2: packing renamed into shipment - cursor.execute("UPDATE ir_model_data " - "SET fs_id = REPLACE(fs_id, 'packing', 'shipment') " - "WHERE fs_id like '%%packing%%' AND module = %s", - (module_name,)) - cursor.execute("UPDATE ir_model_field " - "SET relation = REPLACE(relation, 'packing', 'shipment'), " - "name = REPLACE(name, 'packing', 'shipment') " - "WHERE (relation like '%%packing%%' " - "OR name like '%%packing%%') AND module = %s", - (module_name,)) + cursor.execute(*model_data.update( + columns=[model_data.fs_id], + values=[Overlay(model_data.fs_id, 'shipment', + Position('packing', model_data.fs_id), + len('packing'))], + where=model_data.fs_id.like('%packing%') + & (model_data.module == module_name))) + cursor.execute(*model_field.update( + columns=[model_field.relation], + values=[Overlay(model_field.relation, 'shipment', + Position('packing', model_field.relation), + len('packing'))], + where=model_field.relation.like('%packing%') + & (model_field.module == module_name))) + cursor.execute(*model_field.update( + columns=[model_field.name], + values=[Overlay(model_field.name, 'shipment', + Position('packing', model_field.name), + len('packing'))], + where=model_field.name.like('%packing%') + & (model_field.module == module_name))) table = TableHandler(cursor, cls, module_name) table.column_rename('packing_state', 'shipment_state') table.column_rename('packing_method', 'shipment_method') @@ -251,9 +272,10 @@ class Sale(Workflow, ModelSQL, ModelView): super(Sale, cls).__register__(module_name) # Migration from 1.2 - cursor.execute("UPDATE " + cls._table + " " - "SET invoice_method = 'shipment' " - "WHERE invoice_method = 'packing'") + cursor.execute(*sql_table.update( + columns=[sql_table.invoice_method], + values=['shipment'], + where=sql_table.invoice_method == 'packing')) table = TableHandler(cursor, cls, module_name) # Migration from 2.2 @@ -262,27 +284,30 @@ class Sale(Workflow, ModelSQL, ModelView): # state confirmed splitted into confirmed and processing if (TableHandler.table_exist(cursor, SaleLine._table) and TableHandler.table_exist(cursor, - sale_line_invoice_line_table) + sale_line_invoice_line_table_name) and TableHandler.table_exist(cursor, Move._table)): + sale_line = SaleLine.__table__() + sale_line_invoice_line = \ + Table(sale_line_invoice_line_table_name) + move = Move.__table__() # Wrap subquery inside an other inner subquery because MySQL syntax # doesn't allow update a table and select from the same table in a # subquery. - cursor.execute('UPDATE "%s" ' - "SET state = 'processing' " - 'WHERE id IN (' - 'SELECT id ' - 'FROM (' - 'SELECT s.id ' - 'FROM "%s" AS s ' - 'INNER JOIN "%s" AS l ON l.sale = s.id ' - 'LEFT JOIN "%s" AS li ON li.sale_line = l.id ' - 'LEFT JOIN "%s" AS m ON m.origin = \'%s,\' || l.id ' - "WHERE s.state = 'confirmed' " - 'AND (li.id IS NOT NULL ' - 'OR m.id IS NOT NULL)) AS foo)' - % (cls._table, cls._table, SaleLine._table, - sale_line_invoice_line_table, Move._table, - SaleLine.__name__)) + sub_query = sql_table.join(sale_line, + condition=sale_line.sale == sql_table.id + ).join(sale_line_invoice_line, 'LEFT', + condition=sale_line_invoice_line.sale_line == sale_line.id + ).join(move, 'LEFT', + condition=(move.origin == Concat(SaleLine.__name__, + sale_line.id)) + ).select(sql_table.id, + where=(sql_table.state == 'confirmed') + & ((sale_line_invoice_line.id != None) + | (move.id != None))) + cursor.execute(*sql_table.update( + columns=[sql_table.state], + values=['processing'], + where=sql_table.id.in_(sub_query.select(sub_query.id)))) # Add index on create_date table = TableHandler(cursor, cls, module_name) @@ -891,9 +916,7 @@ class SaleLine(ModelSQL, ModelView): _rec_name = 'description' sale = fields.Many2One('sale.sale', 'Sale', ondelete='CASCADE', select=True) - sequence = fields.Integer('Sequence', - order_field='(%(table)s.sequence IS NULL) %(order)s, ' - '%(table)s.sequence %(order)s') + sequence = fields.Integer('Sequence') type = fields.Selection([ ('line', 'Line'), ('subtotal', 'Subtotal'), @@ -1009,18 +1032,27 @@ class SaleLine(ModelSQL, ModelView): @classmethod def __register__(cls, module_name): - super(SaleLine, cls).__register__(module_name) + TableHandler = backend.get('TableHandler') cursor = Transaction().cursor + sql_table = cls.__table__() + super(SaleLine, cls).__register__(module_name) table = TableHandler(cursor, cls, module_name) # Migration from 1.0 comment change into note if table.column_exist('comment'): - cursor.execute('UPDATE "' + cls._table + '" SET note = comment') + cursor.execute(*sql_table.update( + columns=[sql_table.note], + values=[sql_table.comment])) table.drop_column('comment', exception=True) # 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] + @staticmethod def default_type(): return 'line' @@ -1600,7 +1632,9 @@ class Move: @classmethod def __register__(cls, module_name): + TableHandler = backend.get('TableHandler') cursor = Transaction().cursor + sql_table = cls.__table__() super(Move, cls).__register__(module_name) @@ -1608,9 +1642,10 @@ class Move: # Migration from 2.6: remove sale_line if table.column_exist('sale_line'): - cursor.execute('UPDATE "' + cls._table + '" ' - 'SET origin = \'sale.line,\' || sale_line ' - 'WHERE sale_line IS NOT NULL') + cursor.execute(*sql_table.update( + columns=[sql_table.origin], + values=[Concat('sale.line,', sql_table.sale_line)], + where=sql_table.sale_line != None)) table.drop_column('sale_line') @classmethod @@ -1686,8 +1721,11 @@ class OpenCustomer(Wizard): pool = Pool() ModelData = pool.get('ir.model.data') Wizard = pool.get('ir.action.wizard') + Sale = pool.get('sale.sale') cursor = Transaction().cursor - cursor.execute("SELECT DISTINCT(party) FROM sale_sale") + sale = Sale.__table__() + + cursor.execute(*sale.select(sale.party, group_by=sale.party)) customer_ids = [line[0] for line in Transaction().cursor.fetchall()] action['pyson_domain'] = PYSONEncoder().encode( [('id', 'in', customer_ids)]) @@ -1717,11 +1755,15 @@ class HandleShipmentExceptionAsk(ModelView): @classmethod def __register__(cls, module_name): cursor = Transaction().cursor + model = Table('ir_model') # Migration from 1.2: packing renamed into shipment - cursor.execute("UPDATE ir_model " - "SET model = REPLACE(model, 'packing', 'shipment') " - "WHERE model like '%%packing%%' AND module = %s", - (module_name,)) + cursor.execute(*model.update( + columns=[model.model], + values=[Overlay(model.model, 'shipment', + Position('packing', model.model), + len('packing'))], + where=model.model.like('%packing%') + & (model.module == module_name))) super(HandleShipmentExceptionAsk, cls).__register__(module_name) diff --git a/setup.py b/setup.py index 45016512a4..990a563caa 100644 --- a/setup.py +++ b/setup.py @@ -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' % diff --git a/tests/scenario_sale.rst b/tests/scenario_sale.rst index 374a44621f..8a517cf926 100644 --- a/tests/scenario_sale.rst +++ b/tests/scenario_sale.rst @@ -112,7 +112,7 @@ Create chart of accounts:: >>> AccountTemplate = Model.get('account.account.template') >>> Account = Model.get('account.account') - >>> account_template, = AccountTemplate.find([('parent', '=', False)]) + >>> account_template, = AccountTemplate.find([('parent', '=', None)]) >>> create_chart = Wizard('account.create_chart') >>> create_chart.execute('account') >>> create_chart.form.account_template = account_template diff --git a/view/sale_tree.xml b/view/sale_tree.xml index 8be9f5cb8d..abdf83c6d6 100644 --- a/view/sale_tree.xml +++ b/view/sale_tree.xml @@ -14,5 +14,4 @@ this repository contains the full copyright notices and license terms. --> -