Merge lp:~unifield-team/unifield-addons/uf-108-default-supplier-suggestion into lp:unifield-addons

Proposed by Quentin THEURET @Amaris
Status: Rejected
Rejected by: jftempo
Proposed branch: lp:~unifield-team/unifield-addons/uf-108-default-supplier-suggestion
Merge into: lp:unifield-addons
Diff against target: 2254 lines (+872/-1096)
27 files modified
msf_partner/__init__.py (+0/-27)
msf_partner/__openerp__.py (+0/-49)
msf_partner/partner.py (+0/-45)
msf_partner/partner_demo.xml (+0/-46)
msf_partner/partner_view.xml (+0/-56)
msf_partner/product.py (+0/-38)
msf_partner/product_view.xml (+0/-31)
msf_partner/test/msf_partner.yml (+0/-18)
procurement_list/__init__.py (+1/-0)
procurement_list/__openerp__.py (+3/-0)
procurement_list/partner.py (+92/-0)
procurement_list/partner_view.xml (+27/-0)
procurement_list/procurement_list.py (+123/-36)
procurement_list/procurement_list_view.xml (+12/-4)
procurement_list/security/ir.model.access.csv (+1/-1)
procurement_list/test/procurement_list.yml (+312/-65)
procurement_list/wizard/__init__.py (+1/-0)
procurement_list/wizard/choose_supplier.py (+241/-0)
procurement_list/wizard/choose_supplier_view.xml (+59/-0)
stock_inventory_type/__init__.py (+0/-28)
stock_inventory_type/__openerp__.py (+0/-49)
stock_inventory_type/security/ir.model.access.csv (+0/-2)
stock_inventory_type/stock.py (+0/-135)
stock_inventory_type/stock_data.xml (+0/-23)
stock_inventory_type/stock_move_report.py (+0/-130)
stock_inventory_type/stock_view.xml (+0/-196)
stock_inventory_type/test/adjustment_type.yml (+0/-117)
To merge this branch: bzr merge lp:~unifield-team/unifield-addons/uf-108-default-supplier-suggestion
Reviewer Review Type Date Requested Status
jftempo Needs Fixing
Review via email: mp+53861@code.launchpad.net
To post a comment you must log in.
Revision history for this message
jftempo (jfb-tempo-consulting) wrote :

Please set supplier selection on procurement.list.line and move buttons "create_rfq", "create_po" from procurement.choose.supplier to procurement.list.

review: Needs Fixing
4473. By Quentin THEURET <quentin@tempo-quentin>

UF-108: [IMP] Set supplier selection on procurement.list.line and move buttons create_rfq, create_po from procurement.choose.supplier to procurement.list

Unmerged revisions

4473. By Quentin THEURET <quentin@tempo-quentin>

UF-108: [IMP] Set supplier selection on procurement.list.line and move buttons create_rfq, create_po from procurement.choose.supplier to procurement.list

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== removed directory 'msf_partner'
=== removed file 'msf_partner/__init__.py'
--- msf_partner/__init__.py 2011-03-15 15:01:14 +0000
+++ msf_partner/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,27 +0,0 @@
1#!/usr/bin/env python
2# -*- encoding: utf-8 -*-
3##############################################################################
4#
5# OpenERP, Open Source Management Solution
6# Copyright (C) 2011 TeMPO Consulting, MSF
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23import partner
24import product
25
26# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
27
280
=== removed file 'msf_partner/__openerp__.py'
--- msf_partner/__openerp__.py 2011-03-15 15:01:14 +0000
+++ msf_partner/__openerp__.py 1970-01-01 00:00:00 +0000
@@ -1,49 +0,0 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Management Solution
5# Copyright (C) 2011 TeMPO Consulting, MSF
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21{
22 "name" : "MSF Partners",
23 "version" : "1.0",
24 "author" : "TeMPO Consulting, MSF",
25 "category": "Others",
26 "description": """
27 This modules aims to differentiate Internal/External partners
28 It also aims to create a new type of partner: Manufacturer
29 """,
30 "website": "http://unifield.msf.org",
31 "init_xml": [
32 ],
33 "depends" : [
34 "base",
35 "product",
36 ],
37 "update_xml": [
38 "partner_view.xml",
39 "product_view.xml",
40 ],
41 "demo_xml": [
42 "partner_demo.xml",
43 ],
44 "test": [
45 "test/msf_partner.yml",
46 ],
47 "installable": True,
48 "active": False,
49}
500
=== removed file 'msf_partner/partner.py'
--- msf_partner/partner.py 2011-03-15 15:01:14 +0000
+++ msf_partner/partner.py 1970-01-01 00:00:00 +0000
@@ -1,45 +0,0 @@
1#!/usr/bin/env python
2# -*- encoding: utf-8 -*-
3##############################################################################
4#
5# OpenERP, Open Source Management Solution
6# Copyright (C) 2011 TeMPO Consulting, MSF
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from osv import osv
24from osv import fields
25
26
27class res_partner(osv.osv):
28 _name = 'res.partner'
29 _inherit = 'res.partner'
30
31 _columns = {
32 'manufacturer': fields.boolean(string='Manufacturer', help='Check this box if the partner is a manufacturer'),
33 'partner_type': fields.selection([('internal', 'Internal'), ('section', 'Inter-section'),
34 ('external', 'External')], string='Partner type', required=True),
35 }
36
37 _defaults = {
38 'manufacturer': lambda *a: False,
39 'partner_type': lambda *a: 'internal',
40 }
41
42res_partner()
43
44# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
45
460
=== removed file 'msf_partner/partner_demo.xml'
--- msf_partner/partner_demo.xml 2011-03-15 14:05:12 +0000
+++ msf_partner/partner_demo.xml 1970-01-01 00:00:00 +0000
@@ -1,46 +0,0 @@
1<?xml version="1.0" encoding="utf-8" ?>
2<openerp>
3 <data noupdate="0">
4
5 <record id="base.res_partner_desertic_hispafuentes" model="res.partner">
6 <field name="manufacturer">1</field>
7 <field name="partner_type">section</field>
8 </record>
9
10 <record id="base.res_partner_tinyatwork" model="res.partner">
11 <field name="manufacturer">1</field>
12 </record>
13
14 <record id="base.res_partner_asus" model="res.partner">
15 <field name="partner_type">external</field>
16 </record>
17 <record id="base.res_partner_agrolait" model="res.partner">
18 <field name="partner_type">external</field>
19 </record>
20 <record id="base.res_partner_c2c" model="res.partner">
21 <field name="partner_type">section</field>
22 </record>
23 <record id="base.res_partner_sednacom" model="res.partner">
24 <field name="partner_type">internal</field>
25 </record>
26 <record id="base.res_partner_thymbra" model="res.partner">
27 <field name="partner_type">internal</field>
28 </record>
29
30 <record id="product.supplierinfo10" model="product.supplierinfo">
31 <field name="manufacturer_id" ref="base.res_partner_tinyatwork" />
32 </record>
33
34 <record id="product.supplierinfo11" model="product.supplierinfo">
35 <field name="manufacturer_id" ref="base.res_partner_tinyatwork" />
36 </record>
37
38 <record id="product.supplierinfo6" model="product.supplierinfo">
39 <field name="manufacturer_id" ref="base.res_partner_desertic_hispafuentes" />
40 </record>
41
42 <record id="product.supplierinfo7" model="product.supplierinfo">
43 <field name="manufacturer_id" ref="base.res_partner_tinyatwork" />
44 </record>
45 </data>
46</openerp>
470
=== removed file 'msf_partner/partner_view.xml'
--- msf_partner/partner_view.xml 2011-03-15 15:01:14 +0000
+++ msf_partner/partner_view.xml 1970-01-01 00:00:00 +0000
@@ -1,56 +0,0 @@
1<?xml version="1.0" encoding="utf-8" ?>
2<openerp>
3 <data>
4
5 <record id="msf_view_partner_tree" model="ir.ui.view">
6 <field name="name">msf.view.partner.tree</field>
7 <field name="model">res.partner</field>
8 <field name="type">tree</field>
9 <field name="inherit_id" ref="base.view_partner_tree" />
10 <field name="arch" type="xml">
11 <xpath expr="/tree/field[@name='ref']" position="after">
12 <field name="partner_type" />
13 </xpath>
14 </field>
15 </record>
16
17 <record id="msf_view_partner_form" model="ir.ui.view">
18 <field name="name">msf.view.partner.form</field>
19 <field name="model">res.partner</field>
20 <field name="type">form</field>
21 <field name="inherit_id" ref="base.view_partner_form" />
22 <field name="arch" type="xml">
23 <data>
24 <xpath expr="/form/group/group/field[@name='title']" position="replace">
25 <field name="partner_type" />
26 </xpath>
27 <xpath expr="/form/group/group[2]/field[@name='supplier']" position="after">
28 <field name="manufacturer" />
29 </xpath>
30 </data>
31 </field>
32 </record>
33
34 <record id="msf_view_res_partner_filter" model="ir.ui.view">
35 <field name="name">msf.view.res.partner.filter</field>
36 <field name="model">res.partner</field>
37 <field name="type">search</field>
38 <field name="inherit_id" ref="base.view_res_partner_filter" />
39 <field name="arch" type="xml">
40 <data>
41 <xpath expr="/search/group/filter[@name='supplier']" position="after">
42 <filter string="Manufacturers" name="manufacturer" icon="terp-personal" domain="[('manufacturer','=',1)]" help="Manufacturer Partners"/>
43 </xpath>
44 <xpath expr="/search/group/field[@name='name']" position="before">
45 <filter string="Internal" name="internal" icon="gtk-leave-fullscreen" domain="[('partner_type','=','internal')]" help="Internal Partners"/>
46 <filter string="Inter-section" name="inter-section" icon="gtk-refresh" domain="[('partner_type','=','section')]" help="Inter-section Partners"/>
47 <filter string="External" name="external" icon="gtk-quit" domain="[('partner_type','=','external')]" help="External Partners"/>
48 <separator orientation="vertical" />
49 </xpath>
50 </data>
51 </field>
52 </record>
53
54 </data>
55</openerp>
56
570
=== removed file 'msf_partner/product.py'
--- msf_partner/product.py 2011-03-15 15:01:14 +0000
+++ msf_partner/product.py 1970-01-01 00:00:00 +0000
@@ -1,38 +0,0 @@
1#!/usr/bin/env python
2# -*- encoding: utf-8 -*-
3##############################################################################
4#
5# OpenERP, Open Source Management Solution
6# Copyright (C) 2011 TeMPO Consulting, MSF
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from osv import osv
24from osv import fields
25
26
27class product_supplierinfo(osv.osv):
28 _name = 'product.supplierinfo'
29 _inherit = 'product.supplierinfo'
30
31 _columns = {
32 'manufacturer_id': fields.many2one('res.partner', string='Manufacturer', domain=[('manufacturer', '=', 1)]),
33 }
34
35product_supplierinfo()
36
37# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
38
390
=== removed file 'msf_partner/product_view.xml'
--- msf_partner/product_view.xml 2011-03-10 09:07:17 +0000
+++ msf_partner/product_view.xml 1970-01-01 00:00:00 +0000
@@ -1,31 +0,0 @@
1<?xml version="1.0" encoding="utf-8" ?>
2<openerp>
3 <data>
4
5 <record id="manufacturer_supplierinfo_form_view" model="ir.ui.view">
6 <field name="name">manufacture.supplierinfo.form.view</field>
7 <field name="model">product.supplierinfo</field>
8 <field name="type">form</field>
9 <field name="inherit_id" ref="product.product_supplierinfo_form_view" />
10 <field name="arch" type="xml">
11 <xpath expr="/form/field[@name='product_code']" position="after">
12 <field name="manufacturer_id" />
13 </xpath>
14 </field>
15 </record>
16
17 <record id="manufacturer_supplierinfo_tree_view" model="ir.ui.view">
18 <field name="name">manufacturer.supplierinfo.tree.view</field>
19 <field name="model">product.supplierinfo</field>
20 <field name="type">tree</field>
21 <field name="inherit_id" ref="product.product_supplierinfo_tree_view" />
22 <field name="arch" type="xml">
23 <xpath expr="/tree/field[@name='min_qty']" position="after">
24 <field name="manufacturer_id" />
25 </xpath>
26 </field>
27 </record>
28
29 </data>
30</openerp>
31
320
=== removed directory 'msf_partner/test'
=== removed file 'msf_partner/test/msf_partner.yml'
--- msf_partner/test/msf_partner.yml 2011-03-15 15:01:14 +0000
+++ msf_partner/test/msf_partner.yml 1970-01-01 00:00:00 +0000
@@ -1,18 +0,0 @@
1-
2 In order to test the module msf_partne, I will create a partner
3 and check that the default values are well applied.
4-
5 I create the first partner
6-
7 !record {model: res.partner, id: partner1}:
8 name: A
9 supplier: 1
10 customer: 1
11 address:
12 - name: A
13-
14 I check if the default values are good
15-
16 !assert {model: res.partner, id: partner1}:
17 - partner_type == 'internal', "Default value 'internal' for partner_type is not applied"
18 - manufacturer == 0, "Default value 'False' for manufacturer is not applied"
190
=== modified file 'procurement_list/__init__.py'
--- procurement_list/__init__.py 2011-03-16 13:17:54 +0000
+++ procurement_list/__init__.py 2011-03-24 15:56:19 +0000
@@ -20,6 +20,7 @@
20##############################################################################20##############################################################################
2121
22import procurement_list22import procurement_list
23import partner
23import wizard24import wizard
2425
25# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:26# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
2627
=== modified file 'procurement_list/__openerp__.py'
--- procurement_list/__openerp__.py 2011-03-16 18:18:33 +0000
+++ procurement_list/__openerp__.py 2011-03-24 15:56:19 +0000
@@ -32,13 +32,16 @@
32 'init_xml': [32 'init_xml': [
33 ],33 ],
34 'depends' : [34 'depends' : [
35 'base',
35 'purchase',36 'purchase',
36 ],37 ],
37 'update_xml': [38 'update_xml': [
38 'procurement_list_sequence.xml',39 'procurement_list_sequence.xml',
39 'procurement_list_view.xml',40 'procurement_list_view.xml',
41 'partner_view.xml',
40 'procurement_list_wizard.xml',42 'procurement_list_wizard.xml',
41 'wizard/wizard_import_list_view.xml',43 'wizard/wizard_import_list_view.xml',
44 'wizard/choose_supplier_view.xml',
42 'security/ir.model.access.csv',45 'security/ir.model.access.csv',
43 ],46 ],
44 'demo_xml': [47 'demo_xml': [
4548
=== added file 'procurement_list/partner.py'
--- procurement_list/partner.py 1970-01-01 00:00:00 +0000
+++ procurement_list/partner.py 2011-03-24 15:56:19 +0000
@@ -0,0 +1,92 @@
1#!/usr/bin/env python
2# -*- encoding: utf-8 -*-
3##############################################################################
4#
5# OpenERP, Open Source Management Solution
6# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from osv import osv
24from osv import fields
25
26class res_partner(osv.osv):
27 _name= 'res.partner'
28 _inherit = 'res.partner'
29
30 _order = 'name'
31
32 def _set_in_product(self, cr, uid, ids, field_name, arg, context={}):
33 '''
34 Returns according to the context if the partner is in product form
35 '''
36 res = {}
37
38 product_obj = self.pool.get('product.product')
39
40 # If we aren't in the context of choose supplier on procurement list
41 if not context.get('product_id', False) or 'choose_supplier' not in context:
42 for i in ids:
43 res[i] = False
44 else:
45 product = product_obj.browse(cr, uid, context.get('product_id'))
46 seller_ids = []
47 # Get all suppliers defined on product form
48 for s in product.seller_ids:
49 seller_ids.append(s.name.id)
50 # Check if the partner is in product form
51 for i in ids:
52 if i in seller_ids:
53 res[i] = True
54 else:
55 res[i] = False
56
57 return res
58
59 _columns = {
60 'in_product': fields.function(_set_in_product, string='In product', type="boolean", readonly=True, method=True),
61 }
62
63 def read(self, cr, uid, ids, fields=None, context={}, load='_classic_read'):
64 '''
65 Sort the supplier according to the context
66 '''
67 res = super(res_partner, self).read(cr, uid, ids, fields, context=context, load=load)
68 # If we are in the context of choose supplier on procurement list
69 if context.get('product_id', False) and 'choose_supplier' in context:
70 # Add in_product field in read
71 if not 'in_product' in fields:
72 fields.append('in_product')
73
74 seller_ids =[]
75 not_seller_ids = []
76
77 for r in res:
78 if r.get('in_product', False):
79 seller_ids.append(r)
80 else:
81 not_seller_ids.append(r)
82
83 result = seller_ids + not_seller_ids
84 else:
85 result = res
86
87 return result
88
89res_partner()
90
91# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
92
093
=== added file 'procurement_list/partner_view.xml'
--- procurement_list/partner_view.xml 1970-01-01 00:00:00 +0000
+++ procurement_list/partner_view.xml 2011-03-24 15:56:19 +0000
@@ -0,0 +1,27 @@
1<?xml version="1.0" encoding="utf-8" ?>
2<openerp>
3 <data>
4
5 <record id="in_product_view_partner_tree" model="ir.ui.view">
6 <field name="name">in.product.view.partner.tree</field>
7 <field name="model">res.partner</field>
8 <field name="type">tree</field>
9 <field name="inherit_id" ref="base.view_partner_tree" />
10 <field name="arch" type="xml">
11 <xpath expr="/tree" position="replace">
12 <tree string="Partners" colors="red:in_product==True">
13 <field name="name" />
14 <field name="ref" groups="base.group_extended" />
15 <field name="phone" />
16 <field name="email" />
17 <field name="city" />
18 <field name="country" />
19 <field name="user_id" />
20 <field name="in_product" invisible="1" />
21 </tree>
22 </xpath>
23 </field>
24 </record>
25
26 </data>
27</openerp>
0\ No newline at end of file28\ No newline at end of file
129
=== modified file 'procurement_list/procurement_list.py'
--- procurement_list/procurement_list.py 2011-03-16 18:05:16 +0000
+++ procurement_list/procurement_list.py 2011-03-24 15:56:19 +0000
@@ -43,10 +43,6 @@
43 'line_ids': fields.one2many('procurement.list.line', 'list_id', string='Lines', readonly=True,43 'line_ids': fields.one2many('procurement.list.line', 'list_id', string='Lines', readonly=True,
44 states={'draft': [('readonly', False)]}),44 states={'draft': [('readonly', False)]}),
45 'notes': fields.text(string='Notes'),45 'notes': fields.text(string='Notes'),
46 'supplier_ids': fields.many2many('res.partner', 'procurement_list_supplier_rel',
47 'list_id', 'supplier_id', string='Suppliers',
48 domain="[('supplier', '=', True)]",
49 states={'done': [('readonly', True)]}),
50 'order_ids': fields.many2many('purchase.order', 'procurement_list_order_rel',46 'order_ids': fields.many2many('purchase.order', 'procurement_list_order_rel',
51 'list_id', 'order_id', string='Orders', readonly=True),47 'list_id', 'order_id', string='Orders', readonly=True),
52 }48 }
@@ -75,6 +71,82 @@
75 self.write(cr, uid, ids, {'state': 'cancel'})71 self.write(cr, uid, ids, {'state': 'cancel'})
7672
77 return True73 return True
74
75 def create_po(self, cr, uid, ids, context={}):
76 '''
77 Creates all purchase orders according to choices on lines
78 '''
79 if ids and isinstance(ids, (int, long)):
80 ids = [ids]
81
82 order_obj = self.pool.get('purchase.order')
83 order_line_obj = self.pool.get('purchase.order.line')
84 proc_obj = self.pool.get('procurement.list')
85 line_obj = self.pool.get('procurement.list.line')
86 prod_sup_obj = self.pool.get('product.supplierinfo')
87
88 # We search if at least one line hasn't defined supplier
89 for list in self.browse(cr, uid, ids):
90 for line in list.line_ids:
91 if not line.supplier_id:
92 raise osv.except_osv(_('Error'), _('You cannot create purchase orders while all lines haven\'t a defined supplier'))
93
94 # We search lines group by supplier_id
95 po_exists = {}
96 po_id = False
97 po_ids = []
98 line_ids = line_obj.search(cr, uid, [('list_id', 'in', ids)], order='supplier_id')
99 for l in line_obj.browse(cr, uid, line_ids):
100 # Search if a PO already exists in the system
101 if not po_exists.get(l.supplier_id.id, False):
102 # If no PO in local memory, search in DB
103 po_exist = order_obj.search(cr, uid, [('origin', '=', l.list_id.name), ('partner_id', '=', l.supplier_id.id)])
104 if po_exist:
105 # A PO exists in DB, set the id in local memory
106 po_exists[l.supplier_id.id] = po_exist[0]
107 else:
108 # try to create a new PO, and set its id in local memory
109 address = l.supplier_id.address_get().get('default')
110 # Returns an error when the supplier has not defined address
111 if not address:
112 raise osv.except_osv(_('Error'), _('The supplier %s has no address defined on its form' %l.supplier_id.name))
113 # When starting or when the supplier changed, we create a Purchase Order
114 po_id = order_obj.create(cr, uid, {'partner_id': l.supplier_id.id,
115 'partner_address_id': address,
116 'pricelist_id': l.supplier_id.property_product_pricelist.id,
117 'origin': l.list_id.name,
118 'location_id': proc_obj._get_location(cr, uid, l.list_id.warehouse_id)})
119 po_exists[l.supplier_id.id] = po_id
120
121 # Get the PO id in local memory
122 po_id = po_exists.get(l.supplier_id.id)
123
124 # We create all lines for this supplier
125 price_unit = prod_sup_obj.price_get(cr, uid, [l.supplier_id.id], l.product_id.id, l.product_qty)
126 order_line_obj.create(cr, uid, {'product_uom': l.product_uom_id.id,
127 'product_id': l.product_id.id,
128 'order_id': po_id,
129 'price_unit': price_unit[l.supplier_id.id],
130 'date_planned': l.list_id.order_date,
131 'product_qty': l.product_qty,
132 'name': l.product_id.name,})
133
134 for supplier in po_exists:
135 po_ids.append(po_exists.get(supplier))
136
137 # We confirm all created orders
138 wf_service = netsvc.LocalService("workflow")
139 for po in po_ids:
140 wf_service.trg_validate(uid, 'purchase.order', po, 'purchase_confirm', cr)
141
142 proc_obj.write(cr, uid, ids[0], {'state': 'done', 'order_ids': [(6, 0, po_ids)]})
143
144 return {'type': 'ir.actions.act_window',
145 'res_model': 'purchase.order',
146 'view_type': 'form',
147 'view_mode': 'tree,form',
148 'domain': [('id', 'in', po_ids)],
149 }
78150
79 def create_rfq(self, cr, uid, ids, context={}):151 def create_rfq(self, cr, uid, ids, context={}):
80 ''' 152 '''
@@ -86,43 +158,21 @@
86 order_ids = []158 order_ids = []
87159
88 for list in self.browse(cr, uid, ids, context=context):160 for list in self.browse(cr, uid, ids, context=context):
89 # Returns an error message if no suppliers or no products161 # Returns an error message if no products defined
90 if not list.supplier_ids or len(list.supplier_ids) == 0:
91 raise osv.except_osv(_('Error'), _('No supplier defined for this list !'))
92 if not list.line_ids or len(list.line_ids) == 0:162 if not list.line_ids or len(list.line_ids) == 0:
93 raise osv.except_osv(_('Error'), _('No line defined for this list !'))163 raise osv.except_osv(_('Error'), _('No line defined for this list !'))
94164
95 location_id = self._get_location(cr, uid, list.warehouse_id)165 location_id = self._get_location(cr, uid, list.warehouse_id)
96 # Creates a RfQ for each supplier...166
97 for supplier in list.supplier_ids:167 context['active_ids'] = ids
98 po_id = purchase_obj.create(cr, uid, {'partner_id': supplier.id,168 context['active_id'] = ids[0]
99 'partner_address_id': supplier.address_get().get('default'),
100 'pricelist_id': supplier.property_product_pricelist.id,
101 'origin': list.name,
102 'location_id': location_id})
103 order_ids.append(po_id)
104
105 # ... with all lines...
106 for line in list.line_ids:
107 # ... which aren't from stock
108 if not line.from_stock:
109 line_obj.create(cr, uid, {'product_uom': line.product_uom_id.id,
110 'product_id': line.product_id.id,
111 'order_id': po_id,
112 'price_unit': 0.00,
113 'date_planned': list.order_date,
114 'product_qty': line.product_qty,
115 'procurement_line_id': line.id,
116 'name': line.product_id.name,})
117 self.pool.get('procurement.list.line').write(cr, uid, line.id, {'latest': 'RfQ In Progress'})
118
119 self.write(cr, uid, ids, {'state': 'done', 'order_ids': [(6, 0, order_ids)]})
120169
121 return {'type': 'ir.actions.act_window',170 return {'type': 'ir.actions.act_window',
122 'res_model': 'purchase.order',171 'res_model': 'procurement.choose.supplier.rfq',
172 'target': 'new',
123 'view_type': 'form',173 'view_type': 'form',
124 'view_mode': 'tree,form',174 'view_mode': 'form',
125 'domain': [('id', 'in', order_ids)]}175 'context': context}
126176
127 def reset(self, cr, uid, ids, context={}):177 def reset(self, cr, uid, ids, context={}):
128 '''178 '''
@@ -158,6 +208,7 @@
158 'from_stock': fields.boolean(string='From stock ?'),208 'from_stock': fields.boolean(string='From stock ?'),
159 'latest': fields.char(size=64, string='Latest document', readonly=True),209 'latest': fields.char(size=64, string='Latest document', readonly=True),
160 'list_id': fields.many2one('procurement.list', string='List', required=True, ondelete='cascade'),210 'list_id': fields.many2one('procurement.list', string='List', required=True, ondelete='cascade'),
211 'supplier_id': fields.many2one('res.partner', string='Supplier'),
161 }212 }
162 213
163 _defaults = {214 _defaults = {
@@ -183,12 +234,48 @@
183234
184 v = {}235 v = {}
185 if not product_id:236 if not product_id:
186 v.update({'product_uom_id': False})237 v.update({'product_uom_id': False, 'supplier_id': False})
187 else:238 else:
188 product = product_obj.browse(cr, uid, product_id, context=context)239 product = product_obj.browse(cr, uid, product_id, context=context)
189 v.update({'product_uom_id': product.uom_id.id})240 v.update({'product_uom_id': product.uom_id.id, 'supplier_id': product.seller_id.id})
190241
191 return {'value': v}242 return {'value': v}
243
244
245 def split_line(self, cr, uid, ids, context={}):
246 '''
247 Split a line into two lines
248 '''
249 if ids and isinstance(ids, (int, long)):
250 ids = [ids]
251 for line in self.browse(cr, uid, ids):
252 state = line.list_id.state
253 context.update({'line_id': ids[0], 'state': state})
254 return {'type': 'ir.actions.act_window',
255 'res_model': 'procurement.list.line.split',
256 'target': 'new',
257 'view_type': 'form',
258 'view_mode': 'form',
259 'context': context,
260 }
261
262 def merge_line(self, cr, uid, ids, context={}):
263 '''
264 Merges two lines
265 '''
266 if ids and isinstance(ids, (int, long)):
267 ids = [ids]
268 for line in self.browse(cr, uid, ids):
269 state = line.list_id.state
270 context.update({'line_id': ids[0], 'state': state})
271
272 return {'type': 'ir.actions.act_window',
273 'res_model': 'procurement.list.line.merge',
274 'target': 'new',
275 'view_type': 'form',
276 'view_mode': 'form',
277 'context': context,
278 }
192279
193procurement_list_line()280procurement_list_line()
194281
195282
=== modified file 'procurement_list/procurement_list_view.xml'
--- procurement_list/procurement_list_view.xml 2011-03-15 16:28:59 +0000
+++ procurement_list/procurement_list_view.xml 2011-03-24 15:56:19 +0000
@@ -1,6 +1,13 @@
1<?xml version="1.0" encoding="utf-8" ?>1<?xml version="1.0" encoding="utf-8" ?>
2<openerp>2<openerp>
3 <data>3 <data>
4
5 <record id="action_choose_supplier" model="ir.actions.server">
6 <field name="name">Choose Supplier</field>
7 <field name="model_id" ref="model_procurement_choose_supplier"/>
8 <field name="state">code</field>
9 <field name="code">action = obj.start_choose_supplier(context=context)</field>
10 </record>
411
5 <record id="procurement_list_form_view" model="ir.ui.view">12 <record id="procurement_list_form_view" model="ir.ui.view">
6 <field name="name">procurement.list.form.view</field>13 <field name="name">procurement.list.form.view</field>
@@ -25,18 +32,19 @@
25 <field name="comment" />32 <field name="comment" />
26 <field name="from_stock" />33 <field name="from_stock" />
27 <field name="latest" />34 <field name="latest" />
35 <field name="supplier_id" context="{'product_id': product_id, 'choose_supplier': True}" />
36 <button name="split_line" type="object" string="Split Line" icon="terp-stock_effects-object-colorize" />
37 <button name="merge_line" type="object" string="Merge Line" icon="terp-gtk-jump-to-ltr" context="{'wizard_id': active_id}" />
28 </tree>38 </tree>
29 </field>39 </field>
30 <group colspan="4" col="6">40 <group colspan="4" col="6">
31 <field name="state" />41 <field name="state" />
32 <button name="cancel" string="Cancel" icon="gtk-cancel" type="object" states="draft"/>42 <button name="cancel" string="Cancel" icon="gtk-cancel" type="object" states="draft"/>
33 <button name="create_rfq" string="Create RfQ" icon="gtk-execute" type="object" states="draft" />43 <button name="create_rfq" type="object" string="Create RfQ" icon="gtk-execute" states="draft" />
44 <button name="create_po" type="object" string="Create PO" icon="gtk-execute" states="draft" />
34 <button name="reset" string="Reset to Draft" icon="gtk-ok" type="object" states="cancel" />45 <button name="reset" string="Reset to Draft" icon="gtk-ok" type="object" states="cancel" />
35 </group>46 </group>
36 </page>47 </page>
37 <page string="Suppliers">
38 <field name="supplier_ids" nolabel="1" />
39 </page>
40 <page string="Sourcing Documents">48 <page string="Sourcing Documents">
41 <field name="order_ids" nolabel="1" colspan="4">49 <field name="order_ids" nolabel="1" colspan="4">
42 <tree string="Sourcing Documents" colors="blue:state=='draft'">50 <tree string="Sourcing Documents" colors="blue:state=='draft'">
4351
=== modified file 'procurement_list/security/ir.model.access.csv'
--- procurement_list/security/ir.model.access.csv 2011-03-09 13:24:58 +0000
+++ procurement_list/security/ir.model.access.csv 2011-03-24 15:56:19 +0000
@@ -1,3 +1,3 @@
1"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"1"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
2"access_procurement_list_all","procurement.list all","model_procurement_list",,1,1,1,12"access_procurement_list_all","procurement.list all","model_procurement_list",,1,1,1,1
3"access_procurement_list_line_all","procurement.list.line all","model_procurement_list_line",,1,1,1,13"access_procurement_list_line_all","procurement.list.line all","model_procurement_list_line",,1,1,1,1
4\ No newline at end of file4\ No newline at end of file
55
=== modified file 'procurement_list/test/procurement_list.yml'
--- procurement_list/test/procurement_list.yml 2011-03-16 16:38:58 +0000
+++ procurement_list/test/procurement_list.yml 2011-03-24 15:56:19 +0000
@@ -1,4 +1,59 @@
1-1-
2 In order to test the procurement list module, I will create 6 suppliers,
3 5 products and 3 procurement request.
4 After, I try all possibility to test the supplier default selection
5-
6 I create the 6 partners
7-
8 I create supplier S1
9-
10 !record {model: res.partner, id: supplier1}:
11 name: S1
12 supplier: True
13 address:
14 - name: S1
15-
16 I create the supplier S2
17-
18 !record {model: res.partner, id: supplier2}:
19 name: S2
20 supplier: True
21 address:
22 - name: S2
23-
24 I create the supplier S3
25-
26 !record {model: res.partner, id: supplier3}:
27 name: S3
28 supplier: True
29 address:
30 - name: S3
31-
32 I create the supplier S4
33-
34 !record {model: res.partner, id: supplier4}:
35 name: S4
36 supplier: True
37 address:
38 - name: S4
39-
40 I create the supplier S5
41-
42 !record {model: res.partner, id: supplier5}:
43 name: S5
44 supplier: True
45 address:
46 - name: S5
47-
48 I create the supplier S6
49-
50 !record {model: res.partner, id: supplier6}:
51 name: S6
52 supplier: True
53 address:
54 - name: S6
55-
56 I create the product P1
2 In order to test the procurement list module, I start by creating a new product category57 In order to test the procurement list module, I start by creating a new product category
3-58-
4 !record {model: product.category, id: product_cat1}:59 !record {model: product.category, id: product_cat1}:
@@ -22,10 +77,20 @@
22 type: product77 type: product
23 uom_id: product.product_uom_unit78 uom_id: product.product_uom_unit
24 uom_po_id: product.product_uom_unit79 uom_po_id: product.product_uom_unit
25 volume: 0.080 volume : 0.0
26 warranty: 0.081 warranty: 0.0
27 weight: 0.082 weight: 0.0
28 weight_net: 0.083 weight_net: 0.0
84 seller_ids:
85 - sequence: 10
86 min_qty: 0.00
87 name: supplier1
88 - sequence: 20
89 min_qty: 0.00
90 name: supplier2
91 - sequence: 30
92 min_qty: 0.00
93 name: supplier3
29-94-
30 I create a second product, P295 I create a second product, P2
31-96-
@@ -43,34 +108,106 @@
43 standard_price: 100.0108 standard_price: 100.0
44 supply_method: buy109 supply_method: buy
45 type: product110 type: product
46 uom_id: product.product_uom_unit111 uom_id: product.product_uom_unit
47 uom_po_id: product.product_uom_unit112 uom_po_id: product.product_uom_unit
48 volume: 0.0113 volume : 0.0
49 warranty: 0.0114 warranty: 0.0
50 weight: 0.0115 weight: 0.0
51 weight_net: 0.0116 weight_net: 0.0
52-117 seller_ids:
53 I create a partner118 - sequence: 10
54-119 min_qty: 0.00
55 !record {model: res.partner, id: partner1}:120 name: supplier2
56 name: Supplier 1121 - sequence: 20
57-122 min_qty: 0.00
58 I create an address for this partner123 name: supplier1
59-124-
60 !record {model: res.partner.address, id: addr1}:125 I create the product P3
61 partner_id: partner1126-
62 name: Supplier1127 !record {model: product.product, id: product3}:
63-128 categ_id: product.cat0
64 I create a second partner129 cost_method: standard
65-130 mes_type: fixed
66 !record {model: res.partner, id: partner2}:131 name: P3
67 name: Supplier 2132 price_margin: 2.0
68-133 procure_method: make_to_stock
69 I create an address for this second partner134 property_stock_inventory: stock.location_inventory
70-135 property_stock_procurement: stock.location_procurement
71 !record {model: res.partner.address, id: addr2}:136 property_stock_production: stock.location_production
72 partner_id: partner2137 seller_delay: '1'
73 name: Supplier2138 standard_price: 100.0
139 supply_method: buy
140 type: product
141 uom_id: product.product_uom_unit
142 uom_po_id: product.product_uom_unit
143 volume : 0.0
144 warranty: 0.0
145 weight: 0.0
146 weight_net: 0.0
147 seller_ids:
148 - sequence: 10
149 min_qty: 0.00
150 name: supplier3
151-
152 I create the product P4
153-
154 !record {model: product.product, id: product4}:
155 categ_id: product.cat0
156 cost_method: standard
157 mes_type: fixed
158 name: P4
159 price_margin: 2.0
160 procure_method: make_to_stock
161 property_stock_inventory: stock.location_inventory
162 property_stock_procurement: stock.location_procurement
163 property_stock_production: stock.location_production
164 seller_delay: '1'
165 standard_price: 100.0
166 supply_method: buy
167 type: product
168 uom_id: product.product_uom_unit
169 uom_po_id: product.product_uom_unit
170 volume : 0.0
171 warranty: 0.0
172 weight: 0.0
173 weight_net: 0.0
174 seller_ids:
175 - sequence: 10
176 min_qty: 0.00
177 name: supplier3
178 - sequence: 20
179 min_qty: 0.00
180 name: supplier4
181-
182 I create the product P5
183-
184 !record {model: product.product, id: product5}:
185 categ_id: product.cat0
186 cost_method: standard
187 mes_type: fixed
188 name: P5
189 price_margin: 2.0
190 procure_method: make_to_stock
191 property_stock_inventory: stock.location_inventory
192 property_stock_procurement: stock.location_procurement
193 property_stock_production: stock.location_production
194 seller_delay: '1'
195 standard_price: 100.0
196 supply_method: buy
197 type: product
198 uom_id: product.product_uom_unit
199 uom_po_id: product.product_uom_unit
200 volume : 0.0
201 warranty: 0.0
202 weight: 0.0
203 weight_net: 0.0
204 seller_ids:
205 - sequence: 10
206 min_qty: 0.00
207 name: supplier4
208 - sequence: 20
209 min_qty: 0.00
210 name: supplier5
74-211-
75 I create a procurement list for these two products 212 I create a procurement list for these two products
76-213-
@@ -78,28 +215,67 @@
78 requestor: Administration215 requestor: Administration
79 warehouse_id: stock.warehouse0216 warehouse_id: stock.warehouse0
80 origin: R 20043217 origin: R 20043
81 supplier_ids:
82 - partner1
83 - partner2
84-218-
85 I add two lines in this procurement list219 I create a Procurement Request Line 1 for list1
86-220-
87 !record {model: procurement.list.line, id: list1_line1}:221 !record {model: procurement.list.line, id: list1_line1}:
88 product_id: product1222 product_id: product1
89 product_uom_id: product.product_uom_unit223 product_uom_id: product.product_uom_unit
90 product_qty: 100.00224 product_qty: 12.0
91 comment: special comment225 comment: special comment
92 from_stock: False226 from_stock: False
93 list_id: list1227 list_id: list1
228 supplier_id: supplier1
94-229-
95 The second line230 I create a Procurement Request Line 2 for list1
96-231-
97 !record {model: procurement.list.line, id: list1_line2}:232 !record {model: procurement.list.line, id: list1_line2}:
98 product_id: product2233 product_id: product2
99 product_uom_id: product.product_uom_unit234 product_uom_id: product.product_uom_unit
100 product_qty: 50.0235 product_qty: 10.0
101 from_stock: True236 from_stock: True
102 list_id: list1237 list_id: list1
238 supplier_id: supplier2
239-
240 I create a second Procurement Request
241-
242 !record {model: procurement.list, id: list2}:
243 requestor: Administration
244 warehouse_id: stock.warehouse0
245-
246 I create Procurement Request line 1 for list2
247-
248 !record {model: procurement.list.line, id: list2_line1}:
249 product_id: product3
250 product_uom_id: product.product_uom_unit
251 product_qty: 20.0
252 list_id: list2
253 supplier_id: supplier3
254-
255 I create Procurement Request line 2 for list2
256-
257 !record {model: procurement.list.line, id: list2_line2}:
258 product_id: product4
259 product_uom_id: product.product_uom_unit
260 product_qty: 30.0
261 list_id: list2
262 supplier_id: supplier3
263-
264 I create a third Procurement Request
265-
266 !record {model: procurement.list, id: list3}:
267 requestor: Administration
268 warehouse_id: stock.warehouse0
269 origin: R 20045
270-
271 I create a Procurement Request Line 1 for list3
272-
273 !record {model: procurement.list.line, id: list3_line1}:
274 product_id: product5
275 product_uom_id: product.product_uom_unit
276 product_qty: 30.0
277 list_id: list3
278 supplier_id: supplier3
103-279-
104 I check that the list which was initially in the draft state280 I check that the list which was initially in the draft state
105-281-
@@ -108,36 +284,107 @@
108 - requestor == 'Administration'284 - requestor == 'Administration'
109 - origin == 'R 20043'285 - origin == 'R 20043'
110-286-
111 I create RfQ from this list287 I check if the creation of PO is ok
112-288-
113 !python {model: procurement.list}: |289 !python {model: procurement.list}: |
114 pl_obj = self.pool.get('procurement.list')290 self.create_po(cr, uid, [ref('list1')])
115 pl_id1 = pl_obj.browse(cr, uid, ref('list1'))291-
116 pl_id1.create_rfq()292 I check if documents in 'Sourcing' tab are filled
117-293-
118 I check if the latest message in procurement line is 'RfQ In Progress'294 !assert {model: procurement.list, id: list1}:
119-295 - len(order_ids) == 2, "Number of sourcing documents is wrong"
120 !assert {model: procurement.list.line, id: list1_line1}:296-
121 - latest == 'RfQ In Progress'297 I check if the creation of RfQ is ok
122-298-
123 I check if only one RfQ will be created for the 299 !record {model: procurement.choose.supplier.rfq, id: supplier_choose2}:
124-300 choose_id: list2
125 !python {model: procurement.list}: |301 supplier_ids:
126 pl_obj = self.pool.get('procurement.list')302 - supplier3
303 - supplier4
304-
305 I confirm the creation of RfQ
306-
307 !python {model: procurement.choose.supplier.rfq}: |
308 self.create_rfq(cr, uid, [ref('supplier_choose2')])
309-
310 I check if the latest message in procurement line is 'RfQ In Progress'
311-
312 !assert {model: procurement.list.line, id: list2_line1}:
313 - latest == 'RfQ In Progress', "Rfq In Progress not applied in latest field of line"
314-
315 I check if the latest message in procurement line is 'RfQ In Progress'
316-
317 !assert {model: procurement.list.line, id: list2_line2}:
318 - latest == 'RfQ In Progress', "Rfq In Progress not applied in latest field of line"
319-
320 I check if documents in 'Sourcing' tab are filled
321-
322 !assert {model: procurement.list, id: list2}:
323 - len(order_ids) == 2, "Number of sourcing documents is wrong"
324-
325 I check if only one RfQ will be created for the line
326-
327 !python {model: procurement.list}: |
328 list2 = self.browse(cr, uid, ref('list2'))
127 pol_obj = self.pool.get('purchase.order.line')329 pol_obj = self.pool.get('purchase.order.line')
128 order_obj = self.pool.get('purchase.order')330 order_obj = self.pool.get('purchase.order')
129 pol_ids = pol_obj.search(cr, uid, [('product_id', '=', ref('product1'))])331
130 pl = pl_obj.browse(cr, uid, ref('list1'))332 list_line_ids = []
333 for line in list2.line_ids:
334 list_line_ids.append(line.id)
335
336 pol_ids = pol_obj.search(cr, uid, [('product_id', '=', ref('product3')), ('procurement_line_id', 'in', list_line_ids)])
131337
132 for pol in pol_obj.browse(cr, uid, pol_ids):338 for pol in pol_obj.browse(cr, uid, pol_ids):
133 assert pol.order_id.origin == pl.name, "Bad name for the name of the generated Purchase Order"339 assert pol.order_id.origin == pl.name, "Bad origin for the generated Purchase Order"
134 order_obj.wkf_confirm_order(cr, uid, [pol.order_id.id])340 order_obj.wkf_confirm_order(cr, uid, [pol.order_id.id])
135 assert pol.procurement_line_id.latest == pol.order_id.name, "Procurement line not updated"341 print pol.procurement_line_id.latest, pol.order_id.name
136-342 assert pol.procurement_line_id.latest == pol.order_id.name, "Procurement line not updated"
137 I check that no purchase order line with P2343-
138-344 Split the line
139 !python {model: procurement.list}: |345-
140 pl_obj = self.pool.get('procurement.list')346 !record {model: procurement.list.line.split, id: split1}:
141 pol_obj = self.pool.get('purchase.order.line')347 line_id: list3_line1
142 pol_ids = pol_obj.search(cr, uid, [('product_id', '=', ref('product2'))])348 qty: 20.00
143 assert len(pol_ids) == 0, "No purchase order line found !"349-
350 I check if we have two lines for the product P5 now
351-
352 !python {model: procurement.list.line}: |
353 self.pool.get('procurement.list.line.split').split(cr, uid, ref('split1'))
354 assert len(self.search(cr, uid, [('product_id', '=', ref('product5')), ('list_id', '=', ref('list3'))])) == 2, "Line isn't split"
355-
356 I check if the quantity in old line is decrease of 20 PCE
357-
358 !python {model: procurement.list.line}: |
359 assert self.browse(cr, uid, ref('list3_line1')).product_qty == 10.0, "Quantity of old line isn't updated"
360-
361 I check if the quantity of the new line is good
362-
363 !python {model: procurement.list.line}: |
364 line_id = self.search(cr, uid, [('product_id', '=', ref('product5')), ('list_id', '=', ref('list3'))])
365 for line in line_id:
366 if line != ref('list3_line1'):
367 assert self.browse(cr, uid, line).product_qty == 20.00, "Quantity of new line is wrong"
368-
369 I change the supplier of the second line
370-
371 !python {model: procurement.list.line}: |
372 line_id = self.search(cr, uid, [('product_id', '=', ref('product5')), ('list_id', '=', ref('list3')), ('id', '!=', ref('list3_line1'))])
373 self.write(cr, uid, line_id, {'supplier_id': ref('supplier6')})
374-
375 I simulate a click on Create Purchase Order button
376-
377 !python {model: procurement.list}: |
378 self.create_po(cr, uid, [ref('list3')])
379-
380 I check if two purchase orders have well created
381-
382 !assert {model: procurement.list, id: list3}:
383 - len(order_ids) == 2, "Number of sourcing documents is wrong"
384-
385 I check if the purchase orders have well confirmed
386-
387 !python {model: procurement.list}: |
388 for order in self.browse(cr, uid, ref('list3')).order_ids:
389 assert order.state == 'approved', "PO state isn't confirmed"
390
144\ No newline at end of file391\ No newline at end of file
145392
=== modified file 'procurement_list/wizard/__init__.py'
--- procurement_list/wizard/__init__.py 2011-03-16 13:17:54 +0000
+++ procurement_list/wizard/__init__.py 2011-03-24 15:56:19 +0000
@@ -23,6 +23,7 @@
23import wizard_list_to_order23import wizard_list_to_order
24import wizard_list_to_rfq24import wizard_list_to_rfq
25import wizard_import_list25import wizard_import_list
26import choose_supplier
2627
27# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:28# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
2829
2930
=== added file 'procurement_list/wizard/choose_supplier.py'
--- procurement_list/wizard/choose_supplier.py 1970-01-01 00:00:00 +0000
+++ procurement_list/wizard/choose_supplier.py 2011-03-24 15:56:19 +0000
@@ -0,0 +1,241 @@
1#!/usr/bin/env python
2# -*- encoding: utf-8 -*-
3##############################################################################
4#
5# OpenERP, Open Source Management Solution
6# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from osv import osv
24from osv import fields
25
26import netsvc
27import time
28
29from tools.translate import _
30
31
32class procurement_list_line_split(osv.osv_memory):
33 _name = 'procurement.list.line.split'
34 _description = 'Wizard to split a line into two lines'
35
36 _columns = {
37 'line_id': fields.many2one('procurement.list.line', string='Line to split'),
38 'qty': fields.float(digits=(16,2), string='Quantity for the new line', required=True),
39 }
40
41 def default_get(self, cr, uid, fields, context={}):
42 '''
43 Fills information for the wizard
44 '''
45 line_obj = self.pool.get('procurement.list.line')
46
47 res = super(procurement_list_line_split, self).default_get(cr, uid, fields, context)
48 line_id = context.get('line_id', False)
49 state = context.get('state', False)
50
51 if not line_id:
52 return res
53
54 line = line_obj.browse(cr, uid, line_id, context=context)
55 if state == 'done':
56 raise osv.except_osv(_('Error'), _('You cannot split a line in a Done Procurement Request'))
57
58 res['line_id'] = line_id
59
60 # Default quantity = Old quantity divided by 2
61 res['qty'] = line_obj.browse(cr, uid, line_id, context=context).product_qty/2
62
63 return res
64
65 def split(self, cr, uid, ids, context={}):
66 '''
67 Changes the quantity of the old line and creates a new line with the
68 new quantity
69 '''
70 if ids and isinstance(ids, (int, long)):
71 ids = [ids]
72 line_obj = self.pool.get('procurement.list.line')
73
74 for obj in self.browse(cr, uid, ids, context=context):
75 # Returns an error if the quantity is negative
76 if obj.qty < 0.00:
77 raise osv.except_osv(_('Error'), _('The new quantity should be positive'))
78 if obj.qty > obj.line_id.product_qty:
79 raise osv.except_osv(_('Error'), _('The new quantity can\'t be superior to the quantity of initial line'))
80 # Changes the quantity on the old line
81 line_obj.write(cr, uid, [obj.line_id.id], {'product_qty': obj.line_id.product_qty-obj.qty})
82 # Creates the new line with new quantity
83 line_obj.create(cr, uid, {'list_id': obj.line_id.list_id.id,
84 'product_id': obj.line_id.product_id.id,
85 'product_uom_id': obj.line_id.product_uom_id.id,
86 'product_qty': obj.qty,
87 'supplier_id': False,})
88
89 return {'type': 'ir.actions.act_window_close'}
90
91procurement_list_line_split()
92
93
94class procurement_list_line_merge(osv.osv_memory):
95 _name = 'procurement.list.line.merge'
96 _description = 'Merge Lines'
97
98 _columns = {
99 'line_id': fields.many2one('procurement.list.line', string='Line to merged', readonly=True),
100 'line_ids': fields.many2many('procurement.list.line', 'merge_line_rel', 'merge_id', 'line_id',
101 string='Lines to merged'),
102 }
103
104 def default_get(self, cr, uid, fields, context={}):
105 '''
106 Initializes data with only lines with the same product and the same
107 procurement list
108
109 '''
110 line_obj = self.pool.get('procurement.list.line')
111 res = {}
112
113 line_id = context.get('line_id', False)
114 state = context.get('state', False)
115 if not line_id:
116 raise osv.except_osv(_('Error'), _('No lines to merged'))
117
118 line = line_obj.browse(cr, uid, line_id, context=context)
119 if state == 'done':
120 raise osv.except_osv(_('Error'), _('You cannot merge a line in a Done Procurement Request'))
121 product_id = line.product_id.id
122 product_uom = line.product_uom_id.id
123 wizard_id = line.list_id.id
124
125 res['line_id'] = line_id
126 res['line_ids']= line_obj.search(cr, uid, [('list_id', '=', wizard_id),
127 ('product_id', '=', product_id),
128 ('product_uom_id', '=', product_uom)])
129
130 if line_id in res['line_ids']:
131 res['line_ids'].remove(line_id)
132
133 return res
134
135 def merge_confirm(self, cr, uid, ids, context={}):
136 '''
137 Merged lines
138 '''
139 if ids and isinstance(ids, (int, long)):
140 ids = [ids]
141 line_obj = self.pool.get('procurement.list.line')
142
143 for obj in self.browse(cr, uid, ids, context=context):
144 # Get the supplier of the main line because if merge no lines,
145 # the supplier shouldn't removed
146 supplier_id = obj.line_id.supplier_id.id
147 qty = obj.line_id.product_qty
148 for line in obj.line_ids:
149 qty += line.product_qty
150 supplier_id = False
151 line_obj.unlink(cr, uid, [line.id])
152
153 line_obj.write(cr, uid, [obj.line_id.id], {'product_qty': qty, 'supplier_id': supplier_id})
154
155 return {'type': 'ir.actions.act_window_close'}
156
157procurement_list_line_merge()
158
159
160class procurement_choose_supplier_rfq(osv.osv_memory):
161 _name = 'procurement.choose.supplier.rfq'
162 _description = 'Choose Supplier tp generate RfQ'
163
164 _columns = {
165 'choose_id': fields.many2one('procurement.list', string='Wizard'),
166 'supplier_ids': fields.many2many('res.partner', 'supplier_rfq_rel', 'rfq_id', 'supplier_id',
167 string='Suppliers', domain=[('supplier', '=', 1)]),
168 }
169
170 def default_get(self, cr, uid, fields, context={}):
171 '''
172 Fills information in the wizard
173 '''
174 res = super(procurement_choose_supplier_rfq, self).default_get(cr, uid, fields, context=context)
175 wizard_id = context.get('active_id', False)
176
177 if not wizard_id:
178 return res
179
180 res['choose_id'] = wizard_id
181
182 return res
183
184 def create_rfq(self, cr, uid, ids, context={}):
185 '''
186 Creates Requests for Quotation for each supplier with all lines
187 '''
188 if ids and isinstance(ids, (int, long)):
189 ids = [ids]
190 order_obj = self.pool.get('purchase.order')
191 order_line_obj = self.pool.get('purchase.order.line')
192 proc_list_obj = self.pool.get('procurement.list')
193 proc_line_obj = self.pool.get('procurement.list.line')
194
195 po_ids = [] # List of all created RfQ
196
197 for obj in self.browse(cr, uid, ids):
198 origin = obj.choose_id.name
199 location_id = proc_list_obj._get_location(cr, uid, obj.choose_id.warehouse_id)
200
201 lines = []
202 for l in obj.choose_id.line_ids:
203 lines.append({'line_id': l.id,
204 'product_id': l.product_id.id,
205 'product_uom': l.product_uom_id.id,
206 'product_name': l.product_id.name,
207 'product_qty': l.product_qty,})
208
209 # Creates one RfQ for each supplier
210 for s in obj.supplier_ids:
211 po_id = order_obj.create(cr, uid, {'partner_id': s.id,
212 'partner_address_id': s.address_get().get('default'),
213 'pricelist_id': s.property_product_pricelist.id,
214 'origin': origin,
215 'location_id': location_id})
216 po_ids.append(po_id)
217 # Creates lines
218 for l in lines:
219 order_line_obj.create(cr, uid, {'product_uom': l.get('product_uom'),
220 'product_id': l.get('product_id'),
221 'order_id': po_id,
222 'price_unit': 0.00,
223 'date_planned': obj.choose_id.order_date,
224 'product_qty': l.get('product_qty'),
225 'name': l.get('product_name'),
226 })
227
228 proc_id = self.browse(cr, uid, ids[0]).choose_id.id
229 proc_list_obj.write(cr, uid, proc_id, {'state': 'done', 'order_ids': [(6, 0, po_ids)]})
230
231 return {'type': 'ir.actions.act_window',
232 'res_model': 'purchase.order',
233 'view_type': 'form',
234 'view_mode': 'tree,form',
235 'domain': [('id', 'in', po_ids)]}
236
237procurement_choose_supplier_rfq()
238
239
240# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
241
0242
=== added file 'procurement_list/wizard/choose_supplier_view.xml'
--- procurement_list/wizard/choose_supplier_view.xml 1970-01-01 00:00:00 +0000
+++ procurement_list/wizard/choose_supplier_view.xml 2011-03-24 15:56:19 +0000
@@ -0,0 +1,59 @@
1<?xml version="1.0" encoding="utf-8" ?>
2<openerp>
3 <data>
4
5 <record id="choose_supplier_line_split_qty" model="ir.ui.view">
6 <field name="name">choose.supplier.line.split.qty</field>
7 <field name="model">procurement.list.line.split</field>
8 <field name="type">form</field>
9 <field name="arch" type="xml">
10 <form string="Split line">
11 <separator colspan="4" string="New quantity" />
12 <field name="qty" colspan="4" />
13 <separator colspan="4" string="Actions" />
14 <button special="cancel" string="Cancel" icon="gtk-cancel" colspan="2" type="object" />
15 <button name="split" string="New line" icon="gtk-ok" colspan="2" type="object" />
16 </form>
17 </field>
18 </record>
19
20 <record id="choose_supplier_line_merge" model="ir.ui.view">
21 <field name="name">choose.supplier.line.merge</field>
22 <field name="model">procurement.list.line.merge</field>
23 <field name="type">form</field>
24 <field name="arch" type="xml">
25 <form string="Merge lines">
26 <separator colspan="4" string="Possible lines to merge" />
27 <field name="line_ids" colspan="4" nolabel="1" >
28 <tree string="Lines">
29 <field name="product_id" />
30 <field name="product_qty" />
31 <field name="product_uom_id" />
32 <field name="supplier_id" />
33 </tree>
34 </field>
35 <separator colspan="4" />
36 <button special="cancel" string="Cancel" icon="gtk-cancel" colspan="2" type="object" />
37 <button name="merge_confirm" string="Merge" icon="gtk-ok" colspan="2" type="object" />
38 </form>
39 </field>
40 </record>
41
42 <record id="choose_supplier_rfq_form_view" model="ir.ui.view">
43 <field name="name">choose.supplier.rfq.form.view</field>
44 <field name="model">procurement.choose.supplier.rfq</field>
45 <field name="type">form</field>
46 <field name="arch" type="xml">
47 <form string="Choose Suppliers">
48 <separator colspan="4" string="Suppliers" />
49 <field name="supplier_ids" colspan="4" nolabel="1" />
50 <separator colspan="4" />
51 <button special="cancel" string="Cancel" icon="gtk-cancel" colspan="2" type="object" />
52 <button name="create_rfq" type="object" string="Create RfQ" icon="gtk-execute" />
53 </form>
54 </field>
55 </record>
56
57 </data>
58</openerp>
59
060
=== removed directory 'stock_inventory_type'
=== removed file 'stock_inventory_type/__init__.py'
--- stock_inventory_type/__init__.py 2011-03-15 17:05:15 +0000
+++ stock_inventory_type/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,28 +0,0 @@
1#!/usr/bin/env python
2# -*- encoding: utf-8 -*-
3##############################################################################
4#
5# OpenERP, Open Source Management Solution
6# Copyright (C) 2011 TeMPO Consulting, MSF
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24import stock
25import stock_move_report
26
27# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
28
290
=== removed file 'stock_inventory_type/__openerp__.py'
--- stock_inventory_type/__openerp__.py 2011-03-15 17:05:15 +0000
+++ stock_inventory_type/__openerp__.py 1970-01-01 00:00:00 +0000
@@ -1,49 +0,0 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Management Solution
5# Copyright (C) 2011 TeMPO Consulting, MSF
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21{
22 "name" : "Stock Adjustment/Move Report",
23 "version" : "1.0",
24 "author" : "TeMPO Consulting, MSF",
25 "category": "Inventory Control",
26 "description": """
27 This module aims to help you to determine the type \
28 of your inventory adjustment and to search stock move \
29 by type of adjustment.
30 """,
31 "website": "http://unifield.msf.org",
32 "init_xml": [
33 ],
34 "depends" : [
35 "stock",
36 ],
37 "update_xml": [
38 "stock_view.xml",
39 "stock_data.xml",
40 "security/ir.model.access.csv",
41 ],
42 "demo_xml": [
43 ],
44 "test": [
45 "test/adjustment_type.yml",
46 ],
47 "installable": True,
48 "active": False,
49}
500
=== removed directory 'stock_inventory_type/security'
=== removed file 'stock_inventory_type/security/ir.model.access.csv'
--- stock_inventory_type/security/ir.model.access.csv 2011-03-09 14:54:31 +0000
+++ stock_inventory_type/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
1"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
2"access_stock_adjustment_type_all","stock.adjustment.type all","model_stock_adjustment_type",,1,1,1,1
30
=== removed file 'stock_inventory_type/stock.py'
--- stock_inventory_type/stock.py 2011-03-15 17:05:15 +0000
+++ stock_inventory_type/stock.py 1970-01-01 00:00:00 +0000
@@ -1,135 +0,0 @@
1#!/usr/bin/env python
2# -*- encoding: utf-8 -*-
3##############################################################################
4#
5# OpenERP, Open Source Management Solution
6# Copyright (C) 2011 TeMPO Consulting, MSF
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24from osv import osv
25from osv import fields
26
27from tools.translate import _
28
29
30class stock_adjustment_type(osv.osv):
31 _name = 'stock.adjustment.type'
32 _description = 'Inventory/Move Adjustment Types'
33
34 _columns = {
35 'name': fields.char(size=64, string='Name', required=True),
36 }
37
38stock_adjustment_type()
39
40
41class stock_inventory_line(osv.osv):
42 _name = 'stock.inventory.line'
43 _inherit = 'stock.inventory.line'
44
45 _columns = {
46 'type_id': fields.many2one('stock.adjustment.type', string='Adjustment type'),
47 'comment': fields.char(size=128, string='Comment'),
48 }
49
50stock_inventory_line()
51
52
53class stock_move(osv.osv):
54 _name = 'stock.move'
55 _inherit = 'stock.move'
56
57 _columns = {
58 'type_id': fields.many2one('stock.adjustment.type', string='Adjustment type', readonly=True),
59 'comment': fields.char(size=128, string='Comment'),
60 }
61
62stock_move()
63
64
65class stock_inventory(osv.osv):
66 _name = 'stock.inventory'
67 _inherit = 'stock.inventory'
68
69 def action_confirm(self, cr, uid, ids, context={}):
70 """ Confirm the inventory and writes its finished date
71 @return True
72 """
73 # @@@override@ stock.stock_inventory.action_confirm()
74 # to perform the correct inventory corrections we need analyze stock location by
75 # location, never recursively, so we use a special context
76 product_context = dict(context, compute_child=False)
77
78 location_obj = self.pool.get('stock.location')
79 for inv in self.browse(cr, uid, ids, context=context):
80 move_ids = []
81 for line in inv.inventory_line_id:
82 pid = line.product_id.id
83 product_context.update(uom=line.product_uom.id,date=inv.date)
84 amount = location_obj._product_get(cr, uid, line.location_id.id, [pid], product_context)[pid]
85
86 change = line.product_qty - amount
87 lot_id = line.prod_lot_id.id
88 type_id = line.type_id.id
89 if change:
90 location_id = line.product_id.product_tmpl_id.property_stock_inventory.id
91 value = {
92 'name': 'INV:' + str(line.inventory_id.id) + ':' + line.inventory_id.name,
93 'product_id': line.product_id.id,
94 'product_uom': line.product_uom.id,
95 'prodlot_id': lot_id,
96 'date': inv.date,
97 # msf
98 'comment': line.comment,
99 #
100 }
101 if change > 0:
102 value.update( {
103 'product_qty': change,
104 'location_id': location_id,
105 'location_dest_id': line.location_id.id,
106 })
107 else:
108 value.update( {
109 'product_qty': -change,
110 'location_id': line.location_id.id,
111 'location_dest_id': location_id,
112 })
113 if lot_id:
114 value.update({
115 'prodlot_id': lot_id,
116 'product_qty': line.product_qty
117 })
118 # msf
119 if type_id:
120 value.update({
121 'type_id': type_id,
122 })
123 #
124 move_ids.append(self._inventory_line_hook(cr, uid, line, value))
125 message = _('Inventory') + " '" + inv.name + "' "+ _("is done.")
126 self.log(cr, uid, inv.id, message)
127 self.write(cr, uid, [inv.id], {'state': 'confirm', 'move_ids': [(6, 0, move_ids)]})
128
129 return True
130 # @@@end
131
132stock_inventory()
133
134# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
135
1360
=== removed file 'stock_inventory_type/stock_data.xml'
--- stock_inventory_type/stock_data.xml 2011-03-09 14:54:31 +0000
+++ stock_inventory_type/stock_data.xml 1970-01-01 00:00:00 +0000
@@ -1,23 +0,0 @@
1<?xml version="1.0" encoding="utf-8" ?>
2<openerp>
3 <data>
4
5 <record id="adjustment_type_loss" model="stock.adjustment.type">
6 <field name="name">Loss</field>
7 </record>
8
9 <record id="adjustment_type_scrap" model="stock.adjustment.type">
10 <field name="name">Scrap</field>
11 </record>
12
13 <record id="adjustment_type_expired" model="stock.adjustment.type">
14 <field name="name">Expired</field>
15 </record>
16
17 <record id="adjustment_type_broken" model="stock.adjustment.type">
18 <field name="name">Broken</field>
19 </record>
20
21 </data>
22</openerp>
23
240
=== removed file 'stock_inventory_type/stock_move_report.py'
--- stock_inventory_type/stock_move_report.py 2011-03-15 17:05:15 +0000
+++ stock_inventory_type/stock_move_report.py 1970-01-01 00:00:00 +0000
@@ -1,130 +0,0 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Management Solution
5# Copyright (C) 2011 TeMPO Consulting, MSF
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22from osv import osv
23from osv import fields
24
25from decimal_precision import decimal_precision as dp
26
27import tools
28
29
30class report_stock_move(osv.osv):
31 _name = 'report.stock.move'
32 _inherit = 'report.stock.move'
33
34 _columns = {
35 'type_id': fields.many2one('stock.adjustment.type', string='Adjustment type'),
36 }
37
38 def init(self, cr):
39 # @@@override@ stock.report_stock_move.init
40 tools.drop_view_if_exists(cr, 'report_stock_move')
41 cr.execute("""
42 CREATE OR REPLACE view report_stock_move AS (
43 SELECT
44 min(sm_id) as id,
45 sm_type_id as type_id,
46 date_trunc('day',al.dp) as date,
47 al.curr_year as year,
48 al.curr_month as month,
49 al.curr_day as day,
50 al.curr_day_diff as day_diff,
51 al.curr_day_diff1 as day_diff1,
52 al.curr_day_diff2 as day_diff2,
53 al.location_id as location_id,
54 al.picking_id as picking_id,
55 al.company_id as company_id,
56 al.location_dest_id as location_dest_id,
57 al.product_qty,
58 al.out_qty as product_qty_out,
59 al.in_qty as product_qty_in,
60 al.address_id as partner_id,
61 al.product_id as product_id,
62 al.state as state ,
63 al.product_uom as product_uom,
64 al.categ_id as categ_id,
65 coalesce(al.type, 'other') as type,
66 al.stock_journal as stock_journal,
67 sum(al.in_value - al.out_value) as value
68 FROM (SELECT
69 CASE WHEN sp.type in ('out') THEN
70 sum(sm.product_qty * pu.factor)
71 ELSE 0.0
72 END AS out_qty,
73 CASE WHEN sp.type in ('in') THEN
74 sum(sm.product_qty * pu.factor)
75 ELSE 0.0
76 END AS in_qty,
77 CASE WHEN sp.type in ('out') THEN
78 sum(sm.product_qty * pu.factor) * pt.standard_price
79 ELSE 0.0
80 END AS out_value,
81 CASE WHEN sp.type in ('in') THEN
82 sum(sm.product_qty * pu.factor) * pt.standard_price
83 ELSE 0.0
84 END AS in_value,
85 min(sm.id) as sm_id,
86 sm.date as dp,
87 sm.type_id as sm_type_id,
88 to_char(date_trunc('day',sm.date), 'YYYY') as curr_year,
89 to_char(date_trunc('day',sm.date), 'MM') as curr_month,
90 to_char(date_trunc('day',sm.date), 'YYYY-MM-DD') as curr_day,
91 avg(date(sm.date)-date(sm.create_date)) as curr_day_diff,
92 avg(date(sm.date_expected)-date(sm.create_date)) as curr_day_diff1,
93 avg(date(sm.date)-date(sm.date_expected)) as curr_day_diff2,
94 sm.location_id as location_id,
95 sm.location_dest_id as location_dest_id,
96 sum(sm.product_qty) as product_qty,
97 pt.categ_id as categ_id ,
98 sm.address_id as address_id,
99 sm.product_id as product_id,
100 sm.picking_id as picking_id,
101 sm.company_id as company_id,
102 sm.state as state,
103 sm.product_uom as product_uom,
104 sp.type as type,
105 sp.stock_journal_id AS stock_journal
106 FROM
107 stock_move sm
108 LEFT JOIN stock_picking sp ON (sm.picking_id=sp.id)
109 LEFT JOIN product_product pp ON (sm.product_id=pp.id)
110 LEFT JOIN product_uom pu ON (sm.product_uom=pu.id)
111 LEFT JOIN product_template pt ON (pp.product_tmpl_id=pt.id)
112 LEFT JOIN stock_location sl ON (sm.location_id = sl.id)
113
114 GROUP BY
115 sm.id,sp.type, sm.date,sm.address_id, sm.type_id,
116 sm.product_id,sm.state,sm.product_uom,sm.date_expected,
117 sm.product_id,pt.standard_price, sm.picking_id, sm.product_qty,
118 sm.company_id,sm.product_qty, sm.location_id,sm.location_dest_id,pu.factor,pt.categ_id, sp.stock_journal_id)
119 AS al
120
121 GROUP BY
122 al.out_qty,al.in_qty,al.curr_year,al.curr_month, al.sm_type_id,
123 al.curr_day,al.curr_day_diff,al.curr_day_diff1,al.curr_day_diff2,al.dp,al.location_id,al.location_dest_id,
124 al.address_id,al.product_id,al.state,al.product_uom,
125 al.picking_id,al.company_id,al.type,al.product_qty, al.categ_id, al.stock_journal
126 )
127 """)
128 # @@@end
129
130report_stock_move()
1310
=== removed file 'stock_inventory_type/stock_view.xml'
--- stock_inventory_type/stock_view.xml 2011-03-15 17:05:15 +0000
+++ stock_inventory_type/stock_view.xml 1970-01-01 00:00:00 +0000
@@ -1,196 +0,0 @@
1<?xml version="1.0" encoding="utf-8" ?>
2<openerp>
3 <data>
4
5 <!-- Stock Adjustment Types -->
6
7 <record id="stock_adjustment_type_form_view" model="ir.ui.view">
8 <field name="name">stock.adjustment.type.form.view</field>
9 <field name="model">stock.adjustment.type</field>
10 <field name="type">form</field>
11 <field name="arch" type="xml">
12 <form string="Adjustment Type">
13 <field name="name" colspan="4" select="1" />
14 </form>
15 </field>
16 </record>
17
18 <record id="stock_adjustment_type_tree_view" model="ir.ui.view">
19 <field name="name">stock.adjustment.type.tree.view</field>
20 <field name="model">stock.adjustment.type</field>
21 <field name="type">tree</field>
22 <field name="arch" type="xml">
23 <tree string="Adjustment Types">
24 <field name="name" />
25 </tree>
26 </field>
27 </record>
28
29 <record id="action_stock_adjustment_type" model="ir.actions.act_window">
30 <field name="name">Stock Adjustment Types</field>
31 <field name="res_model">stock.adjustment.type</field>
32 <field name="view_type">form</field>
33 <field name="view_mode">tree,form</field>
34 </record>
35
36 <menuitem
37 name="Inventory"
38 id="menu_configuration_inventory"
39 parent="stock.menu_stock_configuration" />
40
41 <menuitem
42 action="action_stock_adjustment_type"
43 id="menu_stock_adjustment_type"
44 parent="menu_configuration_inventory" />
45
46
47 <!-- Overrirde Stock Inventory Lines -->
48 <record id="stock_inventory_line_tree_type_id" model="ir.ui.view">
49 <field name="name">stock.inventory.line.tree.type.id</field>
50 <field name="model">stock.inventory.line</field>
51 <field name="type">tree</field>
52 <field name="inherit_id" ref="stock.stock_inventory_line_tree" />
53 <field name="arch" type="xml">
54 <xpath expr="/tree/field[@name='prodlot_id']" position="after">
55 <field name="type_id" widget="selection" />
56 <field name="comment" />
57 </xpath>
58 </field>
59 </record>
60
61 <record id="stock_inventory_line_form_type_id" model="ir.ui.view">
62 <field name="name">stock.inventory.line.form.type.id</field>
63 <field name="model">stock.inventory.line</field>
64 <field name="type">form</field>
65 <field name="inherit_id" ref="stock.stock_inventory_line_tree" />
66 <field name="arch" type="xml">
67 <xpath expr="/form/field[@name='prodlot_id']" position="after">
68 <field name="type_id" widget="selection" />
69 <field name="comment" />
70 </xpath>
71 </field>
72 </record>
73
74 <record id="stock_inventory_form_type_id" model="ir.ui.view">
75 <field name="name">stock.inventory.form.type.id</field>
76 <field name="model">stock.inventory</field>
77 <field name="type">form</field>
78 <field name="inherit_id" ref="stock.view_inventory_form" />
79 <field name="arch" type="xml">
80 <data>
81 <xpath expr="/form/notebook/page/field[@name='inventory_line_id']/tree/field[@name='product_id']" position="after">
82 <field name="type_id" widget="selection" />
83 <field name="comment" />
84 </xpath>
85 <xpath expr="/form/notebook/page/field[@name='inventory_line_id']/form/field[@name='product_id']" position="after">
86 <field name="type_id" widget="selection" />
87 <field name="comment" />
88 </xpath>
89 <xpath expr="/form/notebook/page[@string='Posted Inventory']/field[@name='move_ids']/tree/field[@name='prodlot_id']" position="after">
90 <field name="type_id" widget="selection" />
91 </xpath>
92 </data>
93 </field>
94 </record>
95
96 <!-- Override Stock Moves -->
97 <record id="stock_move_tree_type_id" model="ir.ui.view">
98 <field name="name">stock.move.tree.type.id</field>
99 <field name="model">stock.move</field>
100 <field name="type">tree</field>
101 <field name="inherit_id" ref="stock.stock_move_tree" />
102 <field name="arch" type="xml">
103 <xpath expr="/tree/field[@name='prodlot_id']" position="after">
104 <field name="type_id" widget="selection" />
105 <field name="comment" />
106 </xpath>
107 </field>
108 </record>
109
110 <record id="stock_move_tree2_type_id" model="ir.ui.view">
111 <field name="name">stock.move.tree2.type.id</field>
112 <field name="model">stock.move</field>
113 <field name="type">tree</field>
114 <field name="inherit_id" ref="stock.stock_move_tree2" />
115 <field name="arch" type="xml">
116 <xpath expr="/tree/field[@name='prodlot_id']" position="after">
117 <field name="type_id" widget="selection" />
118 <field name="comment" />
119 </xpath>
120 </field>
121 </record>
122
123 <record id="view_move_tree_type_id" model="ir.ui.view">
124 <field name="name">view.move.tree.type.id</field>
125 <field name="model">stock.move</field>
126 <field name="type">tree</field>
127 <field name="inherit_id" ref="stock.view_move_tree" />
128 <field name="arch" type="xml">
129 <xpath expr="/tree/field[@name='create_date']" position="after">
130 <field name="type_id" widget="selection" />
131 <field name="comment" />
132 </xpath>
133 </field>
134 </record>
135
136 <record id="view_move_form_type_id" model="ir.ui.view">
137 <field name="name">view.move.form.type.id</field>
138 <field name="model">stock.move</field>
139 <field name="type">form</field>
140 <field name="inherit_id" ref="stock.view_move_form" />
141 <field name="arch" type="xml">
142 <xpath expr="/form/group/button[@string='Scrap']" position="after">
143 <field name="type_id" widget="selection" />
144 <field name="comment" />
145 </xpath>
146 </field>
147 </record>
148
149 <record id="view_move_search_type_id" model="ir.ui.view">
150 <field name="name">view.move.search.type.id</field>
151 <field name="model">stock.move</field>
152 <field name="type">search</field>
153 <field name="inherit_id" ref="stock.view_move_search" />
154 <field name="arch" type="xml">
155 <xpath expr="/search/group/field[@name='product_id']" position="before">
156 <field name="type_id" widget="selection" />
157 <field name="comment" />
158 </xpath>
159 </field>
160 </record>
161
162 <record id="view_stock_tree_type_id" model="ir.ui.view">
163 <field name="name">view.stock.tree.type.id</field>
164 <field name="model">report.stock.move</field>
165 <field name="type">tree</field>
166 <field name="inherit_id" ref="stock.view_stock_tree" />
167 <field name="arch" type="xml">
168 <xpath expr="/tree/field[@name='type']" position="after">
169 <field name="type_id" />
170 </xpath>
171 </field>
172 </record>
173
174 <record id="view_stock_search_type_id" model="ir.ui.view">
175 <field name="name">view.stock.search.type.id</field>
176 <field name="model">report.stock.move</field>
177 <field name="type">search</field>
178 <field name="inherit_id" ref="stock.view_stock_search" />
179 <field name="arch" type="xml">
180 <data>
181 <xpath expr="/search/group/separator[3]" position="after">
182 <field name="type_id" widget="selection" />
183 </xpath>
184 <xpath expr="/search/group[@string='Group By...']/filter[@name='group_type']" position="after">
185 <filter string="Adjustment Type" name="group_type_id" icon="terp-stock_symbol-selection" context="{'group_by':'type_id'}" />
186 </xpath>
187 <xpath expr="/search/group[@string='Group By...']/separator[5]" position="replace">
188 <newline />
189 </xpath>
190 </data>
191 </field>
192 </record>
193
194 </data>
195</openerp>
196
1970
=== removed directory 'stock_inventory_type/test'
=== removed file 'stock_inventory_type/test/adjustment_type.yml'
--- stock_inventory_type/test/adjustment_type.yml 2011-03-09 16:36:19 +0000
+++ stock_inventory_type/test/adjustment_type.yml 1970-01-01 00:00:00 +0000
@@ -1,117 +0,0 @@
1-
2 In order to test the stock_inventory_type module, I will create product,
3 create a physical inventory, fill inventory lines from location
4-
5 I create a product category
6-
7 !record {model: product.category, id: product_category1}:
8 name: Categ1
9-
10 I create the first product (P1)
11-
12 !record {model: product.product, id: product_p1}:
13 valuation: manual_periodic
14 supply_method: produce
15 mes_type: fixed
16 uom_id: product.product_uom_unit
17 uom_po_id: product.product_uom_unit
18 type: product
19 procure_method: make_to_stock
20 cost_method: standard
21 categ_id: stock_inventory_type.product_category1
22 name: P1
23 standard_price: 10.0
24-
25 I create the second product (P2)
26-
27 !record {model: product.product, id: product_p2}:
28 valuation: manual_periodic
29 supply_method: produce
30 mes_type: fixed
31 uom_id: product.product_uom_unit
32 uom_po_id: product.product_uom_unit
33 type: product
34 procure_method: make_to_stock
35 cost_method: standard
36 categ_id: stock_inventory_type.product_category1
37 name: P2
38 standard_price: 20.0
39-
40 I create the third product (P3)
41-
42 !record {model: product.product, id: product_p3}:
43 valuation: manual_periodic
44 supply_method: produce
45 mes_type: fixed
46 uom_id: product.product_uom_unit
47 uom_po_id: product.product_uom_unit
48 type: product
49 procure_method: make_to_stock
50 cost_method: standard
51 categ_id: stock_inventory_type.product_category1
52 name: P3
53 standard_price: 30.0
54-
55 I create a physical inventory
56-
57 !record {model: stock.inventory, id: stock_inventory1}:
58 company_id: base.main_company
59 date: !eval time.strftime('%Y-%m-%d %H:%M:%S')
60 inventory_line_id:
61 - company_id: base.main_company
62 location_id: stock.stock_location_stock
63 product_id: stock_inventory_type.product_p1
64 product_qty: 70.0
65 product_uom: product.product_uom_unit
66 type_id: stock_inventory_type.adjustment_type_loss
67 comment: Loss items
68 - company_id: base.main_company
69 location_id: stock.stock_location_stock
70 product_id: stock_inventory_type.product_p2
71 product_qty: 50.0
72 product_uom: product.product_uom_unit
73 type_id: stock_inventory_type.adjustment_type_expired
74 comment: Expired product at 12/12/2012
75 - company_id: base.main_company
76 location_id: stock.stock_location_stock
77 product_id: stock_inventory_type.product_p3
78 product_qty: 10.0
79 product_uom: product.product_uom_unit
80 type_id: stock_inventory_type.adjustment_type_scrap
81 name: Test of UNI-SUP-1.15
82 state: draft
83-
84 I confirm the Inventory
85-
86 !python {model: stock.inventory}: |
87 self.action_confirm(cr, uid, [ref('stock_inventory1')])
88 self.action_done(cr, uid, [ref('stock_inventory1')])
89-
90 I check the 'Loss' stock moves
91-
92 !python {model: stock.move}: |
93 move_ids = self.search(cr, uid, [('type_id', '=', ref('stock_inventory_type.adjustment_type_loss'))])
94 assert move_ids, "No lines with 'Loss' type"
95 move = self.browse(cr, uid, move_ids[0])
96 assert move.product_id.id == ref('stock_inventory_type.product_p1'), "Move product (P1) is not correct"
97 assert move.product_qty == 70.0, "Move quatity (70.0) is not correct"
98 assert move.comment == 'Loss items', "Move comment (Loss items) is not correct"
99-
100 I check the 'Expired' stock moves
101-
102 !python {model: stock.move}: |
103 move_ids = self.search(cr, uid, [('type_id', '=', ref('stock_inventory_type.adjustment_type_expired'))])
104 assert move_ids, "No lines with 'Expired' type"
105 move = self.browse(cr, uid, move_ids[0])
106 assert move.product_id.id == ref('stock_inventory_type.product_p2'), "Move product (P2) is not correct"
107 assert move.product_qty == 50.0, "Move quatity (50.0) is not correct"
108 assert move.comment == 'Expired product at 12/12/2012', "Move comment (Expired product at 12/12/2012) is not correct"
109-
110 I check the 'Scrapped' stock moves
111-
112 !python {model: stock.move}: |
113 move_ids = self.search(cr, uid, [('type_id', '=', ref('stock_inventory_type.adjustment_type_scrap'))])
114 assert move_ids, "No lines with 'Scrap' type"
115 move = self.browse(cr, uid, move_ids[0])
116 assert move.product_id.id == ref('stock_inventory_type.product_p3'), "Move product (P3) is not correct"
117 assert move.product_qty == 10.0, "Move quatity (10.0) is not correct"

Subscribers

People subscribed via source and target branches

to all changes: