~unifield-team/unifield-wm/us-826

658.1.7 by Quentin THEURET
UF-857 [ADD] Add order cycle and automatic replenishment reports
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
import tools
23
from osv import fields,osv
24
from decimal_precision import decimal_precision as dp
25
26
class order_cycle_rules_report(osv.osv):
27
    _name = 'order.cycle.rules.report'
28
    _auto = False
29
    _order = 'product_reference, product_name, product_id, location_id'
30
    
31
    def _get_nomen_s(self, cr, uid, ids, fields, *a, **b):
32
        value = {}
33
        for f in fields:
34
            value[f] = False
35
36
        ret = {}
37
        for id in ids:
38
            ret[id] = value
39
        return ret
40
    
713 by jf
[FIX] context None
41
    def _search_nomen_s(self, cr, uid, obj, name, args, context=None):
658.1.7 by Quentin THEURET
UF-857 [ADD] Add order cycle and automatic replenishment reports
42
43
        if not args:
44
            return []
45
        narg = []
46
        for arg in args:
47
            el = arg[0].split('_')
48
            el.pop()
49
            narg=[('_'.join(el), arg[1], arg[2])]
50
        
51
        return narg
52
    
53
    def onChangeSearchNomenclature(self, cr, uid, id, position, type, nomen_manda_0, nomen_manda_1, nomen_manda_2, nomen_manda_3, num=True, context=None):
54
        return self.pool.get('product.product').onChangeSearchNomenclature(cr, uid, id, position, type, nomen_manda_0, nomen_manda_1, nomen_manda_2, nomen_manda_3, num=num, context=context)
55
    
713 by jf
[FIX] context None
56
    def _get_nomen_name(self, cr, uid, ids, field_name, args, context=None):
658.1.7 by Quentin THEURET
UF-857 [ADD] Add order cycle and automatic replenishment reports
57
        '''
58
        Returns a string with all nomenclature levels separated by '/'
59
        '''
60
        res = {}
61
        
62
        for rule in self.browse(cr, uid, ids, context=context):
765.5.1 by Quentin THEURET
[FIX] Fix error on server when try to open list of procurement rules from procurement report
63
            res[rule.id] = ''
64
            if rule.nomen_manda_0:
65
                res[rule.id] = rule.nomen_manda_0.name
66
            if rule.nomen_manda_1:
67
                res[rule.id] += '/'
68
                res[rule.id] += rule.nomen_manda_1.name
69
            if rule.nomen_manda_2:
70
                res[rule.id] += '/'
71
                res[rule.id] += rule.nomen_manda_2.name
72
            if rule.nomen_manda_3:
73
                res[rule.id] += '/'
74
                res[rule.id] += rule.nomen_manda_3.name  
658.1.7 by Quentin THEURET
UF-857 [ADD] Add order cycle and automatic replenishment reports
75
            
76
        return res
77
    
713 by jf
[FIX] context None
78
    def _get_stock(self, cr, uid, ids, field_name, args, context=None):
658.1.7 by Quentin THEURET
UF-857 [ADD] Add order cycle and automatic replenishment reports
79
        '''
80
        Returns stock value of a product
81
        '''
713 by jf
[FIX] context None
82
        if context is None:
83
            context = {}
658.1.7 by Quentin THEURET
UF-857 [ADD] Add order cycle and automatic replenishment reports
84
        res = {}
85
        
86
        ir_data = self.pool.get('ir.model.data')
87
        stock_location = ir_data.get_object_reference(cr, uid, 'stock', 'stock_location_stock')[1]
88
        # TODO: Change msf_profile by msf_location_setup module
765.5.1 by Quentin THEURET
[FIX] Fix error on server when try to open list of procurement rules from procurement report
89
        intermediate_stock = ir_data.get_object_reference(cr, uid, 'msf_config_locations', 'stock_location_intermediate_client_view')[1]
90
        consumption_stock = ir_data.get_object_reference(cr, uid, 'msf_config_locations', 'stock_location_consumption_units_view')[1]
658.1.7 by Quentin THEURET
UF-857 [ADD] Add order cycle and automatic replenishment reports
91
        
92
        for rule in self.browse(cr, uid, ids, context=context):
93
            res[rule.id] = {'stock': 0.00,
94
                            'intermediate_stock': 0.00,
95
                            'consumption_stock': 0.00,
96
                            'amc': 0.00,
97
                            'fmc': 0.00}
98
            
99
            if rule.product_id:
100
                res[rule.id]['amc'] = rule.product_id.product_amc
101
                res[rule.id]['fmc'] = rule.product_id.reviewed_consumption
102
            
103
                c = context.copy()
104
                c.update({'location': stock_location, 'compute_child': True})
105
                product = self.pool.get('product.product').browse(cr, uid, rule.product_id.id, context=c)
106
                res[rule.id]['stock'] = product.qty_available
107
                
108
                c2 = context.copy()
109
                c2.update({'location': consumption_stock, 'compute_child': True})
110
                product2 = self.pool.get('product.product').browse(cr, uid, rule.product_id.id, context=c2)
111
                res[rule.id]['consumption_stock'] = product2.qty_available
112
                
113
                c3 = context.copy()
114
                c3.update({'location': intermediate_stock, 'compute_child': True})
115
                product3 = self.pool.get('product.product').browse(cr, uid, rule.product_id.id, context=c3)
116
                res[rule.id]['intermediate_stock'] = product3.qty_available
117
            
118
            total_stock = res[rule.id]['stock'] + res[rule.id]['intermediate_stock'] + res[rule.id]['consumption_stock']
119
            moh = res[rule.id]['amc'] > 0 and total_stock / res[rule.id]['amc'] or 0.00
120
            
121
            res[rule.id].update({'total_stock': total_stock, 'moh': moh})
122
        
123
        return res
124
    
125
    _columns = {
126
        'rule_id': fields.many2one('stock.warehouse.order.cycle', string='Rules reference', readonly=True),
127
        'product_id': fields.many2one('product.product', string='Product', readonly=True),
128
        'location_id': fields.many2one('stock.location', string='Location', readonly=True),
129
        'product_reference': fields.char(size=64, string='Reference', type='char'),
130
        'product_name': fields.char(size=128, string='Name', type='char'),
131
        'nomen_manda_0': fields.many2one('product.nomenclature', 'Main Type', required=True, select=1),
132
        'nomen_manda_1': fields.many2one('product.nomenclature', 'Group', required=True, select=1),
133
        'nomen_manda_2': fields.many2one('product.nomenclature', 'Family', required=True, select=1),
134
        'nomen_manda_3': fields.many2one('product.nomenclature', 'Root', required=True, select=1),
135
        'nomen_manda_0_s': fields.function(_get_nomen_s, method=True, type='many2one', relation='product.nomenclature', string='Main Type', fnct_search=_search_nomen_s, multi="nom_s"),
136
        'nomen_manda_1_s': fields.function(_get_nomen_s, method=True, type='many2one', relation='product.nomenclature', string='Group', fnct_search=_search_nomen_s, multi="nom_s"),
137
        'nomen_manda_2_s': fields.function(_get_nomen_s, method=True, type='many2one', relation='product.nomenclature', string='Family', fnct_search=_search_nomen_s, multi="nom_s"),
138
        'nomen_manda_3_s': fields.function(_get_nomen_s, method=True, type='many2one', relation='product.nomenclature', string='Root', fnct_search=_search_nomen_s, multi="nom_s"),
139
        'nomen_name': fields.function(_get_nomen_name, method=True, type='char', string='Nomenclature level', readonly=True),
140
        'product_uom_id': fields.many2one('product.uom', string='UoM', readonly=True),
141
        'frequency_id': fields.many2one('stock.frequence', string='Frequency', readonly=True),
142
        'delivery_lt': fields.float(digits=(16,2), string='Delivery LT', readonly=True),
143
        'order_coverage': fields.float(digits=(16,2), string='Order coverage', readonly=True),
144
        'safety_time': fields.float(digits=(16,2), string='Safety stock (in months)', readonly=True),
145
        'safety_stock': fields.float(digits=(16,2), string='Safety stock', readonly=True),
146
        'consumption': fields.char(size=64, string='Consumption', readonly=True),
147
        'total_stock': fields.function(_get_stock, method=True, type='float', string='Total stock', readonly=True, multi='stock'),
148
        'stock': fields.function(_get_stock, method=True, type='float', string='Stock (stock & children)', readonly=True, multi='stock'),
149
        'intermediate_stock': fields.function(_get_stock, method=True, type='float', string='ISi stocks', readonly=True, multi='stock'),
150
        'consumption_stock': fields.function(_get_stock, method=True, type='float', string='CUi stocks', readonly=True, multi='stock'),
151
        'amc': fields.function(_get_stock, method=True, type='float', string='AMC', readonly=True, multi='stock'),
152
        'moh': fields.function(_get_stock, method=True, type='float', string='MoH', readonly=True, multi='stock'),
153
        'fmc': fields.function(_get_stock, method=True, type='float', string='FMC', readonly=True, multi='stock'),
154
    }
155
    
156
    def init(self, cr):
157
        '''
158
        Creates the SQL view on database
159
        '''
160
        tools.drop_view_if_exists(cr, 'order_cycle_rules_report')
161
        cr.execute("""
162
            CREATE OR REPLACE view order_cycle_rules_report AS (
163
                SELECT 
164
                    row_number() OVER(ORDER BY line.product_id) AS id,
165
                    min.id AS rule_id,
166
                    line.product_id AS product_id,
167
                    min.location_id AS location_id,
168
                    min.frequence_id AS frequency_id,
169
                    temp.uom_id AS product_uom_id,
170
                    min.leadtime AS delivery_lt,
171
                    min.order_coverage AS order_coverage,
172
                    min.safety_stock_time AS safety_time,
827.7.16 by Quentin THEURET
UF-1069 [FIX] Replenishment rules report : Move safety stock value from order cycle to order cycle line in sql_view
173
                    line.safety_stock AS safety_stock,
658.1.7 by Quentin THEURET
UF-857 [ADD] Add order cycle and automatic replenishment reports
174
                    CASE WHEN min.past_consumption = 't' THEN 'AMC' ELSE 'FMC' END consumption,
175
                    prod.default_code AS product_reference,
715.1.3 by Quentin THEURET
UF-925 [FIX] Fix development bug
176
                    temp.name AS product_name,
658.1.7 by Quentin THEURET
UF-857 [ADD] Add order cycle and automatic replenishment reports
177
                    temp.nomen_manda_0 AS nomen_manda_0,
178
                    temp.nomen_manda_1 AS nomen_manda_1,
179
                    temp.nomen_manda_2 AS nomen_manda_2,
180
                    temp.nomen_manda_3 AS nomen_manda_3
181
                FROM
182
                    stock_warehouse_order_cycle min
183
                    LEFT JOIN
827.7.15 by Quentin THEURET
UF-1069 [FIX] Replenishment rules report : Update the sql view to take into account the new products list on order cycle rules
184
                        stock_warehouse_order_cycle_line line
658.1.7 by Quentin THEURET
UF-857 [ADD] Add order cycle and automatic replenishment reports
185
                        ON
186
                        line.order_cycle_id = min.id
187
                    LEFT JOIN
188
                        product_product prod
189
                        ON
190
                        line.product_id = prod.id
191
                    LEFT JOIN
192
                        product_template temp
193
                        ON
194
                        prod.product_tmpl_id = temp.id
195
            )
196
            """)
197
    
198
order_cycle_rules_report()
199
713 by jf
[FIX] context None
200
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: