1
# -*- encoding: utf-8 -*-
2
##############################################################################
4
# Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved.
8
# WARNING: This program as such is intended to be used by professional
9
# programmers who take the whole responsability of assessing all potential
10
# consequences resulting from its eventual inadequacies and bugs
11
# End users who are looking for a ready-to-use solution with commercial
12
# garantees and support are strongly adviced to contract a Free Software
15
# This program is Free Software; you can redistribute it and/or
16
# modify it under the terms of the GNU General Public License
17
# as published by the Free Software Foundation; either version 2
18
# of the License, or (at your option) any later version.
20
# This program is distributed in the hope that it will be useful,
21
# but WITHOUT ANY WARRANTY; without even the implied warranty of
22
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
# GNU General Public License for more details.
25
# You should have received a copy of the GNU General Public License
26
# along with this program; if not, write to the Free Software
27
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29
##############################################################################
32
from osv import fields,osv
34
from mx import DateTime
36
class sale_delivery_line(osv.osv):
37
_name = 'sale.delivery.line'
40
'product_id': fields.many2one('product.product', string='Product', required=True ),
41
'product_qty': fields.float('Product Quantity', digits=(16,2), required=True),
42
'product_uom' : fields.many2one('product.uom', 'Product UoM', required=True),
43
'packaging_id' : fields.many2one('product.packaging', 'Packaging'),
44
'date_planned': fields.datetime('Date Planned', select=True, required=True),
45
'priority': fields.integer('Priority'),
46
'note' : fields.text('Note'),
47
'order_id': fields.many2one('sale.order', 'Order Ref', required=True, ondelete='cascade', select=True),
49
_order = 'priority,date_planned'
51
'priority': lambda *a: 1,
54
def product_id_change(self, cr, uid, ids, product, qty=0, uom=False, packaging=False):
56
product_uom_obj = self.pool.get('product.uom')
57
product_obj = self.pool.get('product.product')
60
return {'value': {'product_qty' : 0.0, 'product_uom': False,
61
'packaging_id': False}, 'domain': {'product_uom': []}}
64
product_obj = product_obj.browse(cr, uid, product)
66
default_uom = product_obj.uom_id and product_obj.uom_id.id
67
pack = self.pool.get('product.packaging').browse(cr, uid, packaging)
68
q = product_uom_obj._compute_qty(cr, uid, uom, pack.qty, default_uom)
69
if not (qty % q) == 0 :
73
warn_msg = "You selected a quantity of %d Units.\nBut it's not compatible with the selected packaging.\nHere is a proposition of quantities according to the packaging: " % (qty)
74
warn_msg = warn_msg + "\n\nEAN: " + str(ean) + " Quantiny: " + str(qty_pack) + " Type of ul: " + str(type_ul.name)
76
'title':'Packing Information !',
79
result['product_qty'] = qty
81
result .update({'type': product_obj.procure_method})
85
result['product_uom'] = product_obj.uom_id.id
86
domain = {'product_uom':
87
[('category_id', '=', product_obj.uom_id.category_id.id)],}
89
return {'value': result, 'domain': domain,'warning':warning}
94
class sale_order(osv.osv):
95
_inherit = 'sale.order'
97
'delivery_line': fields.one2many('sale.delivery.line', 'order_id', 'Delivery Lines', readonly=True, states={'draft':[('readonly',False)]}),
100
def action_ship_create(self, cr, uid, ids, *args):
102
company = self.pool.get('res.users').browse(cr, uid, uid).company_id
103
for order in self.browse(cr, uid, ids, context={}):
104
for delivery in order.delivery_line:
105
cr.execute('select id from sale_order_line where order_id = %d and product_id = %d',(delivery.order_id,delivery.product_id))
106
if not len(cr.fetchall()):
107
raise osv.except_osv(_('Error !'), _('You have selected a product %s for Delivery but it is not in supposed to be saled in this Sale Order') % (delivery.product_id.name))
109
for delivery in order.delivery_line:
110
cr.execute('select sum(product_uom_qty) from sale_order_line where order_id = %d and product_id = %d',(delivery.order_id,delivery.product_id))
111
sale_product_qty = cr.fetchall()[0][0]
112
cr.execute('select sum(product_qty) from sale_delivery_line where order_id = %d and product_id = %d',(delivery.order_id,delivery.product_id))
113
product_qty = cr.fetchall()[0][0]
114
if sale_product_qty < product_qty:
115
raise osv.except_osv(_('Error !'), _('The quanitties plannified in Deliveries (%d) for Product : %s must be equals to or less then the quantities in the Sale Order lines (%d)') % (product_qty,delivery.product_id.name,sale_product_qty))
117
location_id = order.shop_id.warehouse_id.lot_stock_id.id
118
output_id = order.shop_id.warehouse_id.lot_output_id.id
119
if not order.delivery_line:
120
return super(sale_order, self).action_ship_create(cr, uid, ids)
122
for line in order.order_line:
123
if line.product_id and line.product_id.product_tmpl_id.type in ('product', 'consu'):
124
product_qty = line.product_uom_qty-line.deliveries
126
date_planned = DateTime.now() + DateTime.RelativeDateTime(days=line.delay or 0.0)
127
date_planned = (date_planned - DateTime.RelativeDateTime(days=company.security_lead)).strftime('%Y-%m-%d %H:%M:%S')
129
picking_id = self.pool.get('stock.picking').create(cr, uid, {
130
'origin': order.name,
132
'state': 'confirmed',
133
'move_type': order.picking_policy,
135
'address_id': order.partner_shipping_id.id,
137
'invoice_state': (order.order_policy=='picking' and '2binvoiced') or 'none',
139
move_id = self.pool.get('stock.move').create(cr, uid, {
140
'name': line.name[:64],
141
'picking_id': picking_id,
142
'product_id': line.product_id.id,
143
'date_planned': date_planned,
144
'product_qty': product_qty,
145
'product_uom': line.product_uom.id,
146
'product_uos_qty': product_qty,
147
'product_uos': (line.product_uos and line.product_uos.id)\
148
or line.product_uom.id,
149
'product_packaging' : line.product_packaging.id,
150
'address_id' : line.address_allotment_id.id or order.partner_shipping_id.id,
151
'location_id': location_id,
152
'location_dest_id': output_id,
153
'sale_line_id': line.id,
154
'tracking_id': False,
158
proc_id = self.pool.get('mrp.procurement').create(cr, uid, {
160
'origin': order.name,
161
'date_planned': date_planned,
162
'product_id': line.product_id.id,
163
'product_qty': product_qty,
164
'product_uom': line.product_uom.id,
165
'product_uos_qty': product_qty,
166
'product_uos': line.product_uom.id,
167
'location_id': order.shop_id.warehouse_id.lot_stock_id.id,
168
'procure_method': line.type,
170
'property_ids': [(6, 0, [x.id for x in line.property_ids])],
173
elif line.product_id and line.product_id.product_tmpl_id.type=='service':
174
proc_id = self.pool.get('mrp.procurement').create(cr, uid, {
176
'origin': order.name,
177
'date_planned': date_planned,
178
'product_id': line.product_id.id,
179
'product_qty': line.product_uom_qty,
180
'product_uom': line.product_uom.id,
181
'location_id': order.shop_id.warehouse_id.lot_stock_id.id,
182
'procure_method': line.type,
183
'property_ids': [(6, 0, [x.id for x in line.property_ids])],
185
wf_service = netsvc.LocalService("workflow")
186
wf_service.trg_validate(uid, 'mrp.procurement', proc_id, 'button_confirm', cr)
188
for line in order.delivery_line:
189
cr.execute('select id from sale_order_line where order_id = %d and product_id = %d',(ids[0],line.product_id.id))
190
sale_line_id = cr.fetchall()[0][0]
191
sale_line = self.pool.get('sale.order.line').browse(cr, uid, sale_line_id)
192
date_planned = line.date_planned
193
if line.product_id and line.product_id.product_tmpl_id.type in ('product', 'consu'):
194
if not date_planned in picking:
195
loc_dest_id = order.partner_id.property_stock_customer.id
196
picking_id = self.pool.get('stock.picking').create(cr, uid, {
197
'origin': order.name,
199
'state': 'confirmed',
200
'move_type': order.picking_policy,
202
'address_id': order.partner_shipping_id.id,
204
'invoice_state': (order.order_policy=='picking' and '2binvoiced') or 'none',
206
picking[date_planned] = picking_id
209
picking_id = picking[date_planned]
211
move_id = self.pool.get('stock.move').create(cr, uid, {
212
'name': line.product_id.name[:64],
213
'picking_id': picking_id,
214
'product_id': line.product_id.id,
215
'date_planned': date_planned,
216
'product_qty': line.product_qty,
217
'product_uom': line.product_uom.id,
218
'product_uos_qty': line.product_qty,
219
'product_uos': line.product_uom.id,
220
'product_packaging' : line.packaging_id.id,
221
'address_id' : order.partner_shipping_id.id,
222
'location_id': location_id,
223
'location_dest_id': output_id,
224
'tracking_id': False,
228
proc_id = self.pool.get('mrp.procurement').create(cr, uid, {
230
'origin': order.name,
231
'date_planned': date_planned,
232
'product_id': line.product_id.id,
233
'product_qty': line.product_qty,
234
'product_uom': line.product_uom.id,
235
'product_uos_qty': line.product_qty,
236
'product_uos': line.product_uom.id,
237
'location_id': order.shop_id.warehouse_id.lot_stock_id.id,
238
'procure_method': sale_line.type,
240
'property_ids': [(6, 0, [x.id for x in sale_line.property_ids])],
242
wf_service = netsvc.LocalService("workflow")
243
wf_service.trg_validate(uid, 'mrp.procurement', proc_id, 'button_confirm', cr)
245
wf_service = netsvc.LocalService("workflow")
246
wf_service.trg_validate(uid, 'stock.picking', picking[date_planned], 'button_confirm', cr)
250
if order.state=='shipping_except':
251
val['state'] = 'progress'
252
if (order.order_policy == 'manual') and order.invoice_ids:
253
val['state'] = 'manual'
254
self.write(cr, uid, [order.id], val)
259
class sale_order_line(osv.osv):
260
_inherit = 'sale.order.line'
262
def _get_planned_deliveries(self, cr, uid, ids, field_name, arg, context):
264
for val in self.browse(cr, uid, ids):
265
cr.execute('select sum(product_qty) from sale_delivery_line where order_id = %d and product_id = %d',(val.order_id,val.product_id))
266
product_qty = cr.fetchall()[0][0]
267
res[val.id] = product_qty
271
'deliveries': fields.function(_get_planned_deliveries, method=True, string='Planned Deliveries'),
276
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: