Merge with addons
authorRucha Patel <ruchakpatel@gmail.com>
Mon, 13 Oct 2008 06:58:47 +0000 (12:28 +0530)
committerRucha Patel <ruchakpatel@gmail.com>
Mon, 13 Oct 2008 06:58:47 +0000 (12:28 +0530)
bzr revid: ruchakpatel@gmail.com-20081013065847-ffnjkovsr3zuxif1

29 files changed:
addons/account/account_invoice_view.xml
addons/account/invoice.py
addons/account/project/project.py
addons/account/project/project_view.xml
addons/account/project/wizard/__init__.py
addons/account/project/wizard/wizard_account_analytic_line1.py [new file with mode: 0644]
addons/mrp/mrp.py
addons/process/example/sale_order.pdf [deleted file]
addons/process/processus_report.xml [deleted file]
addons/process/report/__init__.py [deleted file]
addons/process/report/ds.ttf [deleted file]
addons/process/report/gtk-help.png [deleted file]
addons/process/report/gtk-new.png [deleted file]
addons/process/report/gtk-open.png [deleted file]
addons/process/report/gtk-print.png [deleted file]
addons/process/report/processus_print.py [deleted file]
addons/process/report/report_processus.py [deleted file]
addons/process/report/role.png [deleted file]
addons/process/report/sb.ttf [deleted file]
addons/product/product.py
addons/product/product_view.xml
addons/purchase/purchase.py
addons/sale/sale.py
addons/sale_delivery/__init__.py [new file with mode: 0644]
addons/sale_delivery/__terp__.py [new file with mode: 0644]
addons/sale_delivery/sale_delivery.py [new file with mode: 0644]
addons/sale_delivery/sale_delivery_view.xml [new file with mode: 0644]
addons/stock/stock.py
addons/stock/stock_view.xml

index 1f76270..b2007a3 100644 (file)
                     <notebook>
                         <page string="Line">
                             <field name="product_id" on_change="product_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id)" select="1"/>
-                            <field name="uos_id"/>
+                            <field name="uos_id"
+                            context="product_id=product_id"
+                            on_change="product_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id)"          
+                            />
                             <field name="quantity" select="1"/>
                             <field name="price_unit" select="1"/>
                             <field name="discount"/>
index b81c624..a8eb3bd 100644 (file)
@@ -848,7 +848,7 @@ class account_invoice_line(osv.osv):
             if type in ('in_invoice', 'in_refund'):
                 return {'domain':{'product_uom':[]}}
             else:
-                return {'value': {'price_unit': 0.0}, 'domain':{'product_uom':[]}}
+                return {'value': {'price_unit': 0.0 }, 'domain':{'uos_id': []}}
         lang=False
         context.update({'lang': lang})
         res = self.pool.get('product.product').browse(cr, uid, product, context=context)
@@ -893,11 +893,12 @@ class account_invoice_line(osv.osv):
             result['account_id'] = a
 
         domain = {}
-        result['uos_id'] = uom or res.uom_id.id or False
+        result['uos_id'] = res.uom_id.id or uom or False
         if result['uos_id']:
             res2 = res.uom_id.category_id.id
             if res2 :
                 domain = {'uos_id':[('category_id','=',res2 )]}
+                result
         return {'value':result, 'domain':domain}
 
     def move_line_get(self, cr, uid, invoice_id, context={}):
index b4cc346..60a1704 100644 (file)
@@ -43,17 +43,32 @@ class account_analytic_account(osv.osv):
     _description = 'Analytic Accounts'
 
     def _credit_calc(self, cr, uid, ids, name, arg, context={}):
+        if 'date_start' in context and context['date_start']:
+            date_start = context['date_start']
+        else:
+            date_start = time.strftime('%Y-01-01')
+        if 'date_stop' in context and context['date_stop']:
+            date_stop = context['date_stop']
+        else:
+            date_stop = time.strftime('%Y-%m-%d')
         acc_set = ",".join(map(str, ids))
-        cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id) WHERE l.amount<0 and a.id IN (%s) GROUP BY a.id" % acc_set)
+        cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id) WHERE l.amount<0 and a.id IN (%s) AND (l.date BETWEEN '%s' and '%s') GROUP BY a.id" % (acc_set,date_start,date_stop))
         r= dict(cr.fetchall())
         for i in ids:
             r.setdefault(i,0.0)
         return r
 
     def _debit_calc(self, cr, uid, ids, name, arg, context={}):
-
+        if 'date_start' in context and context['date_start']:
+            date_start = context['date_start']
+        else:
+            date_start = time.strftime('%Y-01-01')
+        if 'date_stop' in context and context['date_stop']:
+            date_stop = context['date_stop']
+        else:
+            date_stop = time.strftime('%Y-%m-%d')
         acc_set = ",".join(map(str, ids))
-        cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id) WHERE l.amount>0 and a.id IN (%s) GROUP BY a.id" % acc_set)
+        cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id) WHERE l.amount>0 and a.id IN (%s)  AND (l.date BETWEEN '%s' and '%s') GROUP BY a.id" % (acc_set,date_start,date_stop))
         r= dict(cr.fetchall())
         for i in ids:
             r.setdefault(i,0.0)
@@ -62,9 +77,18 @@ class account_analytic_account(osv.osv):
 
 
     def _balance_calc(self, cr, uid, ids, name, arg, context={}):
+        if 'date_start' in context and context['date_start']:
+            date_start = context['date_start']
+        else:
+            date_start = time.strftime('%Y-01-01')
+        if 'date_stop' in context and context['date_stop']:
+            date_stop = context['date_stop']
+        else:
+            date_stop = time.strftime('%Y-%m-%d')
         ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)])
         acc_set = ",".join(map(str, ids2))
-        cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id) WHERE a.id IN (%s) GROUP BY a.id" % acc_set)
+        cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id) WHERE a.id IN (%s)  AND (l.date BETWEEN '%s' and '%s') GROUP BY a.id" % (acc_set,date_start,date_stop))
+#        cr.execute("select a.id, COALESCE(SUM(l.amount),0) from account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id) where (l.date BETWEEN '2008-10-01' AND '2008-10-03') GROUP BY a.id")
         res = {}
         for account_id, sum in cr.fetchall():
             res[account_id] = sum
@@ -91,13 +115,21 @@ class account_analytic_account(osv.osv):
         return dict([(i, res[i]) for i in ids ])
 
     def _quantity_calc(self, cr, uid, ids, name, arg, context={}):
-        #XXX must convert into one uom
+#        XXX must convert into one uom
+        if 'date_start' in context and context['date_start']:
+            date_start = context['date_start']
+        else:
+            date_start = time.strftime('%Y-01-01')
+        if 'date_stop' in context and context['date_stop']:
+            date_stop = context['date_stop']
+        else:
+            date_stop = time.strftime('%Y-%m-%d')
         ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)])
         acc_set = ",".join(map(str, ids2))
-        cr.execute('SELECT a.id, COALESCE(SUM(l.unit_amount), 0) \
+        cr.execute("SELECT a.id, COALESCE(SUM(l.unit_amount), 0) \
                 FROM account_analytic_account a \
                     LEFT JOIN account_analytic_line l ON (a.id = l.account_id) \
-                WHERE a.id IN ('+acc_set+') GROUP BY a.id')
+                WHERE a.id IN (%s) AND (l.date BETWEEN '%s' and '%s') GROUP BY a.id" % (acc_set,date_start,date_stop))
         res = {}
         for account_id, sum in cr.fetchall():
             res[account_id] = sum
@@ -107,6 +139,8 @@ class account_analytic_account(osv.osv):
                 if child <> id:
                     res.setdefault(id, 0.0)
                     res[id] += res.get(child, 0.0)
+            if not id in res:
+                res.setdefault(id, 0.0)
         return dict([(i, res[i]) for i in ids])
 
     def name_get(self, cr, uid, ids, context={}):
index ccc8fb4..1def5a2 100644 (file)
              <field name="view_mode">form,graph</field>
             <field name="view_id" ref="view_account_analytic_account_tree"/>
         </record>
+        
         <menuitem
             action="action_account_analytic_account_tree2"
             id="account_analytic_def_chart"
             parent="account.account_analytic_def_account"/>
+        
+      <!--
+       OVERRIDDEN BY NEW WIZARD
         <menuitem action="action_account_analytic_account_tree2" id="account_analytic_chart" parent="account.menu_finance_charts"/>
+        -->
 
+               <wizard id="action_analytic_account_chart" menu="False" model="account.analytic.account" name="account.analytic.line1" string="Analytic Chart of Accounts"/>
+        
+               <menuitem type="wizard" icon="STOCK_INDENT" action="action_analytic_account_chart" id="account_analytic_chart" parent="account.menu_finance_charts" name="Analytic Account lines"/>
+        
                <record id="analytic_account_form" model="ir.actions.act_window">
             <field name="name">New Analytic Account</field>
             <field name="res_model">account.analytic.account</field>
index 477e526..66cce97 100644 (file)
@@ -35,6 +35,7 @@ import wizard_account_analytic_cost_ledger_report
 import wizard_account_analytic_cost_ledger_for_journal_report
 import wizard_account_analytic_analytic_check
 import wizard_account_analytic_line
+import wizard_account_analytic_line1
 
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
 
diff --git a/addons/account/project/wizard/wizard_account_analytic_line1.py b/addons/account/project/wizard/wizard_account_analytic_line1.py
new file mode 100644 (file)
index 0000000..c8e0d39
--- /dev/null
@@ -0,0 +1,83 @@
+# -*- 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 wizard
+import pooler
+import time
+
+def _action_open_window(self, cr, uid, data, context): 
+    domain=[]
+    cr.execute('select id,name from ir_ui_view where name=%s and type=%s', ('account.analytic.account.tree', 'tree'))
+    view_res = cr.fetchone()
+    return {
+        'name': 'Analytic Entries',
+        'view_type': 'tree',
+        "view_mode": 'tree,form',
+        'res_model': 'account.analytic.account',
+        'type': 'ir.actions.act_window',
+        'view_id' : view_res,
+        'domain' :[('parent_id','=',False)],
+        'context':{'date_start':data['form']['from_date'],'date_stop':data['form']['to_date']},
+        }
+
+
+class account_analytic_line1(wizard.interface):
+    form1 = '''<?xml version="1.0"?>
+    <form string="View Account Analytic Lines">
+        <separator string="Account Analytic Lines Analysis" colspan="4"/>
+        <field name="from_date"/>
+        <newline/>
+        <field name="to_date"/>
+        <newline/>
+        <label string=""/>
+        <label string="(Keep empty to open the current situation)" align="0.0" colspan="3"/>
+    </form>'''
+    form1_fields = {
+             'from_date': {
+                'string': 'From',
+                'type': 'date',
+        },
+             'to_date': {
+                'string': 'To',
+                'type': 'date',
+        },
+    }
+
+    states = {
+      'init': {
+            'actions': [],
+            'result': {'type': 'form', 'arch':form1, 'fields':form1_fields, 'state': [('end', 'Cancel','gtk-cancel'),('open', 'Open Entries','gtk-ok')]}
+        },
+    'open': {
+            'actions': [],
+            'result': {'type': 'action', 'action': _action_open_window, 'state':'end'}
+        }
+    }
+account_analytic_line1('account.analytic.line1')
index 9b26240..e613909 100644 (file)
@@ -766,6 +766,18 @@ class mrp_procurement(osv.osv):
         'close_move': lambda *a: 0,
         'procure_method': lambda *a: 'make_to_order',
     }
+    
+    def unlink(self, cr, uid, ids):
+        procurements = self.read(cr, uid, ids, ['state'])
+        unlink_ids = []
+        for s in procurements:
+            if s['state'] in ['draft','cancel']:
+                unlink_ids.append(s['id'])
+            else:
+                raise osv.except_osv(_('Invalid action !'), _('Cannot delete Procurement Order(s) which are in %s State!' % s['state']))
+        osv.osv.unlink(self, cr, uid, unlink_ids)
+        return True
+    
     def check_product(self, cr, uid, ids):
         for procurement in self.browse(cr, uid, ids):
             if procurement.product_id.type in ('product', 'consu'):
diff --git a/addons/process/example/sale_order.pdf b/addons/process/example/sale_order.pdf
deleted file mode 100644 (file)
index c7ce2b9..0000000
Binary files a/addons/process/example/sale_order.pdf and /dev/null differ
diff --git a/addons/process/processus_report.xml b/addons/process/processus_report.xml
deleted file mode 100644 (file)
index 99e7545..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<terp>
-    <data>
-        <report id="report_processus"
-            model="processus.processus"
-            name="processus.processus.print"
-            string="Print Processus"/>
-    </data>
-</terp>
-
diff --git a/addons/process/report/__init__.py b/addons/process/report/__init__.py
deleted file mode 100644 (file)
index b11db3a..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- encoding: utf-8 -*-
-##############################################################################
-#
-# Copyright (c) 2005-TODAY TINY SPRL. (http://tiny.be) All Rights Reserved.
-#
-# 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 report_processus
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
diff --git a/addons/process/report/ds.ttf b/addons/process/report/ds.ttf
deleted file mode 100644 (file)
index ffbce87..0000000
Binary files a/addons/process/report/ds.ttf and /dev/null differ
diff --git a/addons/process/report/gtk-help.png b/addons/process/report/gtk-help.png
deleted file mode 100644 (file)
index 791a108..0000000
Binary files a/addons/process/report/gtk-help.png and /dev/null differ
diff --git a/addons/process/report/gtk-new.png b/addons/process/report/gtk-new.png
deleted file mode 100644 (file)
index b679e03..0000000
Binary files a/addons/process/report/gtk-new.png and /dev/null differ
diff --git a/addons/process/report/gtk-open.png b/addons/process/report/gtk-open.png
deleted file mode 100644 (file)
index 79cfeda..0000000
Binary files a/addons/process/report/gtk-open.png and /dev/null differ
diff --git a/addons/process/report/gtk-print.png b/addons/process/report/gtk-print.png
deleted file mode 100644 (file)
index 3fb6742..0000000
Binary files a/addons/process/report/gtk-print.png and /dev/null differ
diff --git a/addons/process/report/processus_print.py b/addons/process/report/processus_print.py
deleted file mode 100644 (file)
index f7f6b83..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-# -*- encoding: utf-8 -*-
-import Image
-import ImageDraw
-import ImageFont
-import math
-
-import addons
-
-ROUNDED = 30
-BGCOLOR = (228,233,237)
-TITLECOLOR = (150,70,70)
-FONT = addons.get_module_resource('processus', 'report/sb.ttf')
-BOXSIZE = (160,120)
-
-size = 800,600
-
-class draw(object):
-    def _rounding_box(self, x, y, width, height, title=None, bgcolor=BGCOLOR):
-        d = ImageDraw.Draw(self.img)
-        DR = ROUNDED/2
-        d.polygon( (x+DR,y,x+width-DR,y,x+width,y+DR,x+width,y+height-DR,x+width-DR,y+height,x+DR,y+height,x,y+height-DR,x,y+DR), fill=bgcolor)
-        d.pieslice((x,y,x+ROUNDED,y+ROUNDED),180,270,fill=bgcolor)
-        d.pieslice((x+width-ROUNDED,y,x+width,y+ROUNDED),270,0,fill=title and TITLECOLOR or bgcolor)
-        d.pieslice((x+width-ROUNDED,y+height-ROUNDED,x+width,y+height),0,90,fill=bgcolor)
-        d.pieslice((x,y+height-ROUNDED,x+ROUNDED,y+height),90,180,fill=bgcolor)
-        if title:
-            d.polygon( (x+width/5, y, x+width-DR, y, x+width, y+DR, x+width, y+20, x+width/5+15, y+20), fill=TITLECOLOR)
-            self.draw_text(x+width/5+13, y+4, 10, title, (255,255,255), width*4/5-14)
-
-    def node(self, x, y, width, height, title=None, start_color=BGCOLOR):
-        self._rounding_box(x,y,BOXSIZE[0]-16,BOXSIZE[1], bgcolor=start_color)
-        self._rounding_box(x+12,y,BOXSIZE[0]-16,BOXSIZE[1], bgcolor=(255,255,255))
-        self._rounding_box(x+16,y,BOXSIZE[0]-16,BOXSIZE[1], title)
-
-    def angle(self, arrow):
-        if not arrow[1]-arrow[3]:
-            angle = 180
-        else:
-            angle = math.atan(-(arrow[2]-arrow[0]) / (arrow[1]-arrow[3])) * 180 / math.pi
-            angle = 270 - angle
-            if arrow[3]<arrow[1]:
-                angle = 180 + angle
-        return int(angle)
-
-    def arrow(self, arrow):
-        d = ImageDraw.Draw(self.img)
-        d.line(arrow, width=1, fill=(0,0,0))
-        angle = self.angle(arrow)
-        d.pieslice((arrow[2]-14,arrow[3]-14,arrow[2]+14,arrow[3]+14),angle-18,angle+18,fill=(0,0,0))
-
-    def draw_text(self, x, y, size, title, color=(155,255,255), maxlength=None, font_name=FONT, center=False):
-        d = ImageDraw.Draw(self.img)
-        font = ImageFont.truetype(font_name, size)
-        d.setfont(font)
-        size2 = d.textsize(title)
-        if maxlength:
-            fontsize = min(size, size * maxlength / size2[0])
-            font = ImageFont.truetype(font_name, fontsize)
-            d.setfont(font)
-        size = d.textsize(title)
-        if center:
-            x = x-size[0]/2
-        d.text( (x, y+(size2[1]-size[1])/2), title, color)
-
-    def arrow_role(self, node_from, node_to, role='Hello'):
-        d = ImageDraw.Draw(self.img)
-        x = (node_from[0] + node_to[0]) /2
-        y = (node_from[1] + node_to[1]) /2
-        angle = self.angle(node_from+node_to) + 105
-        d.pieslice((x-40,y-40,x+40,y+40),angle-5,angle+5,fill=(100,0,0))
-        d.pieslice((x-6,y-6,x+6,y+6),angle-7,angle+7,fill=(255,255,255))
-
-        print -180 + angle - 90
-        x = x + math.cos(angle * math.pi / 180) * 40
-        y = y + math.sin(angle * math.pi / 180) * 40
-        a,b = x,y
-        angle -= 120
-
-        x = x + math.cos(angle * math.pi / 180) * 20
-        y = y + math.sin(angle * math.pi / 180) * 20
-
-        d.line((a,b,x,y), width=5, fill=(100,0,0))
-        angle += 125
-        d.pieslice((x-30,y-30,x+30,y+30),angle-7,angle+7,fill=(100,0,0))
-
-        x = x + math.cos(angle * math.pi / 180) * 50
-        y = y + math.sin(angle * math.pi / 180) * 50
-        return (x,y)
-
-    def picture(self, x, y, fname):
-        img = Image.open(fname)
-        img2 = img.convert('RGBA')
-        self.img.paste(img2, (max(0,x-img.size[0]/2), max(0,y-img.size[1])), mask=img2)
-
-    def __init__(self, img):
-        self.img = img
-
-class graph(object):
-    def __init__(self, img):
-        self.draw = draw(img)
-
-    def intersect_one(self, start, stop):
-        if start[0] < stop[0]:
-            x1 = start[0] + BOXSIZE[0]/2 + 3
-        else:
-            x1 = start[0] - BOXSIZE[0]/2 - 3
-        if not start[0]-stop[0]:
-            y1 = 99999999999999
-        else:
-            y1 = start[1] - (start[1] - stop[1]) * (start[0]-x1) / (start[0] - stop[0])
-
-        if start[1] < stop[1]:
-            y2 = start[1] + BOXSIZE[1]/2 + 3
-        else:
-            y2 = start[1] - BOXSIZE[1]/2 - 3
-        if not start[1]-stop[1]:
-            x2 = 99999999999999
-        else:
-            x2 = start[0] - (start[0] - stop[0]) * (start[1]-y2) / (start[1] - stop[1])
-
-        if abs(start[0]-x1)+abs(start[1]-y1)<abs(start[0]-x2)+abs(y2-start[1]):
-            return (x1,y1)
-        return (x2,y2)
-
-    def intersect(self, start, stop):
-        s = self.intersect_one(start,stop)
-        s2 = self.intersect_one(stop,start)
-        return s+s2
-
-    def node(self, x, y, data, start_color=False):
-        self.draw.node(x,y,BOXSIZE[0], BOXSIZE[1], data.get('title','Unknown'), start_color and (255,125,125) or BGCOLOR)
-        self.draw.picture(x+35, y+BOXSIZE[1]-5, addons.get_module_resource('processus', 'report/gtk-help.png'))
-        if start_color:
-            self.draw.picture(x+65, y+BOXSIZE[1]-5, addons.get_module_resource('processus', 'report/gtk-open.png'))
-            self.draw.picture(x+95, y+BOXSIZE[1]-5, addons.get_module_resource('processus', 'report/gtk-print.png'))
-        y = y+25
-        menus = data.get('menu','').split('/')
-        while menus:
-            menu = menus.pop(0)
-            if menu:
-                if menus: menu=menu+' /'
-                self.draw.draw_text(x+23, y, 10, menu, color=(0,0,0), maxlength=BOXSIZE[0] - 25, 
-                    font_name=addons.get_module_resource('processus', 'report/ds.ttf'))
-                y+=15
-
-    def arrow_role(self, node_from, node_to, role='Hello'):
-        start = (node_from[0]+BOXSIZE[0]/2, node_from[1]+BOXSIZE[1]/2)
-        stop = (node_to[0]+BOXSIZE[0]/2, node_to[1]+BOXSIZE[1]/2)
-        (x,y) = self.draw.arrow_role(start, stop, role)
-        self.draw.picture(x, y-3, addons.get_module_resource('processus', 'report/role.png'))
-        self.draw.draw_text(x,y-3, 12, 'Salesman', color=(0,0,0), center=True)
-
-    def arrow(self, node_from, node_to):
-        start = (node_from[0]+BOXSIZE[0]/2, node_from[1]+BOXSIZE[1]/2)
-        stop = (node_to[0]+BOXSIZE[0]/2, node_to[1]+BOXSIZE[1]/2)
-        arrow = self.intersect(start,stop)
-        self.draw.arrow(arrow)
-
-if __name__=='__main__':
-    img = Image.new('RGB',size,'#ffffff')
-    g = graph(img)
-    g.node(50,100,{'title':'SALE AZER ORDER', 'menu':'Sales Management/Sales Orders/My Sales Order/My Open Sales Order'}, start_color=(200,100,100))
-    g.node(350,150,{'title':'SALE AZER AZE ORDER', 'menu':'Sales Management/Sales Orders/My Quotations'})
-    g.arrow((50,100),(350,150))
-
-    g.arrow_role((50,100),(350,150))
-
-    #img.show()
-    img.save('a.pdf')
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
diff --git a/addons/process/report/report_processus.py b/addons/process/report/report_processus.py
deleted file mode 100644 (file)
index 29468d2..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-# -*- encoding: utf-8 -*-
-##############################################################################
-#
-# Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved.
-#
-# $Id: print_instance.py 8595 2008-06-16 13:00:21Z stw $
-#
-# 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, os
-
-import netsvc
-import report,pooler,tools
-
-import processus_print
-import Image
-
-
-class report_graph_instance(object):
-    def __init__(self, cr, uid, ids, data):
-        current_object = 'sale.order'
-        pool = pooler.get_pool(cr.dbname)
-        for processus in pool.get('processus.processus').browse(cr, uid, ids):
-            nodes = {}
-            start = []
-            transitions = {}
-            for node in processus.node_ids:
-                nodes[node.id] = node
-                if node.flow_start:
-                    start.append(node.id)
-                for tr in node.transition_out:
-                    transitions[tr.id] = tr
-            g = tools.graph(nodes.keys(), map(lambda x: (x.node_from_id.id,x.node_to_id.id), transitions.values()))
-            g.process(start)
-            g.scale(250,250, 100, 10)
-
-            img = Image.new('RGB',(1024,768),'#ffffff')
-            g2 = processus_print.graph(img)
-            positions = g.result
-            for name,node in positions.items():
-                start_color = (nodes[name].model_id.model==current_object)
-                g2.node(node['y'],node['x'], {
-                    'title': nodes[name].name,
-                    'menu': nodes[name].menu_id.complete_name
-                }, start_color=start_color)
-            for name,transition in transitions.items():
-                if transition.transition_ids:
-                    g2.arrow_role((positions[transition.node_from_id.id]['y'], positions[transition.node_from_id.id]['x']),
-                        (positions[transition.node_to_id.id]['y'], positions[transition.node_to_id.id]['x']))
-                g2.arrow((positions[transition.node_from_id.id]['y'], positions[transition.node_from_id.id]['x']),
-                    (positions[transition.node_to_id.id]['y'], positions[transition.node_to_id.id]['x']))
-        img.save('/tmp/a.pdf')
-        self.result = file('/tmp/a.pdf').read()
-        self.done = True
-
-    def is_done(self):
-        return self.done
-
-    def get(self):
-        if self.done:
-            return self.result
-        else:
-            return None
-
-class report_graph(report.interface.report_int):
-    def __init__(self, name, table):
-        report.interface.report_int.__init__(self, name)
-        self.table = table
-
-    def result(self):
-        if self.obj.is_done():
-            return (True, self.obj.get(), 'pdf')
-        else:
-            return (False, False, False)
-
-    def create(self, cr, uid, ids, data, context={}):
-        self.obj = report_graph_instance(cr, uid, ids, data)
-        return (self.obj.get(), 'pdf')
-
-report_graph('report.processus.processus.print', 'processus.processus')
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
diff --git a/addons/process/report/role.png b/addons/process/report/role.png
deleted file mode 100644 (file)
index b221adc..0000000
Binary files a/addons/process/report/role.png and /dev/null differ
diff --git a/addons/process/report/sb.ttf b/addons/process/report/sb.ttf
deleted file mode 100644 (file)
index bdfff7b..0000000
Binary files a/addons/process/report/sb.ttf and /dev/null differ
index b3a9f77..8be135b 100644 (file)
@@ -271,6 +271,10 @@ class product_template(osv.osv):
             help='Coefficient to convert UOM to UOS\n'
             ' uom = uos * coeff'),
         'mes_type': fields.selection((('fixed', 'Fixed'), ('variable', 'Variable')), 'Measure Type', required=True),
+        'track_production' : fields.boolean('Track Production Lots' , help="Force to use a Production Lot number during Production"),
+        'track_incoming' : fields.boolean('Track Incomming Lots', help="Force to use a Production Lot number during Purchase"),
+        'track_outgoing' : fields.boolean('Track Outging Lots', help="Force to use a Production Lot number during Sale"),
+        'track_other' : fields.boolean('Track Lots', help="Force to use a Production Lot number during stock operations for traceability."),
         'seller_delay': fields.function(_calc_seller_delay, method=True, type='integer', string='Supplier Lead Time', help="This is the average delay in days between the purchase order confirmation and the reception of goods for this product and for the default supplier. It is used by the scheduler to order requests based on reordering delays."),
         'seller_ids': fields.one2many('product.supplierinfo', 'product_id', 'Partners'),
         'loc_rack': fields.char('Rack', size=16),
index ad35962..8d2a47f 100644 (file)
                                 <field groups="base.group_extended" name="product_manager" select="2"/>
                             </group>
 
-                            <group colspan="2" col="2" name="uom">
-                                <separator string="UOM" colspan="2"/>
+                            <group colspan="2" col="2" name="lot">
+                                <separator string="Lots" colspan="2"/>
+                                <group colspan="2" col="2" name="uom">
                                 <field name="uom_id" on_change="onchange_uom(uom_id,uom_po_id)"/>
                                 <field name="uom_po_id"/>
+                                </group>
+                                <group colspan="1" col="2" name="tracking1">
+                                <field name="track_production"/>
+                                <field name="track_incoming"/>
+                                </group>
+                                <group colspan="1" col="2" name="tracking2">
+                                <field name="track_outgoing"/>
+                                <field name="track_other"/>
+                                </group>
                             </group>
 
                             <group colspan="2" col="2" name="uos" groups="product.group_uos">
index 84074b0..7bbc109 100644 (file)
@@ -206,7 +206,18 @@ class purchase_order(osv.osv):
     _name = "purchase.order"
     _description = "Purchase order"
     _order = "name desc"
-
+    
+    def unlink(self, cr, uid, ids):
+        purchase_orders = self.read(cr, uid, ids, ['state'])
+        unlink_ids = []
+        for s in purchase_orders:
+            if s['state'] in ['draft','cancel']:
+                unlink_ids.append(s['id'])
+            else:
+                raise osv.except_osv(_('Invalid action !'), _('Cannot delete Purchase Order(s) which are in %s State!' % s['state']))
+        osv.osv.unlink(self, cr, uid, unlink_ids)
+        return True
+    
     def button_dummy(self, cr, uid, ids, context={}):
         return True
 
index 3bbc650..31dc3ce 100644 (file)
@@ -261,6 +261,17 @@ class sale_order(osv.osv):
     _order = 'name desc'
 
     # Form filling
+    def unlink(self, cr, uid, ids):
+        sale_orders = self.read(cr, uid, ids, ['state'])
+        unlink_ids = []
+        for s in sale_orders:
+            if s['state'] in ['draft','canceled']:
+                unlink_ids.append(s['id'])
+            else:
+                raise osv.except_osv(_('Invalid action !'), _('Cannot delete Sale Order(s) which are already confirmed !'))
+        osv.osv.unlink(self, cr, uid, unlink_ids)
+        return True
+    
     def onchange_shop_id(self, cr, uid, ids, shop_id):
         v={}
         if shop_id:
@@ -952,9 +963,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 (file)
index 0000000..1d6e7cb
--- /dev/null
@@ -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 (file)
index 0000000..2ec84f1
--- /dev/null
@@ -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 (file)
index 0000000..3f3a7ea
--- /dev/null
@@ -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 (file)
index 0000000..f537287
--- /dev/null
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+    
+         <record id="view_sale_delivery_form" model="ir.ui.view">
+            <field name="name">sale.delivery.form.inherit</field>
+            <field name="model">sale.order</field>
+            <field name="type">form</field>
+            <field name="inherit_id" ref="sale.view_order_form"/>
+            <field name="arch" type="xml">
+                <notebook>
+                    <page string="Deliveries" position="inside">
+                      <field colspan="4" mode="tree,from" name="delivery_line" nolabel="1" widget="one2many_list">
+                                <form string="Delivery Lines">
+                                       <field name="product_id"
+                                       />
+                                                                       <field name="product_qty"
+                                                                       />
+                                                                       <field name="product_uom"
+                                                                       />
+                                                                       <field name="packaging_id"
+                                                                       />
+                                                                       <field name="date_planned"/>
+                                                                       <field name="priority"/>
+                                                                       <separator colspan="4" string="Notes"/>
+                                                                       <field name="note" colspan="4" nolabel="1"/>
+                                </form>
+                                <tree string="Delivery Lines">
+                                       <field name="product_id"/>
+                                                                       <field name="product_qty"/>
+                                                                       <field name="product_uom"/>
+                                                                       <field name="packaging_id"/>
+                                                                       <field name="date_planned"/>
+                                                                       <field name="priority"/>
+                                                                       <field name="note"/>
+                                </tree> 
+                            </field>
+                </page>
+                </notebook>
+            </field>
+        </record>
+        
+    <record model="ir.ui.view" id="view_order_line_tree_inherited">
+               <field name="name">sale.order.line.form1</field>
+               <field name="model">sale.order.line</field>
+               <field name="type">tree</field>
+               <field name="inherit_id" ref="sale.view_order_line_tree"/>
+               <field name="arch" type="xml">
+                        <field name="price_subtotal" position="after">
+                                       <field name="deliveries"/>
+                       </field>
+               </field>
+       </record>
+       
+       
+       <record id="view_sale_delivery_form1" model="ir.ui.view">
+            <field name="name">sale.delivery.form.inherit1</field>
+            <field name="model">sale.order</field>
+            <field name="type">form</field>
+            <field name="inherit_id" ref="sale.view_order_form"/>
+            <field name="arch" type="xml">
+            <field name="price_subtotal" position="after">
+                               <field name="deliveries"/>
+            </field>
+            </field>
+        </record>
+       
+    </data>
+</openerp>
index f0c71c1..8f23a0d 100644 (file)
@@ -320,26 +320,34 @@ class stock_picking(osv.osv):
     _description = "Packing list"
     def _set_maximum_date(self, cr, uid, ids, name, value, arg, context):
         if not value: return False
+<<<<<<< TREE
+        for pick in self.browse(cr, uid, [ids], context):
+=======
         if isinstance(ids, (int, long)):
             ids=[ids]
         for pick in self.browse(cr, uid, ids, context):
+>>>>>>> MERGE-SOURCE
             cr.execute("""update stock_move set
                     date_planned=%s 
                 where
                     picking_id=%d and 
-                    (date_planned=%s or date_planned>%s)""", (value,pick.id,pick.max_date,value))
+                    (date_planned>%s)""", (value,pick.id,value))
         return True
 
     def _set_minimum_date(self, cr, uid, ids, name, value, arg, context):
         if not value: return False
+<<<<<<< TREE
+        for pick in self.browse(cr, uid,[ids], context):
+=======
         if isinstance(ids, (int, long)):
             ids=[ids]
         for pick in self.browse(cr, uid, ids, context):
+>>>>>>> MERGE-SOURCE
             cr.execute("""update stock_move set
                     date_planned=%s 
                 where
                     picking_id=%d and 
-                    (date_planned=%s or date_planned<%s)""", (value,pick.id,pick.min_date,value))
+                    (date_planned<%s)""", (value,pick.id,value))
         return True
 
     def get_min_max_date(self, cr, uid, ids, field_name, arg, context={}):
@@ -410,7 +418,17 @@ class stock_picking(osv.osv):
     #def copy(self, cr, uid, id, data=None, context={}):
     #    data = data or {}
     #    return super(stock_picking, self).copy(cr, uid, id, data, context)
-
+    def unlink(self, cr, uid, ids):
+        pickings = self.read(cr, uid, ids, ['state'])
+        unlink_ids = []
+        for s in pickings:
+            if s['state'] in ['draft','cancel']:
+                unlink_ids.append(s['id'])
+            else:
+                raise osv.except_osv(_('Invalid action !'), _('Cannot delete Picking(s) which are in %s State!' % s['state']))
+        osv.osv.unlink(self, cr, uid, unlink_ids)
+        return True
+    
     def onchange_partner_in(self, cr, uid, context, partner_id=None):
         sid = self.pool.get('res.partner.address').browse(cr, uid, partner_id, context).partner_id.property_stock_supplier.id
         return { }
@@ -872,6 +890,7 @@ class stock_move(osv.osv):
         'state': fields.selection([('draft','Draft'),('waiting','Waiting'),('confirmed','Confirmed'),('assigned','Assigned'),('done','Done'),('cancel','cancel')], 'Status', readonly=True, select=True),
         'price_unit': fields.float('Unit Price',
             digits=(16, int(config['price_accuracy']))),
+        'partner_id':fields.related('picking_id','address_id',type='many2one',relation='res.partner.address', string='Partner'),
     }
     
     _constraints = [
@@ -882,6 +901,17 @@ class stock_move(osv.osv):
             'You try to assign a lot which is not from the same product',
             ['prodlot_id'])]
     
+#    def unlink(self, cr, uid, ids):
+#        moves = self.read(cr, uid, ids, ['state'])
+#        unlink_ids = []
+#        for s in moves:
+#            if s['state'] in ['draft','cancel']:
+#                unlink_ids.append(s['id'])
+#            else:
+#                raise osv.except_osv(_('Invalid action !'), _('Cannot delete Stock Move(s) which are in %s State!' % s['state']))
+#        osv.osv.unlink(self, cr, uid, unlink_ids)
+#        return True
+    
     def _default_location_destination(self, cr, uid, context={}):
         if context.get('move_line', []):
             return context['move_line'][0][2]['location_dest_id']
index 5db7c28..59225c0 100644 (file)
                 <form string="Move Lines">
                     <field name="address_id" invisible="True" context="{'context_display':'partner'}"/>
                     <field name="picking_id" invisible="True"/>
-                    <field domain="[('picking_id','&lt;&gt;',picking_id),('state','in',['confirmed','assigned']),('picking_id.address_id','=',address_id)]" name="move_ids" nolabel="1"/><newline/>
+                    <field domain="[('picking_id','&lt;&gt;',picking_id),('state','in',['confirmed','assigned'])]" name="move_ids" select="1"/><newline/>
                     <group colspan="4">
                         <button special="cancel" string="Cancel"/>
                         <button name="action_move" string="Add" type="object"/>
             <field eval="'ir.actions.wizard,%d'%ref('location_product')" name="value"/>
             <field eval="True" name="object"/>                 
         </record>   
+
                
-             
-               
+             <record id="report_stock_latest_tree" model="ir.ui.view">
+            <field name="name">report.inventory.latest.view</field>
+            <field name="model">report.inventory.latest</field>
+            <field name="type">tree</field>
+            <field name="arch" type="xml">
+                <tree string="Latest inventories by product">
+                    <field name="product" select="1"/>
+                    <field name="qty" select="1"/>
+                    <field name="uom"/>
+                    <field name="inventory"/>
+                    <field name="name"/>
+                </tree>
+            </field>
+        </record>
+        
+        <record id="action_report_stock_latest_form" model="ir.actions.act_window">
+            <field name="name">Latest Inventories by product</field>
+            <field name="type">ir.actions.act_window</field>
+            <field name="res_model">report.inventory.latest</field>
+            <field name="view_type">form</field>
+            <field name="view_mode">tree</field>
+            <field name="domain">[('name','&gt;=',time.strftime('%Y-%m-01'))]</field>
+        </record>
+         <menuitem
+            id="next_id_61"
+            name="Reporting"
+            parent="stock.menu_stock_root"/>
+        <menuitem action="action_report_stock_latest_form" id="menu_report_stock_latest" parent="next_id_61"/>
+        
 
     </data>
 </openerp>