[IMP] sale_crm: Remove the product_ids and Improve the wizard of convert_sale
authorsbh (Open ERP) <sbh@tinyerp.com>
Tue, 13 Jul 2010 07:09:55 +0000 (12:39 +0530)
committersbh (Open ERP) <sbh@tinyerp.com>
Tue, 13 Jul 2010 07:09:55 +0000 (12:39 +0530)
bzr revid: sbh@tinyerp.com-20100713070955-pf54aqa40l6am1nt

addons/sale/wizard/sale_make_invoice.xml
addons/sale_crm/wizard/crm_make_sale.py
addons/sale_crm/wizard/crm_make_sale_view.xml

index 9884aa1..177ef8d 100644 (file)
             </field>
                </record>
 
+               <record id="action_sale_order_make_invoice" model="ir.actions.act_window">
+            <field name="name">Make Invoices</field>
+            <field name="type">ir.actions.act_window</field>
+            <field name="res_model">sale.make.invoice</field>
+            <field name="view_type">form</field>
+            <field name="view_mode">form</field>
+            <field name="target">new</field>
+        </record>
+        
         <act_window name="Make Invoices"                   
                    res_model="sale.make.invoice"
                    src_model="sale.order"
index e54d5d2..683d050 100644 (file)
@@ -22,6 +22,8 @@
 from osv import fields, osv
 from tools.translate import _
 from mx.DateTime import now
+import time
+import decimal_precision as dp
 
 class crm_make_sale(osv.osv_memory):
     """ Make sale  order for crm """
@@ -100,7 +102,6 @@ class crm_make_sale(osv.osv_memory):
                 vals = {
                     'origin': 'Opportunity:%s' % str(case.id),
                     'section_id': case.section_id and case.section_id.id or False,
-                    'picking_policy': make.picking_policy,
                     'shop_id': make.shop_id.id,
                     'partner_id': partner_id,
                     'pricelist_id': pricelist,
@@ -119,14 +120,16 @@ class crm_make_sale(osv.osv_memory):
                 if make.analytic_account.id:
                     vals['project_id'] = make.analytic_account.id
                 new_id = sale_obj.create(cr, uid, vals)
-                for product_id in make.product_ids:
+                for line in make.sale_order_line:
                     value = sale_line_obj.product_id_change(cr, uid, [], pricelist,
-                            product_id.id, qty=1, partner_id=partner_id, fiscal_position=fpos)['value']
-                    value['product_id'] = product_id.id
+                            line.product_id.id, qty=1, partner_id=partner_id, fiscal_position=fpos)['value']
+                    value['product_id'] =line.product_id.id
                     value['order_id'] = new_id
-                    value['tax_id'] = [(6,0,value['tax_id'])]
+                    value['tax_id'] = [(6,0,line['tax_id'])]
+                    value['product_uom_qty']=line.product_uom_qty
+                    value['discount']=line.discount
+                    value['product_uom']=line.product_uom.id
                     sale_line_obj.create(cr, uid, value)
-    
                 case_obj.write(cr, uid, [case.id], {'ref': 'sale.order,%s' % new_id})
                 new_ids.append(new_id)
                 message = _('Opportunity ') + " '" + case.name + "' "+ _("is converted to Sales Quotation.")
@@ -163,10 +166,7 @@ class crm_make_sale(osv.osv_memory):
     _columns = {
         'shop_id': fields.many2one('sale.shop', 'Shop', required=True),
         'partner_id': fields.many2one('res.partner', 'Customer', required=True, help='Use this partner if there is no partner on the Opportunity'),
-        'picking_policy': fields.selection([('direct','Partial Delivery'),
-                                            ('one','Complete Delivery')], 'Picking Policy', required=True),
-        'product_ids': fields.many2many('product.product', 'product_sale_rel',\
-                         'sale_id', 'product_id', 'Products'),
+        'sale_order_line': fields.one2many('sale.order.make.line', 'order_line', 'Product Line', readonly=True, states={'draft': [('readonly', False)]}),
         'analytic_account': fields.many2one('account.analytic.account', 'Analytic Account'),   
         'close': fields.boolean('Close Case', help='Check this to close the case after having created the sale order.'),              
     }
@@ -174,6 +174,160 @@ class crm_make_sale(osv.osv_memory):
          'partner_id': _selectPartner,
          'close': 1
     }
     
 crm_make_sale()
+
+class sale_order_make_line(osv.osv_memory):
+   
+
+    def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
+            uom=False, qty_uos=0, uos=False, name='', partner_id=False,
+            lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False):
+        if not  partner_id:
+            raise osv.except_osv(_('No Customer Defined !'), _('You have to select a customer in the sale form !\nPlease set one customer before choosing a product.'))
+        warning = {}
+        product_uom_obj = self.pool.get('product.uom')
+        partner_obj = self.pool.get('res.partner')
+        product_obj = self.pool.get('product.product')
+        if partner_id:
+            lang = partner_obj.browse(cr, uid, partner_id).lang
+        context = {'lang': lang, 'partner_id': partner_id}
+
+        if not product:
+            return {'value': {'th_weight': 0, 'product_packaging': False,
+                'product_uos_qty': qty}, 'domain': {'product_uom': [],
+                   'product_uos': []}}
+
+        if not date_order:
+            date_order = time.strftime('%Y-%m-%d')
+
+        result = {}
+        product_obj = product_obj.browse(cr, uid, product, context=context)
+        if not packaging and product_obj.packaging:
+            packaging = product_obj.packaging[0].id
+            result['product_packaging'] = packaging
+
+        if packaging:
+            default_uom = product_obj.uom_id and product_obj.uom_id.id
+            pack = self.pool.get('product.packaging').browse(cr, uid, packaging, context=context)
+            q = product_uom_obj._compute_qty(cr, uid, uom, pack.qty, default_uom)
+#            qty = qty - qty % q + q
+            if qty and (q and not (qty % q) == 0):
+                ean = pack.ean
+                qty_pack = pack.qty
+                type_ul = pack.ul
+                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)
+                warn_msg = warn_msg + "\n\n" + _("EAN: ") + str(ean) + _(" Quantity: ") + str(qty_pack) + _(" Type of ul: ") + str(type_ul.name)
+                warning = {
+                    'title': _('Picking Information !'),
+                    'message': warn_msg
+                    }
+            result['product_uom_qty'] = qty
+
+        uom2 = False
+        if uom:
+            uom2 = product_uom_obj.browse(cr, uid, uom)
+            if product_obj.uom_id.category_id.id != uom2.category_id.id:
+                uom = False
+
+        if uos:
+            if product_obj.uos_id:
+                uos2 = product_uom_obj.browse(cr, uid, uos)
+                if product_obj.uos_id.category_id.id != uos2.category_id.id:
+                    uos = False
+            else:
+                uos = False
+        if product_obj.description_sale:
+            result['notes'] = product_obj.description_sale
+        fpos = fiscal_position and self.pool.get('account.fiscal.position').browse(cr, uid, fiscal_position) or False
+        if update_tax: #The quantity only have changed
+            result['delay'] = (product_obj.sale_delay or 0.0)
+            partner = partner_obj.browse(cr, uid, partner_id)
+            result['tax_id'] = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, product_obj.taxes_id)
+            result.update({'type': product_obj.procure_method})
+
+        if not flag:
+            result['name'] = self.pool.get('product.product').name_get(cr, uid, [product_obj.id], context=context)[0][1]
+        domain = {}
+        if (not uom) and (not uos):
+            result['product_uom'] = product_obj.uom_id.id
+            if product_obj.uos_id:
+                result['product_uos'] = product_obj.uos_id.id
+                result['product_uos_qty'] = qty * product_obj.uos_coeff
+                uos_category_id = product_obj.uos_id.category_id.id
+            else:
+                result['product_uos'] = False
+                result['product_uos_qty'] = qty
+                uos_category_id = False
+            domain = {'product_uom':
+                        [('category_id', '=', product_obj.uom_id.category_id.id)],
+                        'product_uos':
+                        [('category_id', '=', uos_category_id)]}
+
+        elif uos and not uom: # only happens if uom is False
+            result['product_uom'] = product_obj.uom_id and product_obj.uom_id.id
+            result['product_uom_qty'] = qty_uos / product_obj.uos_coeff
+        elif uom: # whether uos is set or not
+            default_uom = product_obj.uom_id and product_obj.uom_id.id
+            q = product_uom_obj._compute_qty(cr, uid, uom, qty, default_uom)
+            if product_obj.uos_id:
+                result['product_uos'] = product_obj.uos_id.id
+                result['product_uos_qty'] = qty * product_obj.uos_coeff
+            else:
+                result['product_uos'] = False
+                result['product_uos_qty'] = qty
+
+        if not uom2:
+            uom2 = product_obj.uom_id
+        return {'value': result, 'domain': domain, 'warning': warning}
+    
+    def product_uom_change(self, cursor, user, ids, pricelist, product, qty=0,
+            uom=False, qty_uos=0, uos=False, name='', partner_id=False,
+            lang=False, update_tax=True, date_order=False):
+        res = self.product_id_change(cursor, user, ids, pricelist, product,
+                qty=qty, uom=uom, qty_uos=qty_uos, uos=uos, name=name,
+                partner_id=partner_id, lang=lang, update_tax=update_tax,
+                date_order=date_order)
+        if 'product_uom' in res['value']:
+            del res['value']['product_uom']
+        if not uom:
+            res['value']['price_unit'] = 0.0
+        return res    
+
+    _name = 'sale.order.make.line'
+    _description = 'Sale Order Line'
+    _columns = {
+        'order_line': fields.many2one('crm.make.sale', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, ),
+        'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, ),
+        'name': fields.char('Description', size=256, required=True, select=True, readonly=True, ),
+        'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of sale order lines."),
+        'delay': fields.float('Delivery Lead Time', required=True, help="Number of days between the order confirmation the the shipping of the products to the customer", readonly=True, ),
+        'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True),
+        'procurement_id': fields.many2one('procurement.order', 'Procurement'),
+        'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Sale Price'), readonly=True, ),
+        'tax_id': fields.many2many('account.tax', 'sale_order_tax', 'order_line_id', 'tax_id', 'Taxes', readonly=True, states={'draft':[('readonly',False)]}),
+        'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft':[('readonly',False)]}),
+        'product_uom_qty': fields.float('Quantity (UoM)', digits=(16, 2), required=True, readonly=True, states={'draft':[('readonly',False)]}),
+        'product_uom': fields.many2one('product.uom', 'Unit of Measure ', required=True, readonly=True, states={'draft':[('readonly',False)]}),
+        'product_uos_qty': fields.float('Quantity (UoS)', readonly=True, states={'draft':[('readonly',False)]}),
+        'product_uos': fields.many2one('product.uom', 'Product UoS'),
+        'product_packaging': fields.many2one('product.packaging', 'Packaging'),
+        'discount': fields.float('Discount (%)', digits=(16, 2), readonly=True, states={'draft':[('readonly',False)]}),
+        'notes': fields.text('Notes'),
+    }
+    _order = 'sequence, id'
+    _defaults = {
+        'discount': 0.0,
+        'delay': 0.0,
+        'product_uom_qty': 1,
+        'product_uos_qty': 1,
+        'type': 'make_to_stock',
+        'product_packaging': False
+    }
+
+sale_order_make_line()   
+
+
+
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
index a1da3ed..17e7439 100644 (file)
@@ -9,21 +9,66 @@
           <field name="type">form</field>
           <field name="arch" type="xml">
               <form string="Create a Sale Order" >
+                       <group width="660" height="300">
                     <group colspan="4">
                         <field name="partner_id" required="1"/>
                         <field name="shop_id" required="1" widget="selection"/>
                         <field name="analytic_account"/>
-                        <field name="picking_policy"/>
                         <field name="close" required="1"/>
-                    </group>
-                    <separator string="Products" colspan="4"/>
-                    <field name="product_ids" colspan="4" nolabel="1"/>
+                       </group>
+                            <field colspan="4" mode="tree,form,graph" name="sale_order_line" nolabel="1" widget="one2many_list">
+                                <form string="Sale Order Lines">
+                                    <notebook>
+                                        <page string="Order Line">
+                                            <field colspan="4"
+                                                context="partner_id=parent.partner_id,quantity=product_uom_qty,pricelist=parent.pricelist_id,shop=parent.shop_id,uom=product_uom"
+                                                name="product_id"
+                                                on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, 'lang' in context and context['lang'], True, parent.date_order, product_packaging, parent.fiscal_position, False)"
+                                                />
+                                            <field
+                                                context="partner_id=parent.partner_id,quantity=product_uom_qty,pricelist=parent.pricelist_id,shop=parent.shop_id,uom=product_uom"
+                                                name="product_uom_qty"
+                                                on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, 'lang' in context and context['lang'], False, parent.date_order, product_packaging, parent.fiscal_position, True)"
+                                                />
+                                                <field groups="product.group_uos" name="product_uos_qty"/>
+                                            <field name="product_uom"
+                                                on_change="product_uom_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, 'lang' in context and context['lang'], False, parent.date_order)"/>
+                                            <field
+                                                name="product_packaging"
+                                                context="partner_id=parent.partner_id,quantity=product_uom_qty,pricelist=parent.pricelist_id,shop=parent.shop_id,uom=product_uom"
+                                                on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, 'lang' in context and context['lang'], False, parent.date_order, product_packaging, parent.fiscal_position, False)"
+                                                domain="[('product_id','=',product_id)]"
+                                                groups="base.group_extended"/>
+
+                                            <field colspan="4" name="name"/>
+                                            <field name="price_unit"/>
+                                            <field name="discount"/>
+                                            <field name="type" groups="base.group_extended"/>
+                                            <field name="delay" groups="base.group_extended"/>
+                                            <newline/>
+                                            <separator colspan="5" string="Taxes"/>
+                                            <field colspan="4" name="tax_id" nolabel="1" domain="[('parent_id','=',False),('type_tax_use','&lt;&gt;','purchase')]"/>
+                                        </page>
+                                    </notebook>
+                                </form>
+                                <tree string="Sales order lines">
+                                    <field colspan="4" name="name"/>
+                                    <field name="product_uom_qty" string="Qty"/>
+                                    <field name="product_uom" string="UoM"/>
+                                    <field name="discount"/>
+                                    <field name="price_unit"/>
+                                </tree>
+                            </field>
+                            <newline/>
+
+                               
                 <separator colspan="4"/>
                 <group col="4" colspan="4">
                     <label string="" colspan="2"/>
                     <button special="cancel" string="_Close" icon="gtk-cancel"/>
                     <button name="makeOrder" string="_Ok" type="object" icon='gtk-ok'/>
                 </group>
+                </group>
             </form>
           </field>
        </record>