update the branch with stable addons.
[odoo/odoo.git] / addons / purchase / wizard / wizard_group.py
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
6 #    $Id$
7 #
8 #    This program is free software: you can redistribute it and/or modify
9 #    it under the terms of the GNU General Public License as published by
10 #    the Free Software Foundation, either version 3 of the License, or
11 #    (at your option) any later version.
12 #
13 #    This program is distributed in the hope that it will be useful,
14 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 #    GNU General Public License for more details.
17 #
18 #    You should have received a copy of the GNU General Public License
19 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21 ##############################################################################
22
23 import time
24
25 import wizard
26 import netsvc
27 import pooler
28 from osv.orm import browse_record, browse_null
29
30 merge_form = """<?xml version="1.0"?>
31 <form string="Merge orders">
32     <separator string="Are you sure you want to merge these orders ?"/>
33     <newline/>
34     <label string="Please note that orders will only be merged if they are to the same partner and going to the same location, and lines will only be merged if they are exactly the same except for the quantity and unit."/>
35 </form>
36 """
37
38 merge_fields = {
39 }
40
41 ack_form = """<?xml version="1.0"?>
42 <form string="Merge orders">
43     <separator string="Orders merged"/>
44 </form>"""
45
46 ack_fields = {}
47
48
49 def _merge_orders(self, cr, uid, data, context):
50     order_obj = pooler.get_pool(cr.dbname).get('purchase.order')
51
52     def make_key(br, fields):
53         list_key = []
54         for field in fields:
55             field_val = getattr(br, field)
56             if field in ('product_id', 'move_dest_id', 'account_analytic_id'):
57                 if not field_val:
58                     field_val = False
59             if isinstance(field_val, browse_record):
60                 field_val = field_val.id
61             elif isinstance(field_val, browse_null):
62                 field_val = False
63             elif isinstance(field_val, list):
64                 field_val = ((6, 0, tuple([v.id for v in field_val])),)
65             list_key.append((field, field_val))
66         list_key.sort()
67         return tuple(list_key)
68
69     # compute what the new orders should contain
70     new_orders = {}
71     for porder in [order for order in order_obj.browse(cr, uid, data['ids']) if order.state == 'draft']:
72         order_key = make_key(porder, ('partner_id', 'location_id'))
73
74         new_order = new_orders.setdefault(order_key, ({}, []))
75         new_order[1].append(porder.id)
76         order_infos = new_order[0]
77         if not order_infos:
78             order_infos.update({
79                 'origin': porder.origin,
80                 'date_order': time.strftime('%Y-%m-%d'),
81                 'partner_id': porder.partner_id.id,
82                 'partner_address_id': porder.partner_address_id.id,
83                 'dest_address_id': porder.dest_address_id.id,
84                 'warehouse_id': porder.warehouse_id.id,
85                 'location_id': porder.location_id.id,
86                 'pricelist_id': porder.pricelist_id.id,
87                 'state': 'draft',
88                 'order_line': {},
89                 'notes': '%s' % (porder.notes or '',),
90             })
91         else:
92             #order_infos['name'] += ', %s' % porder.name
93             if porder.notes:
94                 order_infos['notes'] += ('\n%s' % (porder.notes,))
95             if porder.origin:
96                 order_infos['origin'] = order_infos['origin'] + ' ' + porder.origin
97
98         for order_line in porder.order_line:
99             line_key = make_key(order_line, ('name', 'date_planned', 'taxes_id', 'price_unit', 'notes', 'product_id', 'move_dest_id', 'account_analytic_id'))
100             o_line = order_infos['order_line'].setdefault(line_key, {})
101             if o_line:
102                 # merge the line with an existing line
103                 o_line['product_qty'] += order_line.product_qty * order_line.product_uom.factor / o_line['uom_factor']
104             else:
105                 # append a new "standalone" line
106                 for field in ('product_qty', 'product_uom'):
107                     field_val = getattr(order_line, field)
108                     if isinstance(field_val, browse_record):
109                         field_val = field_val.id
110                     o_line[field] = field_val
111                 o_line['uom_factor'] = order_line.product_uom and order_line.product_uom.factor or 1.0
112
113     wf_service = netsvc.LocalService("workflow")
114
115     allorders = []
116     for order_key, (order_data, old_ids) in new_orders.iteritems():
117         # skip merges with only one order
118         if len(old_ids) < 2:
119             allorders += (old_ids or [])
120             continue
121
122         # cleanup order line data
123         for key, value in order_data['order_line'].iteritems():
124             del value['uom_factor']
125             value.update(dict(key))
126         order_data['order_line'] = [(0, 0, value) for value in order_data['order_line'].itervalues()]
127
128         # create the new order
129         neworder_id = order_obj.create(cr, uid, order_data)
130         allorders.append(neworder_id)
131
132         # make triggers pointing to the old orders point to the new order
133         for old_id in old_ids:
134             wf_service.trg_redirect(uid, 'purchase.order', old_id, neworder_id, cr)
135             wf_service.trg_validate(uid, 'purchase.order', old_id, 'purchase_cancel', cr)
136
137     return {
138         'domain': "[('id','in', [" + ','.join(map(str, allorders)) + "])]",
139         'name': 'Purchase Orders',
140         'view_type': 'form',
141         'view_mode': 'tree,form',
142         'res_model': 'purchase.order',
143         'view_id': False,
144         'type': 'ir.actions.act_window'
145     }
146
147
148 class merge_orders(wizard.interface):
149     states = {
150         'init': {
151             'actions': [],
152             'result': {'type': 'form', 'arch' : merge_form, 'fields' : merge_fields, 'state' : [('end', 'Cancel'), ('merge', 'Merge orders') ]}
153         },
154         'merge': {
155             'actions': [],
156             'result': {'type': 'action', 'action': _merge_orders, 'state': 'end'}
157         },
158     }
159
160 merge_orders("purchase.order.merge")
161