From 24ea556c0c23cf811d69fc8965edde79b76a0dce Mon Sep 17 00:00:00 2001 From: Rucha Patel Date: Wed, 24 Sep 2008 19:05:23 +0530 Subject: [PATCH] Developed a module: sale_delivery for sales orders that are shipped in several times for EO2 bzr revid: ruchakpatel@gmail.com-20080924133523-h18auq8hcqtkn1yx --- addons/sale/sale.py | 2 - addons/sale_delivery/__init__.py | 34 ++++ addons/sale_delivery/__terp__.py | 43 ++++ addons/sale_delivery/sale_delivery.py | 206 ++++++++++++++++++++ addons/sale_delivery/sale_delivery_view.xml | 69 +++++++ addons/stock/stock.py | 3 - addons/stock/stock_view.xml | 8 +- 7 files changed, 357 insertions(+), 8 deletions(-) create mode 100644 addons/sale_delivery/__init__.py create mode 100644 addons/sale_delivery/__terp__.py create mode 100644 addons/sale_delivery/sale_delivery.py create mode 100644 addons/sale_delivery/sale_delivery_view.xml diff --git a/addons/sale/sale.py b/addons/sale/sale.py index a949e713068..6f0b2da4a81 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -954,9 +954,7 @@ class sale_config_picking_policy(osv.osv_memory): 'order_policy': lambda *a: 'picking' } def set_default(self, cr, uid, ids, context=None): - print context for o in self.browse(cr, uid, ids, context=context): - print o.picking_policy, o.order_policy ir_values_obj = self.pool.get('ir.values') ir_values_obj.set(cr,uid,'default',False,'picking_policy',['sale.order'],o.picking_policy) ir_values_obj = self.pool.get('ir.values') diff --git a/addons/sale_delivery/__init__.py b/addons/sale_delivery/__init__.py new file mode 100644 index 00000000000..1d6e7cb3107 --- /dev/null +++ b/addons/sale_delivery/__init__.py @@ -0,0 +1,34 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved. +# +# $Id$ +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import sale_delivery + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/sale_delivery/__terp__.py b/addons/sale_delivery/__terp__.py new file mode 100644 index 00000000000..2ec84f19c7a --- /dev/null +++ b/addons/sale_delivery/__terp__.py @@ -0,0 +1,43 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2004-2008 Tiny SPRL (http://tiny.be) All Rights Reserved. +# +# $Id$ +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +############################################################################### +# -*- encoding: utf-8 -*- +{ + "name":"Sale Delivery Planning", + "version":"1.0", + "author":"Tiny", + "category":"Custom", + "depends":["sale"], + "demo_xml":[], + "update_xml":["sale_delivery_view.xml"], + "active": False, + "installable": True, +} + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/sale_delivery/sale_delivery.py b/addons/sale_delivery/sale_delivery.py new file mode 100644 index 00000000000..3f3a7ea6ecf --- /dev/null +++ b/addons/sale_delivery/sale_delivery.py @@ -0,0 +1,206 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved. +# +# $Id$ +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import time +from osv import fields,osv +import netsvc + +class sale_delivery_line(osv.osv): + _name = 'sale.delivery.line' + def _check_product_qty(self, cr, uid, ids): + for delivery in self.browse(cr, uid, ids): + 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)) + sale_product_qty = cr.fetchall()[0][0] + cr.execute('select sum(product_qty) from sale_delivery_line where order_id = %d and product_id = %d',(delivery.order_id,delivery.product_id)) + product_qty = cr.fetchall()[0][0] + if sale_product_qty < product_qty: + return False + return True + + def _check_products(self, cr, uid, ids): + for delivery in self.browse(cr, uid, ids): + cr.execute('select id from sale_order_line where order_id = %d and product_id = %d',(delivery.order_id,delivery.product_id)) + if not len(cr.fetchall()): + return False + return True + + _columns = { + 'product_id': fields.many2one('product.product', string='Product', required=True ), + 'product_qty': fields.float('Product Quantity', digits=(16,2), required=True), + 'product_uom' : fields.many2one('product.uom', 'Product UoM', required=True), + 'packaging_id' : fields.many2one('product.packaging', 'Packaging'), + 'date_planned': fields.datetime('Date Planned', select=True, required=True), + 'priority': fields.integer('Priority'), + 'note' : fields.text('Note'), + 'order_id': fields.many2one('sale.order', 'Order Ref', required=True, ondelete='cascade', select=True), + } + _constraints = [ + (_check_products, + 'You have selected a product which is not in related Sale Order', + ['product_id']), + (_check_product_qty, + 'The quanitties plannified in Deliveries must be equals to or less then the quantities in the Sale Order lines', + ['product_qty'])] + +sale_delivery_line() + + +class sale_order(osv.osv): + _inherit = 'sale.order' + _columns = { + 'delivery_line': fields.one2many('sale.delivery.line', 'order_id', 'Delivery Lines', readonly=True, states={'draft':[('readonly',False)]}), + } + + def action_ship_create(self, cr, uid, ids, *args): +# picking_id=False + picking = {} + company = self.pool.get('res.users').browse(cr, uid, uid).company_id + for order in self.browse(cr, uid, ids, context={}): + output_id = order.shop_id.warehouse_id.lot_output_id.id +# picking_id = False +# if not order.delivery_line: +# return super(sale_order, self).action_ship_create(cr, uid, ids) + for line in order.delivery_line: + cr.execute('select id from sale_order_line where order_id = %d and product_id = %d',(ids[0],line.product_id.id)) + sale_line_id = cr.fetchall()[0][0] + sale_line = self.pool.get('sale.order.line').browse(cr, uid, sale_line_id) + proc_id=False + date_planned = line.date_planned +# date_planned = (date_planned - DateTime.RelativeDateTime(days=company.security_lead)).strftime('%Y-%m-%d %H:%M:%S') +# if line.state == 'done': +# continue + if line.product_id and line.product_id.product_tmpl_id.type in ('product', 'consu'): + location_id = order.shop_id.warehouse_id.lot_stock_id.id +# if not picking_id: + if not date_planned in picking: + loc_dest_id = order.partner_id.property_stock_customer.id + picking_id = self.pool.get('stock.picking').create(cr, uid, { + 'origin': order.name, + 'type': 'out', + 'state': 'confirmed', + 'move_type': order.picking_policy, + 'sale_id': order.id, + 'address_id': order.partner_shipping_id.id, + 'note': order.note, + 'invoice_state': (order.order_policy=='picking' and '2binvoiced') or 'none', + }) + picking[date_planned] = picking_id + + else: + picking_id = picking[date_planned] + + move_id = self.pool.get('stock.move').create(cr, uid, { + 'name': line.product_id.name[:64], + 'picking_id': picking_id, + 'product_id': line.product_id.id, + 'date_planned': date_planned, + 'product_qty': line.product_qty, + 'product_uom': line.product_uom.id, + 'product_uos_qty': line.product_qty, + 'product_uos': line.product_uom.id, + 'product_packaging' : line.packaging_id.id, + 'address_id' : order.partner_shipping_id.id, + 'location_id': location_id, + 'location_dest_id': output_id, + 'tracking_id': False, + 'state': 'waiting', + 'note': line.note, + }) + proc_id = self.pool.get('mrp.procurement').create(cr, uid, { + 'name': order.name, + 'origin': order.name, + 'date_planned': date_planned, + 'product_id': line.product_id.id, + 'product_qty': line.product_qty, + 'product_uom': line.product_uom.id, + 'product_uos_qty': line.product_qty, + 'product_uos': line.product_uom.id, + 'location_id': order.shop_id.warehouse_id.lot_stock_id.id, + 'procure_method': sale_line.type, + 'move_id': move_id, + 'property_ids': [(6, 0, [x.id for x in sale_line.property_ids])], + }) + wf_service = netsvc.LocalService("workflow") + wf_service.trg_validate(uid, 'mrp.procurement', proc_id, 'button_confirm', cr) +# self.pool.get('sale.order.line').write(cr, uid, [line.id], {'procurement_id': proc_id}) + elif line.product_id and line.product_id.product_tmpl_id.type=='service': + proc_id = self.pool.get('mrp.procurement').create(cr, uid, { + 'name': line.name, + 'origin': order.name, + 'date_planned': date_planned, + 'product_id': line.product_id.id, + 'product_qty': line.product_uom_qty, + 'product_uom': line.product_uom.id, + 'location_id': order.shop_id.warehouse_id.lot_stock_id.id, + 'procure_method': line.type, + 'property_ids': [(6, 0, [x.id for x in line.property_ids])], + }) + wf_service = netsvc.LocalService("workflow") + wf_service.trg_validate(uid, 'mrp.procurement', proc_id, 'button_confirm', cr) +# self.pool.get('sale.order.line').write(cr, uid, [line.id], {'procurement_id': proc_id}) + else: + # + # No procurement because no product in the sale.order.line. + # + pass + wf_service = netsvc.LocalService("workflow") + wf_service.trg_validate(uid, 'stock.picking', picking['date_planned'], 'button_confirm', cr) + + val = {} +# if 'date_planned' in picking and picking['date_planned']: +# print + + if order.state=='shipping_except': + val['state'] = 'progress' + if (order.order_policy == 'manual') and order.invoice_ids: + val['state'] = 'manual' + self.write(cr, uid, [order.id], val) + + return True +sale_order() + +class sale_order_line(osv.osv): + _inherit = 'sale.order.line' + + def _get_planned_deliveries(self, cr, uid, ids, field_name, arg, context): + res = {} + for val in self.browse(cr, uid, ids): + cr.execute('select sum(product_qty) from sale_delivery_line where order_id = %d and product_id = %d',(val.order_id,val.product_id)) + product_qty = cr.fetchall()[0][0] + res[val.id] = product_qty + return res + + _columns = { + 'deliveries': fields.function(_get_planned_deliveries, method=True, string='Planned Deliveries'), + } + +sale_order_line() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_delivery/sale_delivery_view.xml b/addons/sale_delivery/sale_delivery_view.xml new file mode 100644 index 00000000000..f5372876dff --- /dev/null +++ b/addons/sale_delivery/sale_delivery_view.xml @@ -0,0 +1,69 @@ + + + + + + sale.delivery.form.inherit + sale.order + form + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + sale.order.line.form1 + sale.order.line + tree + + + + + + + + + + + sale.delivery.form.inherit1 + sale.order + form + + + + + + + + +
+
diff --git a/addons/stock/stock.py b/addons/stock/stock.py index ede9e8e9e99..736daa9333f 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -329,9 +329,7 @@ class stock_picking(osv.osv): def _set_minimum_date(self, cr, uid, ids, name, value, arg, context): if not value: return False - print self.browse(cr, uid, [ids], context) for pick in self.browse(cr, uid,[ids], context): - print value,type(value),pick.min_date cr.execute("""update stock_move set date_planned=%s where @@ -911,7 +909,6 @@ class stock_move(osv.osv): cursor.commit() def onchange_lot_id(self, cr, uid, context, prodlot_id=False,product_qty=False, loc_id=False): - print uid, prodlot_id, product_qty, loc_id if not prodlot_id or not loc_id: return {} prodlot = self.pool.get('stock.production.lot').browse(cr, uid, prodlot_id) diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 3759939f5fc..1a75d6a4cdc 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -1345,10 +1345,12 @@ tree [('name','>=',time.strftime('%Y-%m-01'))] + + - - -