~s-chazallet/sale-wkfl/7.0

« back to all changes in this revision

Viewing changes to sale_delivery_term/sale.py

  • Committer: Alexandre Fayolle
  • Author(s): lorenzo.battistini at agilebg
  • Date: 2013-03-18 11:27:13 UTC
  • mfrom: (9.1.13 adding_sale_delivery_term_7)
  • Revision ID: alexandre.fayolle@camptocamp.com-20130318112713-cnvkpv6ls5c7w31r
[MRG] add sale_multi_picking and sale_delivery_term addons

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
##############################################################################
 
3
#    
 
4
#    Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
 
5
#    Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
 
6
#
 
7
#    This program is free software: you can redistribute it and/or modify
 
8
#    it under the terms of the GNU Affero General Public License as published
 
9
#    by the Free Software Foundation, either version 3 of the License, or
 
10
#    (at your option) any later version.
 
11
#
 
12
#    This program is distributed in the hope that it will be useful,
 
13
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
#    GNU General Public License for more details.
 
16
#
 
17
#    You should have received a copy of the GNU Affero General Public License
 
18
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
#
 
20
##############################################################################
 
21
 
 
22
from openerp.osv import fields, orm
 
23
from openerp.tools.translate import _
 
24
import openerp.addons.decimal_precision as dp
 
25
 
 
26
class sale_delivery_term(orm.Model):
 
27
    _name = 'sale.delivery.term'
 
28
    _columns = {
 
29
        'name': fields.char('Name', size=64, required=True),
 
30
        'line_ids': fields.one2many('sale.delivery.term.line', 'term_id', 'Lines', required=True),
 
31
        'company_id': fields.many2one('res.company','Company',required=True,select=1),
 
32
        }
 
33
    _defaults = {
 
34
        'company_id': lambda self,cr,uid,c: self.pool.get(
 
35
            'res.company')._company_default_get(cr, uid, 'sale.delivery.term', context=c),
 
36
    }
 
37
    
 
38
    def is_total_percentage_correct(self, cr, uid, term_ids, context=None):
 
39
        for term in self.browse(cr, uid, term_ids, context=context):
 
40
            total = 0.0
 
41
            for line in term.line_ids:
 
42
                total += line.quantity_perc
 
43
            if total != 1 :
 
44
                return False
 
45
        return True
 
46
 
 
47
class sale_delivery_term_line(orm.Model):
 
48
 
 
49
    _name = 'sale.delivery.term.line'
 
50
    _rec_name = 'term_id'
 
51
    _columns = {
 
52
        'term_id': fields.many2one('sale.delivery.term', 'Term'),
 
53
        'quantity_perc': fields.float('Quantity percentage', required=True, help="For 20% set '0.2'"),
 
54
        'delay': fields.float('Delivery Lead Time', required=True,
 
55
            help="Number of days between the order confirmation and the shipping of the products to the customer"),
 
56
        }
 
57
 
 
58
class sale_order_line_master(orm.Model):
 
59
    
 
60
    def _clean_on_change_dict(self, res_dict):
 
61
        if res_dict['value'].has_key('delay'):
 
62
            del res_dict['value']['delay']
 
63
        if res_dict['value'].has_key('th_weight'):
 
64
            del res_dict['value']['th_weight']
 
65
        if res_dict['value'].has_key('type'):
 
66
            del res_dict['value']['type']
 
67
        if res_dict['value'].has_key('tax_id'):
 
68
            del res_dict['value']['tax_id']
 
69
        return res_dict
 
70
    
 
71
    def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
 
72
        uom=False, qty_uos=0, uos=False, name='', partner_id=False,
 
73
        lang=False, update_tax=True, date_order=False, packaging=False,
 
74
        fiscal_position=False, flag=False, context=None):
 
75
        res = self.pool.get('sale.order.line').product_id_change(cr, uid, ids, pricelist, product, qty=qty,
 
76
            uom=uom, qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id,
 
77
            lang=lang, update_tax=update_tax, date_order=date_order,
 
78
            packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context)
 
79
        return self._clean_on_change_dict(res)
 
80
        
 
81
    def product_uom_change(self, cursor, user, ids, pricelist, product, qty=0,
 
82
            uom=False, qty_uos=0, uos=False, name='', partner_id=False,
 
83
            lang=False, update_tax=True, date_order=False, context=None):
 
84
        res = self.pool.get('sale.order.line').product_uom_change(cursor, user, ids, pricelist, product, qty=qty,
 
85
            uom=uom, qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id,
 
86
            lang=lang, update_tax=update_tax, date_order=date_order, context=context)
 
87
        return self._clean_on_change_dict(res)
 
88
    
 
89
    def product_packaging_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False,
 
90
                                   partner_id=False, packaging=False, flag=False, context=None):
 
91
        return self.pool.get('sale.order.line').product_packaging_change(
 
92
            cr, uid, ids, pricelist, product, qty=qty, uom=uom,
 
93
            partner_id=partner_id, packaging=packaging, flag=flag, context=context)
 
94
 
 
95
    def _amount_line(self, cr, uid, ids, field_name, arg, context=None):
 
96
        tax_obj = self.pool.get('account.tax')
 
97
        cur_obj = self.pool.get('res.currency')
 
98
        res = {}
 
99
        if context is None:
 
100
            context = {}
 
101
        for line in self.browse(cr, uid, ids, context=context):
 
102
            price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
 
103
            taxes = tax_obj.compute_all(cr, uid, line.tax_ids, price,
 
104
                line.product_uom_qty, line.order_id.partner_invoice_id.id,
 
105
                line.product_id, line.order_id.partner_id)
 
106
            cur = line.order_id.pricelist_id.currency_id
 
107
            res[line.id] = cur_obj.round(cr, uid, cur, taxes['total'])
 
108
        return res
 
109
        
 
110
    def _get_uom_id(self, cr, uid, *args):
 
111
        return self.pool.get('sale.order.line')._get_uom_id(cr, uid, args)
 
112
        
 
113
    _name = 'sale.order.line.master'
 
114
    _columns = {
 
115
        'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade'),
 
116
        'delivery_term_id': fields.many2one('sale.delivery.term', 'Delivery term', required=True),
 
117
        'name': fields.char('Description', size=256, required=True),
 
118
        'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)]),
 
119
        'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Sale Price')),
 
120
        'price_subtotal': fields.function(_amount_line, string='Subtotal',
 
121
            digits_compute= dp.get_precision('Sale Price')),
 
122
        'product_uom_qty': fields.float('Quantity (UoM)', digits_compute= dp.get_precision('Product UoS'), required=True),
 
123
        'product_uom': fields.many2one('product.uom', 'Unit of Measure ', required=True),
 
124
        'product_uos_qty': fields.float('Quantity (UoS)' ,digits_compute= dp.get_precision('Product UoS')),
 
125
        'product_uos': fields.many2one('product.uom', 'Product UoS'),
 
126
        'product_packaging': fields.many2one('product.packaging', 'Packaging'),
 
127
        'order_line_ids': fields.one2many('sale.order.line', 'master_line_id', 'Detailed lines'),
 
128
        'discount': fields.float('Discount (%)', digits=(16, 2)),
 
129
        'tax_ids': fields.many2many('account.tax', 'sale_master_order_line_tax', 'order_line_id', 'tax_id', 'Taxes'),
 
130
        }
 
131
    _defaults = {
 
132
        'product_uom' : _get_uom_id,
 
133
        'product_uom_qty': 1,
 
134
        'product_uos_qty': 1,
 
135
        'product_packaging': False,
 
136
        'price_unit': 0.0,
 
137
    }
 
138
        
 
139
    def _prepare_order_line(self, cr, uid, term_line, master_line, group_index=0, context=None):
 
140
        order_line_pool = self.pool.get('sale.order.line')
 
141
        group_pool = self.pool.get('sale.order.line.group')
 
142
        group_ids = group_pool.search(cr, uid, [])
 
143
        product_uom_qty = master_line.product_uom_qty * term_line.quantity_perc
 
144
        product_uos_qty = master_line.product_uos_qty * term_line.quantity_perc
 
145
        order_line_vals = {}
 
146
        on_change_res = order_line_pool.product_id_change(cr, uid, [], master_line.order_id.pricelist_id.id,
 
147
            master_line.product_id.id, qty=product_uom_qty,
 
148
            uom=master_line.product_uom.id, qty_uos=product_uos_qty,
 
149
            uos=master_line.product_uos.id, name=master_line.name, partner_id=master_line.order_id.partner_id.id,
 
150
            lang=False, update_tax=True, date_order=master_line.order_id.date_order,
 
151
            packaging=master_line.product_packaging.id, fiscal_position=master_line.order_id.fiscal_position.id,
 
152
            flag=False, context=context)
 
153
        order_line_vals.update(on_change_res['value'])
 
154
        order_line_vals.update({
 
155
            'order_id': master_line.order_id.id,
 
156
            'name': master_line.name,
 
157
            'price_unit': master_line.price_unit,
 
158
            'product_uom_qty': product_uom_qty,
 
159
            'product_uom': master_line.product_uom.id,
 
160
            'product_id': master_line.product_id and master_line.product_id.id or False,
 
161
            'product_uos_qty': product_uos_qty,
 
162
            'product_uos': master_line.product_uos and master_line.product_uos.id or False,
 
163
            'product_packaging': master_line.product_packaging.id,
 
164
            'master_line_id': master_line.id,
 
165
            'delay': term_line.delay,
 
166
            'picking_group_id': group_ids[group_index],
 
167
            'tax_id': [(6,0, [tax.id for tax in master_line.tax_ids])],
 
168
            })
 
169
        return order_line_vals
 
170
        
 
171
        
 
172
    def generate_detailed_lines(self, cr, uid, ids, context=None):
 
173
        group_pool = self.pool.get('sale.order.line.group')
 
174
        order_line_pool = self.pool.get('sale.order.line')
 
175
        group_ids = group_pool.search(cr, uid, [])
 
176
        for master_line in self.browse(cr, uid, ids):
 
177
            if master_line.order_line_ids:
 
178
                raise orm.except_orm(_('Error'),
 
179
                    _("Detailed lines generated yet (for master line '%s'). Remove them first") % master_line.name)
 
180
            if len(master_line.delivery_term_id.line_ids) > len(group_ids):
 
181
                raise orm.except_orm(_('Error'),
 
182
                    _("Delivery term lines are %d. Order line groups are %d. Please create more groups")
 
183
                    % (len(master_line.delivery_term_id.line_ids), len(group_ids)))
 
184
            if not master_line.delivery_term_id.is_total_percentage_correct():
 
185
                raise orm.except_orm(_('Error'),
 
186
                    _("Total percentage of delivery term %s is not equal to 1") % master_line.delivery_term_id.name)
 
187
            for group_index, term_line in enumerate(master_line.delivery_term_id.line_ids):
 
188
                order_line_vals = self._prepare_order_line(
 
189
                    cr, uid, term_line, master_line, group_index=group_index, context=context)
 
190
                order_line_pool.create(cr, uid, order_line_vals, context=context)
 
191
        return True
 
192
        
 
193
    def copy_data(self, cr, uid, id, default=None, context=None):
 
194
        if not default:
 
195
            default = {}
 
196
        default.update({
 
197
            'order_line_ids': [],
 
198
            })
 
199
        return super(sale_order_line_master, self).copy_data(cr, uid, id, default, context=context)
 
200
        
 
201
 
 
202
class sale_order_line(orm.Model):
 
203
    _inherit = 'sale.order.line'
 
204
    _columns = {
 
205
        'master_line_id': fields.many2one('sale.order.line.master', 'Master Line'),
 
206
        }
 
207
        
 
208
    def copy_data(self, cr, uid, id, default=None, context=None):
 
209
        if not default:
 
210
            default = {}
 
211
        default.update({'master_line_id': False})
 
212
        return super(sale_order_line, self).copy_data(cr, uid, id, default, context=context)
 
213
 
 
214
 
 
215
class sale_order(orm.Model):
 
216
    _inherit = 'sale.order'
 
217
    _columns = {
 
218
        'master_order_line': fields.one2many('sale.order.line.master', 'order_id', 'Master Order Lines', readonly=True, states={'draft': [('readonly', False)]}),
 
219
        }
 
220
        
 
221
    def copy(self, cr, uid, id, default=None, context=None):
 
222
        if not default:
 
223
            default = {}
 
224
        default.update({
 
225
            'order_line': [],
 
226
        })
 
227
        return super(sale_order, self).copy(cr, uid, id, default, context=context)
 
228
        
 
229
    def generate_detailed_lines(self, cr, uid, ids, context=None):
 
230
        for order in self.browse(cr, uid, ids, context):
 
231
            for master_line in order.master_order_line:
 
232
                master_line.generate_detailed_lines()
 
233
        return True
 
234