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

451.3.1 by chloups208
uf-655
1
# -*- coding: utf-8 -*-
2
##############################################################################
3
#
4
#    OpenERP, Open Source Management Solution
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
5
#    Copyright (C) 2011 TeMPO Consulting, MSF
451.3.1 by chloups208
uf-655
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
2038.1.8 by Quentin THEURET
REF-78 [FIX] Fixed issue with partial incoming shipment processing by the sync. engine
22
import netsvc
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
23
import time
451.3.1 by chloups208
uf-655
24
from osv import osv, fields
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
25
from osv.orm import browse_record
451.3.1 by chloups208
uf-655
26
from tools.translate import _
2449.2.3 by duy.vo at msf
US-28: Added a check if the instance is RW, warning when cancel
27
from order_types.stock import check_rw_warning
451.3.1 by chloups208
uf-655
28
451.3.3 by chloups208
uf-655
29
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
30
class stock_picking_processing_info(osv.osv_memory):
31
    _name = 'stock.picking.processing.info'
32
33
    _columns = {
34
        'picking_id': fields.many2one(
35
            'stock.picking',
36
            string='Picking',
37
            required=True,
38
            readonly=True,
39
        ),
40
        'progress_line': fields.char(
41
            size=64,
42
            string='Processing of lines',
43
            readonly=True,
44
        ),
45
        'create_invoice': fields.char(
46
            size=64,
47
            string='Create invoice',
48
            readonly=True,
49
        ),
50
        'create_bo': fields.char(
51
            size=64,
52
            string='Create Backorder',
53
            readonly=True,
54
        ),
55
        'close_in': fields.char(
56
            size=64,
57
            string='Close IN',
58
            readonly=True,
59
        ),
60
        'prepare_pick': fields.char(
61
            size=64,
62
            string='Prepare picking ticket',
63
            readonly=True,
64
        ),
65
        'start_date': fields.datetime(
66
            string='Date start',
67
            readonly=True,
68
        ),
69
        'end_date': fields.datetime(
70
            string='Date end',
71
            readonly=True,
72
        ),
2264.1.2 by Quentin THEURET
UF-2485 [FIX] There was no possibility to re-set an incoming processing that raised an error.
73
        'error_msg': fields.text(
2264.1.1 by Quentin THEURET
UF-2485 [FIX] If an error was raised during the incoming shipment processing, no error was displayed on the processing wizard.
74
            string='Error',
75
            readonly=True,
76
        ),
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
77
    }
2222 by jf
UTP-1139 [IMP] Performance issue of the Orders sourcing tool
78
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
79
    _defaults = {
80
        'progress_line': _('Not started'),
81
        'create_invoice': _('Not started'),
82
        'create_bo': _('Not started'),
83
        'close_in': _('Not started'),
84
        'prepare_pick': _('Not started'),
2209.5.3 by Quentin THEURET
UTP-1147 [IMP] Now, it's possible to check the processing of an Incoming shipment and other actions are blocked (cancel of the IN, cancel of the move)
85
        'end_date': False,
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
86
    }
87
88
    def refresh(self, cr, uid, ids, context=None):
89
        '''
90
        Just refresh the current page
91
        '''
92
        return {
93
            'type': 'ir.actions.act_window',
94
            'res_model': self._name,
95
            'res_id': ids[0],
96
            'view_type': 'form',
97
            'view_mode': 'form',
2209.5.3 by Quentin THEURET
UTP-1147 [IMP] Now, it's possible to check the processing of an Incoming shipment and other actions are blocked (cancel of the IN, cancel of the move)
98
            'target': 'new',
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
99
            'context': context,
100
        }
101
102
    def close(self, cr, uid, ids, context=None):
103
        '''
104
        Just close the page
105
        '''
2209.5.3 by Quentin THEURET
UTP-1147 [IMP] Now, it's possible to check the processing of an Incoming shipment and other actions are blocked (cancel of the IN, cancel of the move)
106
        if context is None:
107
            context = {}
108
109
        if isinstance(ids, (int, long)):
110
            ids = [ids]
111
112
        mem_brw = self.browse(cr, uid, ids[0], context=context)
113
        view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'view_picking_in_form')[1]
2630.2.1 by Quentin THEURET
US-612 [FIX] Return to the IN form view if user closed the processing wizard and disallow possibility to process two times the same IN
114
        tree_view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'view_picking_in_tree')[1]
115
        src_view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'view_picking_in_search')[1]
116
        context.update({'picking_type': 'incoming', 'view_id': view_id})
117
        return {
118
            'type': 'ir.actions.act_window',
119
            'res_model': 'stock.picking',
120
            'view_id': [view_id, tree_view_id],
121
            'view_type': 'form',
2630.2.2 by Quentin THEURET
US-612 [FIX] Return the form view first
122
            'view_mode': 'form,tree',
2630.2.1 by Quentin THEURET
US-612 [FIX] Return to the IN form view if user closed the processing wizard and disallow possibility to process two times the same IN
123
            'search_view_id': src_view_id,
124
            'target': 'same',
125
            'domain': [('type', '=', 'in')],
126
            'res_id': [mem_brw.picking_id.id],
127
            'context': context,
128
        }
2264.1.2 by Quentin THEURET
UF-2485 [FIX] There was no possibility to re-set an incoming processing that raised an error.
129
130
    def reset_incoming(self, cr, uid, ids, context=None):
131
        '''
132
        Delete the processing wizard and close the page
133
        '''
134
        if context is None:
135
            context = {}
136
137
        if isinstance(ids, (int, long)):
138
            ids = [ids]
139
140
        res = self.close(cr, uid, ids, context=context)
141
142
        self.unlink(cr, uid, ids, context=context)
143
144
        return res
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
145
146
stock_picking_processing_info()
147
148
451.3.3 by chloups208
uf-655
149
class stock_move(osv.osv):
150
    '''
151
    new function to get mirror move
152
    '''
153
    _inherit = 'stock.move'
154
    _columns = {'line_number': fields.integer(string='Line', required=True),
451.3.23 by chloups208
uf-655 work without out object
155
                'change_reason': fields.char(string='Change Reason', size=1024, readonly=True),
1422.15.4 by Quentin THEURET
UF-1616 [IMP] Update OUT stock moves at IN processing even if there are some stock moves for one IN stock moves
156
                'in_out_updated': fields.boolean(string='IN update OUT'),
1908.1.4 by duy.vo at msf
UTP-972: Added a new field to manage the partial ship
157
                'original_qty_partial': fields.integer(string='Original Qty for Partial process - only for sync and partial processed line', required=False),
451.3.3 by chloups208
uf-655
158
                }
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
159
    _defaults = {
160
        'line_number': 0,
161
        'in_out_updated': False,
162
        'original_qty_partial': -1,
163
    }
1394.2.4 by Quentin THEURET
UF-1753 [IMP] Order of stock move displaying
164
    _order = 'line_number, date_expected desc, id'
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
165
1105.3.13 by chloups208
uf-1191 we use copy_data instead of copy in order to set line_number to False if not specified so original value will not be copied and a fresh sequence value used because copy_data is called when main object (ie picking/po/...) is copied, but copy of line object isn't. so when we copy a sale order, corresponding lines have fresh sequencing
166
    def copy_data(self, cr, uid, id, defaults=None, context=None):
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
167
        '''
1449.3.8 by matthieu.choplin at msf
[FIX] uf-1797: if we are on an Incoming Shipment, reset all the m2o fields to False when we dupliacte it
168
        If the line_number is not in the defaults, we set it to False.
1449.3.12 by matthieu.choplin at msf
[FIX] uf-1797: add a tag from the web to reset certain values on the copy of the picking and the stock move
169
        If we are on an Incoming Shipment: we reset purchase_line_id field
1449.3.8 by matthieu.choplin at msf
[FIX] uf-1797: if we are on an Incoming Shipment, reset all the m2o fields to False when we dupliacte it
170
        and we set the location_dest_id to INPUT.
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
171
        '''
172
        if defaults is None:
173
            defaults = {}
174
        if context is None:
175
            context = {}
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
176
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
177
        # we set line_number, so it will not be copied in copy_data - keepLineNumber - the original Line Number will be kept
178
        if 'line_number' not in defaults and not context.get('keepLineNumber', False):
179
            defaults.update({'line_number': False})
1449.3.12 by matthieu.choplin at msf
[FIX] uf-1797: add a tag from the web to reset certain values on the copy of the picking and the stock move
180
        # the tag 'from_button' was added in the web client (openerp/controllers/form.py in the method duplicate) on purpose
181
        if context.get('from_button'):
1449.3.10 by matthieu.choplin at msf
[FIX] uf-1797: target only the fields (m2o) for the tickets
182
            # UF-1797: when we duplicate a doc we delete the link with the poline
2542.3.1 by Quentin THEURET
US-405 [FIX] If a line is split during the incoming shipment processing, and if this line comes from an Internal request, the generated move in internal move doesn't have the good destination location
183
            if 'purchase_line_id' not in defaults:
184
                defaults.update(purchase_line_id=False)
1789.5.3 by Quentin THEURET
UTP-833 [FIX] At picking ticket or internal move duplication, don't change the destination location
185
            if context.get('subtype', False) == 'incoming':
186
                # we reset the location_dest_id to 'INPUT' for the 'incoming shipment'
187
                input_loc = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'msf_cross_docking', 'stock_location_input')[1]
188
                defaults.update(location_dest_id=input_loc)
1105.3.13 by chloups208
uf-1191 we use copy_data instead of copy in order to set line_number to False if not specified so original value will not be copied and a fresh sequence value used because copy_data is called when main object (ie picking/po/...) is copied, but copy of line object isn't. so when we copy a sale order, corresponding lines have fresh sequencing
189
        return super(stock_move, self).copy_data(cr, uid, id, defaults, context=context)
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
190
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
191
    def unlink(self, cr, uid, ids, context=None):
192
        '''
193
        check the numbering on deletion
194
        '''
195
        # Some verifications
196
        if context is None:
197
            context = {}
198
        if isinstance(ids, (int, long)):
199
            ids = [ids]
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
200
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
201
        # objects
202
        tools_obj = self.pool.get('sequence.tools')
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
203
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
204
        if not context.get('skipResequencing', False):
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
205
            # re sequencing only happen if purchase order is draft (behavior 1)
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
206
            # get ids with corresponding po at draft state
207
            draft_not_wkf_ids = self.allow_resequencing(cr, uid, ids, context=context)
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
208
            tools_obj.reorder_sequence_number_from_unlink(
209
                cr,
210
                uid,
211
                draft_not_wkf_ids,
212
                'stock.picking',
213
                'move_sequence_id',
214
                'stock.move',
215
                'picking_id',
216
                'line_number',
217
                context=context,
218
            )
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
219
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
220
        return super(stock_move, self).unlink(cr, uid, ids, context=context)
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
221
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
222
    def allow_resequencing(self, cr, uid, ids, context=None):
223
        '''
224
        define if a resequencing has to be performed or not
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
225
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
226
        return the list of ids for which resequencing will can be performed
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
227
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
228
        linked to Picking + Picking draft + not linked to Po/Fo
229
        '''
230
        # objects
231
        pick_obj = self.pool.get('stock.picking')
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
232
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
233
        resequencing_ids = [x.id for x in self.browse(cr, uid, ids, context=context)
234
                            if x.picking_id and pick_obj.allow_resequencing(cr, uid, x.picking_id, context=context)]
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
235
        return resequencing_ids
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
236
1105.3.17 by chloups208
uf-1191 added hook for modification of moves during chained picking + correction of resequencing msf_tools
237
    def _create_chained_picking_move_values_hook(self, cr, uid, context=None, *args, **kwargs):
238
        '''
239
        Please copy this to your module's method also.
240
        This hook belongs to the action_process method from stock>stock.py>stock_picking
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
241
1105.3.17 by chloups208
uf-1191 added hook for modification of moves during chained picking + correction of resequencing msf_tools
242
        - set the line number of the original picking, could have used the keepLineNumber flag, but used hook to modify original class minimally
243
        '''
244
        if context is None:
245
            context = {}
246
        move_data = super(stock_move, self)._create_chained_picking_move_values_hook(cr, uid, context=context, *args, **kwargs)
247
        # get move reference
248
        move = kwargs['move']
249
        # set the line number from original stock move
250
        move_data.update({'line_number': move.line_number})
251
        return move_data
1287.13.1 by matthieu.choplin at msf
[utp-262] add a hook on the method create_chained_picking so that the location_requestor_id defined in the IR is retrieved in the INTERNAL stock move
252
253
    def _get_location_for_internal_request(self, cr, uid, context=None, **kwargs):
254
        '''
255
        Get the requestor_location_id in case of IR to update the location_dest_id of each move
256
        '''
2151.3.1 by duy.vo at msf
UFTP-186: Added the super call to get location requestor
257
        location_dest_id = super(stock_move, self)._get_location_for_internal_request(cr, uid, context=context, **kwargs)
1287.13.3 by matthieu.choplin at msf
[utp-262] hook for updating the location_dest_id on the internal move lines to take the Requestor Location of the IR
258
        move = kwargs['move']
259
        if move.purchase_line_id:
1287.13.15 by matthieu.choplin at msf
[utp-262] fix the too heavy code (too many browse and search) with a more sophisticated 'if'
260
            proc = move.purchase_line_id.procurement_id
261
            if proc and proc.sale_order_line_ids and proc.sale_order_line_ids[0].order_id and proc.sale_order_line_ids[0].order_id.procurement_request:
2629.3.3 by Quentin THEURET
US-604 [FIX] When the destination type is changed from 'Cross-docking' to 'Stock' on the incoming shipment processor, if the request comes from an IR to External location, don't put the requestor location as destination location of the automatic generated INT, but put the Stock/LOG/MED location
262
                if proc.sale_order_line_ids[0].order_id.location_requestor_id.usage != 'customer':
263
                    location_dest_id = proc.sale_order_line_ids[0].order_id.location_requestor_id.id
1287.13.1 by matthieu.choplin at msf
[utp-262] add a hook on the method create_chained_picking so that the location_requestor_id defined in the IR is retrieved in the INTERNAL stock move
264
        return location_dest_id
265
1105.3.18 by chloups208
uf-1191 stock move do partial + stock picking do partial = the line number is kept during picking processing for internal and starnd outgoing delivery - backorder keeps original numbering
266
    def _do_partial_hook(self, cr, uid, ids, context, *args, **kwargs):
267
        '''
268
        hook to update defaults data
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
269
1105.3.18 by chloups208
uf-1191 stock move do partial + stock picking do partial = the line number is kept during picking processing for internal and starnd outgoing delivery - backorder keeps original numbering
270
        - update the line number, keep original line number
271
        >> performed for all cases (too few (copy - new numbering policy), complete (simple update - no impact), to many (simple update - no impact)
272
        '''
273
        # variable parameters
274
        move = kwargs.get('move', False)
275
        assert move, 'delivery_mechanism.py >> stock_move: _do_partial_hook - missing move'
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
276
1105.3.18 by chloups208
uf-1191 stock move do partial + stock picking do partial = the line number is kept during picking processing for internal and starnd outgoing delivery - backorder keeps original numbering
277
        # calling super method
278
        defaults = super(stock_move, self)._do_partial_hook(cr, uid, ids, context, *args, **kwargs)
279
        assert defaults is not None, 'delivery_mechanism.py >> stock_move: _do_partial_hook - missing defaults'
280
        # update the line number, copy original line_number value
281
        defaults.update({'line_number': move.line_number})
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
282
1105.3.18 by chloups208
uf-1191 stock move do partial + stock picking do partial = the line number is kept during picking processing for internal and starnd outgoing delivery - backorder keeps original numbering
283
        return defaults
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
284
451.3.19 by chloups208
uf-655 more tests
285
    def get_mirror_move(self, cr, uid, ids, data_back, context=None):
451.3.3 by chloups208
uf-655
286
        '''
287
        return a dictionary with IN for OUT and OUT for IN, if exists, False otherwise
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
288
451.3.3 by chloups208
uf-655
289
        only one mirror object should exist for each object (to check)
290
        return objects which are not done
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
291
451.3.16 by chloups208
uf-655 more tests
292
        same sale_line_id/purchase_line_id - same product - same quantity
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
293
451.3.3 by chloups208
uf-655
294
        IN: move -> po line -> procurement -> so line -> move
295
        OUT: move -> so line -> procurement -> po line -> move
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
296
451.3.3 by chloups208
uf-655
297
        I dont use move.move_dest_id because of back orders both on OUT and IN sides
298
        '''
299
        if context is None:
300
            context = {}
451.3.15 by chloups208
uf-655: change product + tests
301
        if isinstance(ids, (int, long)):
302
            ids = [ids]
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
303
451.3.24 by chloups208
uf-655 cancel and update OUT
304
        # objects
451.3.3 by chloups208
uf-655
305
        so_line_obj = self.pool.get('sale.order.line')
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
306
451.3.3 by chloups208
uf-655
307
        res = {}
308
        for obj in self.browse(cr, uid, ids, context=context):
1422.15.8 by Quentin THEURET
UF-1616 [FIX] Fix error raised by unit tests
309
            res[obj.id] = {'move_id': False, 'picking_id': False, 'picking_version': 0, 'quantity': 0, 'moves': []}
451.3.3 by chloups208
uf-655
310
            if obj.picking_id and obj.picking_id.type == 'in':
311
                # we are looking for corresponding OUT move from sale order line
312
                if obj.purchase_line_id:
313
                    # linekd to a po
314
                    if obj.purchase_line_id.procurement_id:
315
                        # on order
316
                        procurement_id = obj.purchase_line_id.procurement_id.id
317
                        # find the corresponding sale order line
318
                        so_line_ids = so_line_obj.search(cr, uid, [('procurement_id', '=', procurement_id)], context=context)
827.5.1 by chloups208
uf-645 new process folder in sale_override + corrected delivery mechanism, when replenishment rule, we have procurement but no corresponding sale order line
319
                        # if the procurement comes from replenishment rules, there will be a procurement, but no associated sale order line
320
                        # we therefore do not raise an exception, but handle the case only if sale order lines are found
321
                        if so_line_ids:
322
                            # find the corresponding OUT move
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
323
                            move_ids = self.search(cr, uid, [('product_id', '=', data_back['product_id']),
324
                                                             ('state', 'in', ('assigned', 'confirmed')),
1422.15.4 by Quentin THEURET
UF-1616 [IMP] Update OUT stock moves at IN processing even if there are some stock moves for one IN stock moves
325
                                                             ('sale_line_id', '=', so_line_ids[0]),
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
326
                                                             ('in_out_updated', '=', False),
327
                                                             ('picking_id.type', '=', 'out'),
328
                                                             ('processed_stock_move', '=', False),
329
                                                             ], order="state desc", context=context)
827.5.1 by chloups208
uf-645 new process folder in sale_override + corrected delivery mechanism, when replenishment rule, we have procurement but no corresponding sale order line
330
                            # list of matching out moves
331
                            integrity_check = []
332
                            for move in self.browse(cr, uid, move_ids, context=context):
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
333
                                pick = move.picking_id
334
                                cond1 = move.picking_id.subtype == 'standard'
2038.1.3 by Quentin THEURET
REF-61 [FIX] Fixed bad cleaning that broke the update of PICK/OUT at IN reception
335
                                cond2 = move.product_qty != 0.00 and pick.subtype == 'picking' and not pick.backorder_id and pick.state == 'draft'
827.5.1 by chloups208
uf-645 new process folder in sale_override + corrected delivery mechanism, when replenishment rule, we have procurement but no corresponding sale order line
336
                                # move from draft picking or standard picking
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
337
                                if cond2 or cond1:
1279.2.1 by chloups208
uf-1534 we mark the stock moves which are completely or partially processed (process incoming, process outgoing, create picking ticket) + when OUT is updated at IN processing, we first check if the stock move we are trying to update has already been processed, if this is the case, the stock move is not updated
338
                                    integrity_check.append(move)
827.5.1 by chloups208
uf-645 new process folder in sale_override + corrected delivery mechanism, when replenishment rule, we have procurement but no corresponding sale order line
339
                            # return the first one matching
1279.2.3 by chloups208
uf-1534 if (one of) the corresponding move is already processed, partially or completely, the process of IN does not udpate the OUT move, when the move is not updated a message is displayed identifying the case
340
                            if integrity_check:
341
                                if all([not move.processed_stock_move for move in integrity_check]):
342
                                    # the out stock moves (draft picking or std out) have not yet been processed, we can therefore update them
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
343
                                    res[obj.id].update({
344
                                        'move_id': integrity_check[0].id,
345
                                        'moves': integrity_check,
346
                                        'picking_id': integrity_check[0].picking_id.id,
347
                                        'picking_version': integrity_check[0].picking_id.update_version_from_in_stock_picking,
348
                                        'quantity': integrity_check[0].product_qty,
349
                                    })
1279.2.3 by chloups208
uf-1534 if (one of) the corresponding move is already processed, partially or completely, the process of IN does not udpate the OUT move, when the move is not updated a message is displayed identifying the case
350
                                else:
351
                                    # the corresponding OUT move have been processed completely or partially,, we do not update the OUT
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
352
                                    msg_log = _('The Stock Move %s from %s has already been processed and is '
353
                                                'therefore not updated.') % (integrity_check[0].name, integrity_check[0].picking_id.name)
354
                                    self.log(cr, uid, integrity_check[0].id, msg_log)
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
355
451.3.16 by chloups208
uf-655 more tests
356
            else:
451.3.3 by chloups208
uf-655
357
                # we are looking for corresponding IN from on_order purchase order
451.3.16 by chloups208
uf-655 more tests
358
                assert False, 'This method is not implemented for OUT or Internal moves'
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
359
451.3.3 by chloups208
uf-655
360
        return res
1851.9.2 by Quentin THEURET
UTP-647 [IMP] Create and close automatically the internal move after an incoming shipment direct to stock
361
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
362
    def create_data_back(self, move):
363
        '''
364
        build data_back dictionary
365
        '''
366
        res = {'id': move.id,
367
               'name': move.product_id.partner_ref,
368
               'product_id': move.product_id.id,
369
               'product_uom': move.product_uom.id,
370
               'product_qty': move.product_qty,
2703.11.1 by Quentin THEURET
UF-2246 [FIX] Keep batch number, expiry date and asset, if set on the initial IN, to the Backorder
371
               'prodlot_id': move.prodlot_id and move.prodlot_id.id or False,
372
               'asset_id': move.asset_id and move.asset_id.id or False,
373
               'expired_date': move.expired_date or False,
2629.3.5 by Quentin THEURET
US-604 [IMP] If the destination type is changed at IN reception, keep the inital destiantion type for backordered moves
374
               'location_dest_id': move.location_dest_id.id,
375
               'move_cross_docking_ok': move.move_cross_docking_ok,
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
376
               }
377
        return res
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
378
1851.9.2 by Quentin THEURET
UTP-647 [IMP] Create and close automatically the internal move after an incoming shipment direct to stock
379
    def hook__create_chained_picking(self, cr, uid, pick_values, picking):
380
        res = super(stock_move, self).hook__create_chained_picking(cr, uid, pick_values, picking)
381
382
        if picking:
383
            res['auto_picking'] = picking.type == 'in' and picking.move_lines[0]['direct_incoming']
384
385
        return res
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
386
451.3.3 by chloups208
uf-655
387
stock_move()
388
451.3.1 by chloups208
uf-655
389
390
class stock_picking(osv.osv):
391
    '''
392
    do_partial modification
393
    '''
394
    _inherit = 'stock.picking'
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
395
396
    def _get_progress_memory(self, cr, uid, ids, field_name, args, context=None):
397
        '''
398
        Returns the ID of the stock.picking.processing.info osv_memory linked
399
        to the picking.
400
        '''
401
        mem_obj = self.pool.get('stock.picking.processing.info')
402
403
        if context is None:
404
            context = {}
405
406
        if isinstance(ids, (int, long)):
407
            ids = [ids]
408
409
        res = {}
410
        for pick_id in ids:
2209.5.4 by Quentin THEURET
UTP-1147 [IMP] Add a warning message on the incoming shipment when the processing is in progress
411
            res[pick_id] = {
412
                'progress_memory': -1,
413
                'progress_memory_not_done': 0,
2264.1.2 by Quentin THEURET
UF-2485 [FIX] There was no possibility to re-set an incoming processing that raised an error.
414
                'progress_memory_error': 0,
2209.5.4 by Quentin THEURET
UTP-1147 [IMP] Add a warning message on the incoming shipment when the processing is in progress
415
            }
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
416
            mem_ids = mem_obj.search(cr, uid, [
417
                ('picking_id', '=', pick_id),
2264.10.1 by Quentin THEURET
UF-2487 [FIX] Remove the In progress message on the incoming shipment when the incoming shipment is done
418
                ('picking_id.state', '!=', 'done'),
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
419
            ], order='start_date desc', context=context)
420
            if mem_ids:
2209.5.4 by Quentin THEURET
UTP-1147 [IMP] Add a warning message on the incoming shipment when the processing is in progress
421
                res[pick_id]['progress_memory'] = mem_ids[0]
422
                nd_ids = mem_obj.search(cr, uid, [
423
                    ('end_date', '=', False),
424
                    ('id', 'in', mem_ids),
425
                ], context=context)
426
                if nd_ids:
427
                    res[pick_id]['progress_memory_not_done'] = 1
2264.1.2 by Quentin THEURET
UF-2485 [FIX] There was no possibility to re-set an incoming processing that raised an error.
428
                    for nd in mem_obj.read(cr, uid, nd_ids, ['error_msg'], context=context):
429
                        if nd['error_msg']:
430
                            res[pick_id]['progress_memory_error'] = 1
431
                            break
2264.1.1 by Quentin THEURET
UF-2485 [FIX] If an error was raised during the incoming shipment processing, no error was displayed on the processing wizard.
432
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
433
        return res
434
2209.5.3 by Quentin THEURET
UTP-1147 [IMP] Now, it's possible to check the processing of an Incoming shipment and other actions are blocked (cancel of the IN, cancel of the move)
435
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
436
    _columns = {
437
        'move_sequence_id': fields.many2one(
438
            'ir.sequence',
439
            string='Moves Sequence',
440
            help="This field contains the information related to the numbering of the moves of this picking.",
441
            required=True,
442
            ondelete='cascade',
443
        ),
444
        'change_reason': fields.char(
445
            string='Change Reason',
446
            size=1024,
447
            readonly=True,
448
        ),
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
449
        'progress_memory': fields.function(
450
            _get_progress_memory,
451
            method=True,
2209.5.4 by Quentin THEURET
UTP-1147 [IMP] Add a warning message on the incoming shipment when the processing is in progress
452
            string='Has processing info',
453
            type='integer',
454
            store=False,
455
            readonly=True,
456
            multi='process',
457
        ),
458
        'progress_memory_not_done': fields.function(
459
            _get_progress_memory,
460
            method=True,
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
461
            string='Is in progress',
2209.5.4 by Quentin THEURET
UTP-1147 [IMP] Add a warning message on the incoming shipment when the processing is in progress
462
            type='boolean',
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
463
            store=False,
464
            readonly=True,
2209.5.4 by Quentin THEURET
UTP-1147 [IMP] Add a warning message on the incoming shipment when the processing is in progress
465
            multi='process',
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
466
        ),
2264.1.1 by Quentin THEURET
UF-2485 [FIX] If an error was raised during the incoming shipment processing, no error was displayed on the processing wizard.
467
        'progress_memory_error': fields.function(
468
            _get_progress_memory,
469
            method=True,
470
            string='Processing error',
2264.1.2 by Quentin THEURET
UF-2485 [FIX] There was no possibility to re-set an incoming processing that raised an error.
471
            type='boolean',
2264.1.1 by Quentin THEURET
UF-2485 [FIX] If an error was raised during the incoming shipment processing, no error was displayed on the processing wizard.
472
            store=False,
473
            readonly=True,
474
            multi='process',
475
        ),
2478.4.3 by Quentin THEURET
US-211 [FIX] At IN processing, if the IN is a DPO IN and processed by the sync. engine, put the processed lines on a new IN and don't put this IN on 'Shipped Availabel' state
476
        'in_dpo': fields.boolean(
477
            string='Incoming shipment of a DPO',
478
            readonly=True,
479
        ),
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
480
    }
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
481
2209.5.3 by Quentin THEURET
UTP-1147 [IMP] Now, it's possible to check the processing of an Incoming shipment and other actions are blocked (cancel of the IN, cancel of the move)
482
    def go_to_processing_wizard(self, cr, uid, ids, context=None):
483
        '''
484
        If the stock.picking has a stock.picking.processing.info linked to it,
485
        open this wizard.
486
        '''
487
        if context is None:
488
            context = {}
489
490
        if isinstance(ids, (int, long)):
491
            ids = [ids]
492
493
        for picking in self.browse(cr, uid, ids, context=context):
494
            if picking.progress_memory > 0:
495
                return {
496
                    'type': 'ir.actions.act_window',
497
                    'res_model': 'stock.picking.processing.info',
498
                    'res_id': int(picking.progress_memory),
499
                    'view_type': 'form',
500
                    'view_mode': 'form',
501
                    'target': 'new',
502
                    'context': context,
503
                }
2222 by jf
UTP-1139 [IMP] Performance issue of the Orders sourcing tool
504
2209.5.3 by Quentin THEURET
UTP-1147 [IMP] Now, it's possible to check the processing of an Incoming shipment and other actions are blocked (cancel of the IN, cancel of the move)
505
        raise osv.except_osv(
506
            _('Error'),
507
            _('The picking has no processing in progress or is already processed'),
508
        )
509
451.3.5 by chloups208
uf-655
510
    def _stock_picking_action_process_hook(self, cr, uid, ids, context=None, *args, **kwargs):
511
        '''
512
        Please copy this to your module's method also.
513
        This hook belongs to the action_process method from stock>stock.py>stock_picking
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
514
451.3.5 by chloups208
uf-655
515
        - allow to modify the data for wizard display
516
        '''
451.3.6 by chloups208
uf-655
517
        if context is None:
518
            context = {}
451.3.15 by chloups208
uf-655: change product + tests
519
        if isinstance(ids, (int, long)):
520
            ids = [ids]
451.3.5 by chloups208
uf-655
521
        res = super(stock_picking, self)._stock_picking_action_process_hook(cr, uid, ids, context=context, *args, **kwargs)
522
        wizard_obj = self.pool.get('wizard')
2204.8.1 by Quentin THEURET
UTP-1115 [IMP] Change calls of open_wizard() method of wizard object because one of the attributes has been changed : type -> w_type
523
        res = wizard_obj.open_wizard(cr, uid, ids, w_type='update', context=dict(context,
451.3.5 by chloups208
uf-655
524
                                                                               wizard_ids=[res['res_id']],
525
                                                                               wizard_name=res['name'],
526
                                                                               model=res['res_model'],
451.3.8 by chloups208
uf-655
527
                                                                               step='default'))
451.3.5 by chloups208
uf-655
528
        return res
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
529
451.3.3 by chloups208
uf-655
530
    def create(self, cr, uid, vals, context=None):
531
        '''
532
        create the sequence for the numbering of the lines
533
        '''
1449.3.12 by matthieu.choplin at msf
[FIX] uf-1797: add a tag from the web to reset certain values on the copy of the picking and the stock move
534
        if not vals:
535
            vals = {}
451.3.3 by chloups208
uf-655
536
        # object
537
        seq_pool = self.pool.get('ir.sequence')
538
        po_obj = self.pool.get('purchase.order')
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
539
451.3.3 by chloups208
uf-655
540
        new_seq_id = self.create_sequence(cr, uid, vals, context=context)
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
541
        vals.update({'move_sequence_id': new_seq_id, })
451.3.3 by chloups208
uf-655
542
        # if from order, we udpate the sequence to match the order's one
543
        # line number correspondance to be checked with Magali
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
544
        # I keep that code deactivated, as when the picking is wkf, hide_new_button must always be true
451.3.3 by chloups208
uf-655
545
        seq_value = False
546
        if vals.get('purchase_id') and False:
547
            seq_id = po_obj.read(cr, uid, [vals.get('purchase_id')], ['sequence_id'], context=context)[0]['sequence_id'][0]
548
            seq_value = seq_pool.read(cr, uid, [seq_id], ['number_next'], context=context)[0]['number_next']
549
        elif vals.get('sale_id') and False:
550
            seq_id = po_obj.read(cr, uid, [vals.get('sale_id')], ['sequence_id'], context=context)[0]['sequence_id'][0]
551
            seq_value = seq_pool.read(cr, uid, [seq_id], ['number_next'], context=context)[0]['number_next']
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
552
451.3.3 by chloups208
uf-655
553
        if seq_value:
554
            # update sequence value of stock picking to match order's one
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
555
            seq_pool.write(cr, uid, [new_seq_id], {'number_next': seq_value, })
556
451.3.3 by chloups208
uf-655
557
        return super(stock_picking, self).create(cr, uid, vals, context=context)
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
558
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
559
    def allow_resequencing(self, cr, uid, pick_browse, context=None):
560
        '''
561
        allow resequencing criteria
562
        '''
563
        if pick_browse.state == 'draft' and not pick_browse.purchase_id and not pick_browse.sale_id:
564
            return True
565
        return False
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
566
1105.3.18 by chloups208
uf-1191 stock move do partial + stock picking do partial = the line number is kept during picking processing for internal and starnd outgoing delivery - backorder keeps original numbering
567
    def _do_partial_hook(self, cr, uid, ids, context, *args, **kwargs):
568
        '''
569
        hook to update defaults data
570
        '''
571
        # variable parameters
572
        move = kwargs.get('move')
573
        assert move, 'delivery_mechanism.py >> stock_picking: _do_partial_hook - missing move'
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
574
1105.3.18 by chloups208
uf-1191 stock move do partial + stock picking do partial = the line number is kept during picking processing for internal and starnd outgoing delivery - backorder keeps original numbering
575
        # calling super method
576
        defaults = super(stock_picking, self)._do_partial_hook(cr, uid, ids, context, *args, **kwargs)
577
        assert defaults is not None, 'delivery_mechanism.py >> stock_picking: _do_partial_hook - missing defaults'
578
        # update the line number, copy original line_number value
579
        defaults.update({'line_number': move.line_number})
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
580
581
        # UTP-972: Set the original total qty of the original move to the new partial move, for sync purpose only
1977.7.1 by Quentin THEURET
UF-2320 [FIX] Keep the quantity of the original stock move when process partially a stock move − We keep the quantity of the original stock move on the other stock move to get the good stock move on another sync. instance
582
        orig_qty = move.product_qty
583
        if move.original_qty_partial and move.original_qty_partial != -1:
584
            orig_qty = move.original_qty_partial
585
        defaults.update({'original_qty_partial': orig_qty})
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
586
1105.3.18 by chloups208
uf-1191 stock move do partial + stock picking do partial = the line number is kept during picking processing for internal and starnd outgoing delivery - backorder keeps original numbering
587
        return defaults
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
588
451.3.19 by chloups208
uf-655 more tests
589
    def _update_mirror_move(self, cr, uid, ids, data_back, diff_qty, out_move=False, context=None):
451.3.3 by chloups208
uf-655
590
        '''
591
        update the mirror move with difference quantity diff_qty
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
592
451.3.18 by chloups208
uf-655 more tests
593
        if out_move is provided, it is used for copy if another cannot be found (meaning the one provided does
594
        not fit anyhow)
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
595
546.2.4 by chloups208
uf-655 average cost computation
596
        # NOTE: the price is not update in OUT move according to average price computation. this is an open point.
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
597
451.3.16 by chloups208
uf-655 more tests
598
        if diff_qty < 0, the qty is decreased
599
        if diff_qty > 0, the qty is increased
451.3.3 by chloups208
uf-655
600
        '''
601
        # stock move object
602
        move_obj = self.pool.get('stock.move')
451.3.18 by chloups208
uf-655 more tests
603
        # first look for a move - we search even if we get out_move because out_move
604
        # may not be valid anymore (product changed) - get_mirror_move will validate it or return nothing
1279.2.5 by chloups208
uf-1534 update the version of the OUT when the IN updates it
605
        out_move_id = move_obj.get_mirror_move(cr, uid, [data_back['id']], data_back, context=context)[data_back['id']]['move_id']
451.3.18 by chloups208
uf-655 more tests
606
        if not out_move_id and out_move:
451.3.35 by chloups208
uf-655 created moves see their name updated, tests are updated for new inverted openerp logic for in backorders
607
            # copy existing out_move with move properties: - update the name of the stock move
451.3.37 by chloups208
uf-655 the new stock moves in OUT picking are confirmed (Not Available by default) - yml tests are updated to take po workflow integration into account when IN is canceled
608
            # the state is confirmed, we dont know if available yet - should be in input location before stock
451.3.35 by chloups208
uf-655 created moves see their name updated, tests are updated for new inverted openerp logic for in backorders
609
            values = {'name': data_back['name'],
610
                      'product_id': data_back['product_id'],
451.3.18 by chloups208
uf-655 more tests
611
                      'product_qty': 0,
546.2.3 by chloups208
uf-655 missing uos_qty for finance
612
                      'product_uos_qty': 0,
451.3.19 by chloups208
uf-655 more tests
613
                      'product_uom': data_back['product_uom'],
451.3.37 by chloups208
uf-655 the new stock moves in OUT picking are confirmed (Not Available by default) - yml tests are updated to take po workflow integration into account when IN is canceled
614
                      'state': 'confirmed',
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
615
                      'prodlot_id': False,  # reset batch number
616
                      'asset_id': False,  # reset asset
451.3.18 by chloups208
uf-655 more tests
617
                      }
618
            out_move_id = move_obj.copy(cr, uid, out_move, values, context=context)
619
        # update quantity
451.3.3 by chloups208
uf-655
620
        if out_move_id:
621
            # decrease/increase depending on diff_qty sign the qty by diff_qty
451.3.25 by chloups208
uf-655 cancel and update OUT
622
            data = move_obj.read(cr, uid, [out_move_id], ['product_qty', 'picking_id', 'name', 'product_uom'], context=context)[0]
623
            picking_out_name = data['picking_id'][1]
624
            stock_move_name = data['name']
625
            uom_name = data['product_uom'][1]
626
            present_qty = data['product_qty']
451.3.16 by chloups208
uf-655 more tests
627
            new_qty = max(present_qty + diff_qty, 0)
1349.25.13 by Quentin THEURET
UF-1627 [FIX] Fix unit tests errors
628
            if new_qty > 0.00 and present_qty != 0.00:
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
629
                new_move_id = move_obj.copy(cr, uid, out_move_id, {'product_qty': diff_qty,
1421.2.8 by Quentin THEURET
UTP-289 [IMP] Add change UoM on stock picking
630
                                                                   'product_uom': data_back['product_uom'],
631
                                                                   'product_uos': data_back['product_uom'],
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
632
                                                                   'product_uos_qty': diff_qty, }, context=context)
1349.25.13 by Quentin THEURET
UF-1627 [FIX] Fix unit tests errors
633
                move_obj.action_confirm(cr, uid, [new_move_id], context=context)
634
#                if present_qty == 0.00:
635
#                    move_obj.write(cr, uid, [out_move_id], {'state': 'draft'})
636
#                    move_obj.unlink(cr, uid, out_move_id, context=context)
637
            else:
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
638
                move_obj.write(cr, uid, [out_move_id], {'product_qty': new_qty,
1421.2.8 by Quentin THEURET
UTP-289 [IMP] Add change UoM on stock picking
639
                                                        'product_uom': data['product_uom'][0],
640
                                                        'product_uos': data['product_uom'][0],
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
641
                                                        'product_uos_qty': new_qty, }, context=context)
642
451.3.25 by chloups208
uf-655 cancel and update OUT
643
            # log the modification
644
            # log creation message
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
645
            msg_log = _('The Stock Move %s from %s has been updated to %s %s.') % (stock_move_name, picking_out_name, new_qty, uom_name)
646
            move_obj.log(cr, uid, out_move_id, msg_log)
451.3.3 by chloups208
uf-655
647
        # return updated move or False
648
        return out_move_id
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
649
652.3.8 by matthieu.choplin at msf
enable the location selection when you process an incoming shipment (and especially the choose between crossdocking or stock)
650
    def _do_incoming_shipment_first_hook(self, cr, uid, ids, context=None, *args, **kwargs):
651
        '''
652
        hook to update values for stock move if first encountered
653
        '''
654
        values = kwargs.get('values')
655
        assert values is not None, 'missing values'
656
        return values
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
657
658
    def _get_db_data_dict(self, cr, uid):
659
        """
660
        Get some data from data.xml file (like stock locations, Unifield setup...)
661
        """
662
        # Objects
663
        data_obj = self.pool.get('ir.model.data')
664
        loc_obj = self.pool.get('stock.location')
665
666
        setup = self.pool.get('unifield.setup.configuration').get_config(cr, uid)
667
668
        cd_loc = loc_obj.get_cross_docking_location(cr, uid)
669
        service_loc = loc_obj.get_service_location(cr, uid)
670
        non_stock = loc_obj.search(cr, uid, [('non_stockable_ok', '=', True)])
671
        if non_stock:
672
            non_stock = non_stock[0]
673
        input_loc = data_obj.get_object_reference(cr, uid, 'msf_cross_docking', 'stock_location_input')[1]
674
675
        db_data = {
676
            'setup': setup,
677
            'cd_loc': cd_loc,
678
            'service_loc': service_loc,
679
            'non_stock': non_stock,
680
            'input_loc': input_loc
681
        }
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
682
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
683
        return db_data
684
685
    def _compute_average_values(self, cr, uid, move, line, product_availability, context=None):
686
        """
687
        Compute the average price of the product according to processed quantities
688
        """
689
        # Objects
690
        uom_obj = self.pool.get('product.uom')
691
        currency_obj = self.pool.get('res.currency')
692
        product_obj = self.pool.get('product.product')
693
694
        if context is None:
695
            context = {}
696
697
        average_values = {}
698
2556.1.1 by Quentin THEURET
US-281 [FIX] Take the good currency when compute the IN price changement
699
        if move.price_currency_id:
700
            move_currency_id = move.price_currency_id.id
701
        else:
702
            move_currency_id = move.company_id.currency_id.id
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
703
        context['currency_id'] = move_currency_id
704
705
        qty = line.quantity
706
        if line.uom_id.id != line.product_id.uom_id.id:
707
            qty = uom_obj._compute_qty(cr, uid, line.uom_id.id, line.quantity, line.product_id.uom_id.id)
708
709
        product_availability.setdefault(line.product_id.id, line.product_id.qty_available)
710
711
        if qty > 0.00:
712
            new_price = line.cost
713
            # Recompute unit price if the currency used is not the functional currency
714
            if line.currency.id != move_currency_id:
715
                new_price = currency_obj.compute(cr, uid, line.currency.id, move_currency_id,
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
716
                                                 new_price, round=False, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
717
718
            # Recompute unit price if the UoM received is not the default UoM of the product
719
            if line.uom_id.id != line.product_id.uom_id.id:
720
                new_price = uom_obj._compute_price(cr, uid, line.uom_id.id, new_price,
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
721
                                                   line.product_id.uom_id.id)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
722
723
            new_std_price = 0.00
724
            if line.product_id.qty_available <= 0.00:
725
                new_std_price = new_price
726
            else:
727
                # Get the current price
1994.1.38 by Quentin THEURET
REF-27 [IMP] Improve the Outgoing delivery processing wizard
728
                current_price = product_obj.price_get(cr, uid, [line.product_id.id], 'standard_price', context=context)[line.product_id.id]
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
729
                # Check no division by zero
730
                if product_availability[line.product_id.id]:
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
731
                    new_std_price = ((current_price * product_availability[line.product_id.id])
732
                                     + (new_price * qty)) / (product_availability[line.product_id.id] + qty)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
733
2556.1.1 by Quentin THEURET
US-281 [FIX] Take the good currency when compute the IN price changement
734
            new_std_price = currency_obj.compute(cr, uid, line.currency.id, move.company_id.currency_id.id,
2556.1.3 by Quentin THEURET
US-281 [IMP] Bad computation of average cost of the product
735
                                                 new_std_price, round=True, context=context)
2556.1.1 by Quentin THEURET
US-281 [FIX] Take the good currency when compute the IN price changement
736
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
737
            # Write the field according to price type field
738
            product_obj.write(cr, uid, [line.product_id.id], {'standard_price': new_std_price})
2703.8.5 by Quentin THEURET
US-802 [IMP] Create a standard.price.track.changes record at reception and set the flag 'Manually changed' if the cost price has been changed on incoming shipment processing wizard
739
            pchanged = False
740
            # Is price changed ?
741
            if line.cost and move.purchase_line_id:
742
                p_price = move.purchase_line_id.price_unit
743
                pchanged = abs(p_price - line.cost) > 10**-3
2703.8.8 by Quentin THEURET
US-802 [FIX] Put the name of the real user in the Product cost price changes at Reception
744
            sptc_values = {
2703.8.5 by Quentin THEURET
US-802 [IMP] Create a standard.price.track.changes record at reception and set the flag 'Manually changed' if the cost price has been changed on incoming shipment processing wizard
745
                    'standard_price': new_std_price,
746
                    'old_price': line.product_id.standard_price,
747
                    'manually_changed': pchanged,
2703.8.8 by Quentin THEURET
US-802 [FIX] Put the name of the real user in the Product cost price changes at Reception
748
            }
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
749
750
            # Record the values that were chosen in the wizard, so they can be
751
            # used for inventory valuation of real-time valuation is enabled.
752
            average_values = {
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
753
                'price_unit': new_price,
754
                'price_currency_id': line.currency.id,
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
755
            }
756
2703.8.8 by Quentin THEURET
US-802 [FIX] Put the name of the real user in the Product cost price changes at Reception
757
        return average_values, sptc_values
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
758
759
    def _get_values_from_line(self, cr, uid, move, line, db_data, context=None):
760
        """
761
        Prepare the value for a processed move according to line values
762
        """
763
        # Objects
764
        uom_obj = self.pool.get('product.uom')
2308.20.9 by Quentin THEURET
UFTP-329 [FIX] Non stockable or service products are received on cross-docking and shouldn't
765
        pol_obj = self.pool.get('purchase.order.line')
766
        sol_obj = self.pool.get('sale.order.line')
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
767
768
        if context is None:
769
            context = {}
770
771
        wizard = line.wizard_id
772
773
        values = {
774
            'name': line.product_id.partner_ref,
775
            'product_id': line.product_id.id,
776
            'original_qty_partial': move.product_qty,
777
            'product_qty': line.quantity,
778
            'product_uom': line.uom_id.id,
779
            'product_uos_qty': line.quantity,
780
            'product_uos': line.uom_id.id,
781
            'prodlot_id': line.prodlot_id and line.prodlot_id.id or False,
2038.1.7 by Quentin THEURET
REF-79 [FIX] Fixed the issue on IN processing with a line with an asset form − An error was raised even if an asset form was set on the line
782
            'asset_id': line.asset_id and line.asset_id.id or False,
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
783
            'change_reason': line.change_reason,
784
            # Values from incoming wizard
785
            'direct_incoming': line.wizard_id.direct_incoming,
786
            # Values for Direct Purchase Order
787
            'sync_dpo': move.dpo_line_id and True or move.sync_dpo,
2478.4.6 by Quentin THEURET
US-211 [FIX] On IN, keep link to the DPO line at coordo to send the message of reception
788
            'dpo_line_id': False,
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
789
        }
2478.4.6 by Quentin THEURET
US-211 [FIX] On IN, keep link to the DPO line at coordo to send the message of reception
790
        if move.dpo_line_id:
791
            if isinstance(move.dpo_line_id, int):
792
                values['dpo_line_id'] = move.dpo_line_id
793
            else:
794
                values['dpo_line_id'] = move.dpo_line_id.id
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
795
796
        # UTP-872: Don't change the quantity if the move is canceled
797
        # If the quantity is changed to 0.00, a backorder is created
798
        # for canceled moves
799
        if move.state == 'cancel':
800
            values.update({
801
                'product_qty': move.product_qty,
802
                'product_uos_qty': move.product_uos_qty
803
            })
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
804
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
805
        # UTP-872: Added also the state into the move line if the state comes from the sync
806
        if line.state:
807
            values['state'] = line.state
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
808
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
809
        if line.cost:
810
            values['price_unit'] = line.cost
811
        elif line.uom_id.id != move.product_uom.id:
812
            new_price = uom_obj._compute_price(cr, uid, move.product_uom.id, move.price_unit, line.uom_id.id)
813
            values['price_unit'] = new_price
814
2308.20.9 by Quentin THEURET
UFTP-329 [FIX] Non stockable or service products are received on cross-docking and shouldn't
815
        service_non_stock_ok = False
2630.1.1 by Quentin THEURET
US-625 [FIX] At IN reception of a service product with destination type 'Cross-docking', the destination location of the move must be 'Service', not 'Cross-docking'
816
        if move.purchase_line_id and line.product_id.type in ('consu', 'service_recep'):
2308.20.9 by Quentin THEURET
UFTP-329 [FIX] Non stockable or service products are received on cross-docking and shouldn't
817
            sol_ids = pol_obj.get_sol_ids_from_pol_ids(cr, uid, [move.purchase_line_id.id], context=context)
818
            for sol_brw in sol_obj.browse(cr, uid, sol_ids, context=context):
819
                if sol_brw.order_id.procurement_request:
820
                    service_non_stock_ok = True
821
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
822
        # We check the dest_type for INCOMING shipment (and not the source_type which is reserved for OUTGOING shipment)
2308.20.9 by Quentin THEURET
UFTP-329 [FIX] Non stockable or service products are received on cross-docking and shouldn't
823
        if wizard.dest_type == 'to_cross_docking' and not service_non_stock_ok:
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
824
            if db_data.get('setup').allocation_setup == 'unallocated':
825
                raise osv.except_osv(
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
826
                    _('Error'),
827
                    _('You cannot made moves from/to Cross-docking locations when the Allocated stocks configuration is set to \'Unallocated\'.'),
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
828
                )
829
            # Below, "source_type" is only used for the outgoing shipment. We set it to "None" because by default it is
830
            # "default" and we do not want that info on INCOMING shipment
831
            wizard.source_type = None
832
            values.update({
833
                'location_dest_id': db_data.get('cd_loc'),
2629.3.6 by Quentin THEURET
US-604 [FIX] Don't keep the Cross-Docking value to the IN backorder
834
                'cd_from_bo': False,
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
835
            })
2308.20.9 by Quentin THEURET
UFTP-329 [FIX] Non stockable or service products are received on cross-docking and shouldn't
836
        elif wizard.dest_type == 'to_stock' or service_non_stock_ok:
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
837
            # Below, "source_type" is only used for the outgoing shipment. We set it to "None because by default it is
838
            # "default" and we do not want that info on INCOMING shipment
1994.1.35 by Quentin THEURET
REF-27 [IMP] Replace the osv.osv_memory wizard to process an incoming shipment by an osv.osv wizard
839
            if line.product_id.type == 'consu':
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
840
                values['location_dest_id'] = db_data.get('non_stock')
1994.1.35 by Quentin THEURET
REF-27 [IMP] Replace the osv.osv_memory wizard to process an incoming shipment by an osv.osv wizard
841
            elif line.product_id.type == 'service_recep':
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
842
                values['location_dest_id'] = db_data.get('service_loc')
843
            else:
844
                # treat moves towards STOCK if NOT SERVICE
845
                values['location_dest_id'] = db_data.get('input_loc')
846
847
            values['cd_from_bo'] = False
848
849
        if wizard.dest_type != 'to_cross_docking':
850
            values['direct_incoming'] = wizard.direct_incoming
851
852
        return values
853
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
854
    def update_processing_info(self, cr, uid, picking, prog_id=False, values=None, context=None):
855
        '''
856
        Update the osv_memory processing info object linked to picking ID.
857
858
        :param cr: Cursor to the database
2222 by jf
UTP-1139 [IMP] Performance issue of the Orders sourcing tool
859
        :param uid: ID of the user that calls the method
860
        :param picking: browse_record of a stock.picking or the ID of a
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
861
                        stock.picking
862
        :param prog_id: ID of a stock.picking.processing.info to update
863
        :param values: Dictoionary that contains the values to put on picking
864
                       processing object
865
        :param context: Context of the call
866
867
        :return: The ID of the stock.picking.processing.info that have been
868
                 updated.
869
        '''
870
        prog_obj = self.pool.get('stock.picking.processing.info')
871
2263.1.2 by Quentin THEURET
[FIX] Fixed use of bad key on context to check if we are on sync. process or not
872
        if context is None:
873
            context = {}
874
875
        if context.get('sync_message_execution', False):
2263.1.1 by Quentin THEURET
[FIX] Fix problen with IN processing wizard and synchronization engine
876
            return False
877
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
878
        if not prog_id:
879
            if not isinstance(picking, browse_record) and isinstance(picking, (int, long)):
880
                picking = self.browse(cr, uid, picking, context=context)
881
882
            prog_ids = prog_obj.search(cr, uid, [('picking_id', '=', picking.id)], context=context)
883
            if prog_ids:
884
                prog_id = prog_ids[0]
885
            else:
886
                prog_id = prog_obj.create(cr, uid, {
887
                    'picking_id': picking.id,
888
                }, context=context)
889
890
        if not values:
891
            return prog_id
892
893
        prog_obj.write(cr, uid, [prog_id], values, context=context)
894
895
        return prog_id
896
2209.5.1 by Quentin THEURET
UTP-1147 [IMP] Incoming shipment :: Processing :: If the processing of the IN is too long, put it in background and display a message to the user
897
    def do_incoming_shipment_new_cr(self, cr, uid, wizard_ids, context=None):
898
        """
899
        Call the do_incoming_shipment() method with a new cursor.
900
        """
2264.1.1 by Quentin THEURET
UF-2485 [FIX] If an error was raised during the incoming shipment processing, no error was displayed on the processing wizard.
901
        inc_proc_obj = self.pool.get('stock.incoming.processor')
902
2209.5.1 by Quentin THEURET
UTP-1147 [IMP] Incoming shipment :: Processing :: If the processing of the IN is too long, put it in background and display a message to the user
903
        # Create new cursor
904
        import pooler
905
        new_cr = pooler.get_db(cr.dbname).cursor()
2222 by jf
UTP-1139 [IMP] Performance issue of the Orders sourcing tool
906
2264.1.1 by Quentin THEURET
UF-2485 [FIX] If an error was raised during the incoming shipment processing, no error was displayed on the processing wizard.
907
        res = True
908
2210.2.7 by Quentin THEURET
UTP-1147 [FIX] Take care of the creation of internal batches before open a new cursor
909
        try:
910
            # Call do_incoming_shipment()
911
            res = self.do_incoming_shipment(new_cr, uid, wizard_ids, context=context)
912
            new_cr.commit()
913
        except Exception, e:
914
            new_cr.rollback()
2264.1.1 by Quentin THEURET
UF-2485 [FIX] If an error was raised during the incoming shipment processing, no error was displayed on the processing wizard.
915
916
            for wiz in inc_proc_obj.read(new_cr, uid, wizard_ids, ['picking_id'], context=context):
917
                self.update_processing_info(new_cr, uid, wiz['picking_id'][0], False, {
2264.1.2 by Quentin THEURET
UF-2485 [FIX] There was no possibility to re-set an incoming processing that raised an error.
918
                    'error_msg': '%s\n\nPlease reset the incoming shipment '\
919
                                 'processing and fix the source of the error'\
920
                                 'before re-try the processing.' % str(e),
2264.1.1 by Quentin THEURET
UF-2485 [FIX] If an error was raised during the incoming shipment processing, no error was displayed on the processing wizard.
921
                }, context=context)
2210.2.7 by Quentin THEURET
UTP-1147 [FIX] Take care of the creation of internal batches before open a new cursor
922
        finally:
923
            # Close the cursor
2626.1.19 by jf
US-684 [IMP] Close and remove cursor used by background process
924
            new_cr.close(True)
2209.5.1 by Quentin THEURET
UTP-1147 [IMP] Incoming shipment :: Processing :: If the processing of the IN is too long, put it in background and display a message to the user
925
926
        return res
927
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
928
    def do_incoming_shipment(self, cr, uid, wizard_ids, context=None):
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
929
        """
930
        Take the data in wizard_ids and lines of stock.incoming.processor and
931
        do the split of stock.move according to the data.
932
        """
933
        # Objects
934
        inc_proc_obj = self.pool.get('stock.incoming.processor')
935
        move_proc_obj = self.pool.get('stock.move.in.processor')
936
        loc_obj = self.pool.get('stock.location')
937
        uom_obj = self.pool.get('product.uom')
938
        move_obj = self.pool.get('stock.move')
939
        sequence_obj = self.pool.get('ir.sequence')
2210.9.12 by Quentin THEURET
UTP-1112 [FIX] The price unit in the OUTgoing delivery moves should be in the currency of the IR
940
        cur_obj = self.pool.get('res.currency')
2703.8.8 by Quentin THEURET
US-802 [FIX] Put the name of the real user in the Product cost price changes at Reception
941
        sptc_obj = self.pool.get('standard.price.track.changes')
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
942
        wf_service = netsvc.LocalService("workflow")
2359.4.7 by dvo at dvo
UF-2531: Various fix for the creation of RW messages - now create manual frequently to make sure the order and content of messages are kept correctly
943
        usb_entity = self._get_usb_entity_type(cr, uid)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
944
945
        if context is None:
946
            context = {}
947
948
        if isinstance(wizard_ids, (int, long)):
949
            wizard_ids = [wizard_ids]
950
951
        db_data_dict = self._get_db_data_dict(cr, uid)
952
953
        # UF-1617: Get the sync_message case
954
        sync_in = context.get('sync_message_execution', False)
2165.14.16 by dvo at dvo
UF-2415: RW: INT and IN
955
        if context.get('rw_sync', False):
956
            sync_in = False
2207.1.2 by Quentin THEURET
UF-2426 [FIX] Case 3: Fixed problem with 'in_out_updated' value when receive a IN from RW
957
958
        in_out_updated = True
959
        if sync_in:
960
            in_out_updated = False
961
2165.14.16 by dvo at dvo
UF-2415: RW: INT and IN
962
        backorder_id = False
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
963
964
        internal_loc = loc_obj.search(cr, uid, [('usage', '=', 'internal'), ('cross_docking_location_ok', '=', False)])
1994.13.1 by Quentin THEURET
UTP-967 [FIX] If a procurement order is made from a Min/Max rule, don't cancel and/or remove the attached stock move (from procurement to dest location) till the incoming shipment is not done
965
        proc_loc_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'location_procurement')[1]
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
966
        context['location'] = internal_loc
967
968
        product_availability = {}
2209.5.3 by Quentin THEURET
UTP-1147 [IMP] Now, it's possible to check the processing of an Incoming shipment and other actions are blocked (cancel of the IN, cancel of the move)
969
        picking_ids = []
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
970
971
        for wizard in inc_proc_obj.browse(cr, uid, wizard_ids, context=context):
972
            picking = wizard.picking_id
2209.5.3 by Quentin THEURET
UTP-1147 [IMP] Now, it's possible to check the processing of an Incoming shipment and other actions are blocked (cancel of the IN, cancel of the move)
973
            picking_ids.append(picking)
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
974
            backordered_moves = []  # Moves that need to be put in a backorder
975
            done_moves = []  # Moves that are completed
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
976
            out_picks = set()
1994.1.34 by Quentin THEURET
REF-27 [IMP] Change the osv.osv_memory incoming shipment wizard by a osv.osv wizard
977
            processed_out_moves = []
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
978
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
979
            total_moves = len(picking.move_lines)
980
            move_done = 0
981
            prog_id = self.update_processing_info(cr, uid, picking, False, {
982
                'progress_line': _('In progress (%s/%s)') % (move_done, total_moves),
983
                'start_date': time.strftime('%Y-%m-%d %H:%M:%S')
984
            }, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
985
            for move in picking.move_lines:
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
986
                move_done += 1
987
                prog_id = self.update_processing_info(cr, uid, picking, prog_id, {
988
                    'progress_line': _('In progress (%s/%s)') % (move_done, total_moves),
989
                }, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
990
                # Get all processed lines that processed this stock move
991
                proc_ids = move_proc_obj.search(cr, uid, [('wizard_id', '=', wizard.id), ('move_id', '=', move.id)], context=context)
992
                # The processed quantity
993
                count = 0
994
                need_split = False
995
996
                data_back = move_obj.create_data_back(move)
997
                mirror_data = move_obj.get_mirror_move(cr, uid, [move.id], data_back, context=context)[move.id]
998
                out_moves = mirror_data['moves']
999
                average_values = {}
2703.8.8 by Quentin THEURET
US-802 [FIX] Put the name of the real user in the Product cost price changes at Reception
1000
                move_sptc_values = []
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1001
1002
                for line in move_proc_obj.browse(cr, uid, proc_ids, context=context):
1003
                    values = self._get_values_from_line(cr, uid, move, line, db_data_dict, context=context)
2038.1.8 by Quentin THEURET
REF-78 [FIX] Fixed issue with partial incoming shipment processing by the sync. engine
1004
                    if not values.get('product_qty', 0.00):
1005
                        continue
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1006
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1007
                    # Check if we must re-compute the price of the product
2406.6.1 by Quentin THEURET
BKLG-39 [IMP] Compute the averace cost price at each IN even if the destination location is Cross-Docking
1008
                    compute_average = picking.type == 'in' and line.product_id.cost_method
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1009
                    if values.get('location_dest_id', False):
1010
                        dest_loc = loc_obj.browse(cr, uid, values['location_dest_id'], context=context)
2406.6.1 by Quentin THEURET
BKLG-39 [IMP] Compute the averace cost price at each IN even if the destination location is Cross-Docking
1011
                        compute_average = picking.type == 'in' and line.product_id.cost_method == 'average'
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1012
1013
                    if compute_average:
2703.8.8 by Quentin THEURET
US-802 [FIX] Put the name of the real user in the Product cost price changes at Reception
1014
                        average_values, sptc_values = self._compute_average_values(cr, uid, move, line, product_availability, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1015
                        values.update(average_values)
2703.8.8 by Quentin THEURET
US-802 [FIX] Put the name of the real user in the Product cost price changes at Reception
1016
                        move_sptc_values.append(sptc_values)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1017
1018
                    # The quantity
1019
                    if line.uom_id.id != move.product_uom.id:
1020
                        count += uom_obj._compute_qty(cr, uid, line.uom_id.id, line.quantity, move.product_uom.id)
1021
                    else:
1022
                        count += line.quantity
1023
1024
                    values['processed_stock_move'] = True
1025
                    if not need_split:
1026
                        need_split = True
1027
                        # Mark the done IN stock move as processed
1028
                        move_obj.write(cr, uid, [move.id], values, context=context)
1029
                        done_moves.append(move.id)
1030
                    else:
1031
                        values['state'] = 'assigned'
2542.3.1 by Quentin THEURET
US-405 [FIX] If a line is split during the incoming shipment processing, and if this line comes from an Internal request, the generated move in internal move doesn't have the good destination location
1032
                        values['purchase_line_id'] = move.purchase_line_id and move.purchase_line_id.id or False
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1033
                        context['keepLineNumber'] = True
1994.1.38 by Quentin THEURET
REF-27 [IMP] Improve the Outgoing delivery processing wizard
1034
                        new_move_id = move_obj.copy(cr, uid, move.id, values, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1035
                        context['keepLineNumber'] = False
1036
                        done_moves.append(new_move_id)
1037
1038
                    values['processed_stock_move'] = False
1039
1040
                    out_values = values.copy()
1041
                    # Remove sync. DPO fields
1042
                    out_values.update({
1043
                        'dpo_line_id': 0,
1044
                        'sync_dpo': False,
1045
                        'state': 'confirmed',
1046
                    })
1994.1.34 by Quentin THEURET
REF-27 [IMP] Change the osv.osv_memory incoming shipment wizard by a osv.osv wizard
1047
                    if out_values.get('location_dest_id', False):
1048
                        out_values.pop('location_dest_id')
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1049
1050
                    remaining_out_qty = line.quantity
1051
                    out_move = None
2207.1.2 by Quentin THEURET
UF-2426 [FIX] Case 3: Fixed problem with 'in_out_updated' value when receive a IN from RW
1052
1053
                    # Sort the OUT moves to get the closest quantities as the IN quantity
1054
                    out_moves = sorted(out_moves, key=lambda x: abs(x.product_qty-line.quantity))
1055
2206.2.4 by Quentin THEURET
UF-2418 [FIX] Fix bug when receive more than the expecetd quantity :: The OUT qty was not updated well
1056
                    for lst_out_move in out_moves:
2206.2.3 by Quentin THEURET
UF-2418 [FIX] At reception of IN, if there are some OUT moves linked, dispatch the quantity into these differents OUT moves
1057
                        if remaining_out_qty <= 0.00:
2206.1.2 by duy.vo at msf
UF-2418: Fixed from QT
1058
                            break
2206.2.1 by Quentin THEURET
UF-2418 [FIX] At IN processing, if there are two lines in OUT and only one line in IN, the system tries to update the OUT with a line with 0.00 as quantity and display an error message
1059
2206.2.4 by Quentin THEURET
UF-2418 [FIX] Fix bug when receive more than the expecetd quantity :: The OUT qty was not updated well
1060
                        out_move = move_obj.browse(cr, uid, lst_out_move.id, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1061
2210.9.12 by Quentin THEURET
UTP-1112 [FIX] The price unit in the OUTgoing delivery moves should be in the currency of the IR
1062
                        if values.get('price_unit', False) and out_move.price_currency_id.id != move.price_currency_id.id:
1063
                            price_unit = cur_obj.compute(
1064
                                cr,
1065
                                uid,
1066
                                move.price_currency_id.id,
1067
                                out_move.price_currency_id.id,
1068
                                values.get('price_unit'),
1069
                                round=False,
1070
                                context=context
1071
                            )
1072
                            out_values['price_unit'] = price_unit
1073
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1074
                        # List the Picking Ticket that need to be created from the Draft Picking Ticket
1075
                        if out_move.picking_id.type == 'out' \
1076
                           and out_move.picking_id.subtype == 'picking' \
1077
                           and out_move.picking_id.state == 'draft':
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1078
                            out_picks.add(out_move.picking_id.id)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1079
1080
                        if line.uom_id.id != out_move.product_uom.id:
1081
                            uom_partial_qty = uom_obj._compute_qty(cr, uid, line.uom_id.id, remaining_out_qty, out_move.product_uom.id)
1082
                        else:
1083
                            uom_partial_qty = remaining_out_qty
1084
2466.7.1 by Quentin THEURET
US-185 [FIX] For OUT created by IR to external consumption unit, if the OUT is partially processed (forced) before reception of the IN, the quantities in the OUT BO was not good (don't take care of the quantities already processed)
1085
                        # Manage OUT BO moves already processed (forced)
1086
                        bo_moves = []
2466.7.2 by Quentin THEURET
US-185 [FIX] In case of reception of less quantities than remaining OUT, split the OUT
1087
                        minus_qty = 0.00
2466.7.1 by Quentin THEURET
US-185 [FIX] For OUT created by IR to external consumption unit, if the OUT is partially processed (forced) before reception of the IN, the quantities in the OUT BO was not good (don't take care of the quantities already processed)
1088
                        if out_move.picking_id and out_move.picking_id.backorder_id:
1089
                            bo_moves = move_obj.search(cr, uid, [
1090
                                ('picking_id', '=', out_move.picking_id.backorder_id.id),
1091
                                ('sale_line_id', '=', out_move.sale_line_id.id),
1092
                                ('state', '=', 'done'),
2574.1.1 by Quentin THEURET
US-490 [FIX] At reception, on checking of quantities already sent (forced) before the reception, don't return the stock moves that are already sent but craeated by a reception
1093
                                ('in_out_updated', '=', False),
2466.7.1 by Quentin THEURET
US-185 [FIX] For OUT created by IR to external consumption unit, if the OUT is partially processed (forced) before reception of the IN, the quantities in the OUT BO was not good (don't take care of the quantities already processed)
1094
                            ], context=context)
1095
                            while bo_moves:
1096
                                boms = move_obj.browse(cr, uid, bo_moves, context=context)
1097
                                bo_moves = []
1098
                                for bom in boms:
1099
                                    if bom.product_uom.id != out_move.product_uom.id:
2466.7.2 by Quentin THEURET
US-185 [FIX] In case of reception of less quantities than remaining OUT, split the OUT
1100
                                        minus_qty += uom_obj._compute_qty(cr, uid, bom.product_uom.id, bom.product_qty, out_move.product_uom.id)
2466.7.1 by Quentin THEURET
US-185 [FIX] For OUT created by IR to external consumption unit, if the OUT is partially processed (forced) before reception of the IN, the quantities in the OUT BO was not good (don't take care of the quantities already processed)
1101
                                    else:
2466.7.2 by Quentin THEURET
US-185 [FIX] In case of reception of less quantities than remaining OUT, split the OUT
1102
                                        minus_qty += bom.product_qty
2466.7.1 by Quentin THEURET
US-185 [FIX] For OUT created by IR to external consumption unit, if the OUT is partially processed (forced) before reception of the IN, the quantities in the OUT BO was not good (don't take care of the quantities already processed)
1103
                                    if bom.picking_id and bom.picking_id.backorder_id:
1104
                                        bo_moves.extend(move_obj.search(cr, uid, [
1105
                                            ('picking_id', '=', bom.picking_id.backorder_id.id),
1106
                                            ('sale_line_id', '=', bom.sale_line_id.id),
1107
                                            ('state', '=', 'done'),
2574.1.1 by Quentin THEURET
US-490 [FIX] At reception, on checking of quantities already sent (forced) before the reception, don't return the stock moves that are already sent but craeated by a reception
1108
                                            ('in_out_updated', '=', False),
2466.7.1 by Quentin THEURET
US-185 [FIX] For OUT created by IR to external consumption unit, if the OUT is partially processed (forced) before reception of the IN, the quantities in the OUT BO was not good (don't take care of the quantities already processed)
1109
                                        ], context=context))
1110
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1111
                        if uom_partial_qty < out_move.product_qty:
1112
                            # Splt the out move
1113
                            out_values.update({
1114
                                'product_qty': remaining_out_qty,
1115
                                'product_uom': line.uom_id.id,
2207.1.2 by Quentin THEURET
UF-2426 [FIX] Case 3: Fixed problem with 'in_out_updated' value when receive a IN from RW
1116
                                'in_out_updated': in_out_updated,
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1117
                            })
1118
                            context['keepLineNumber'] = True
1994.1.34 by Quentin THEURET
REF-27 [IMP] Change the osv.osv_memory incoming shipment wizard by a osv.osv wizard
1119
                            new_out_move_id = move_obj.copy(cr, uid, out_move.id, out_values, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1120
                            context['keepLineNumber'] = False
1121
                            remaining_out_qty = 0.00
1994.1.48 by Quentin THEURET
REF-27 [FIX] Fixed bug on processing of incoming shipment linked to an OUT, the OUT move quantity was not reduce
1122
                            move_obj.write(cr, uid, [out_move.id], {
1123
                                'product_qty': out_move.product_qty - uom_partial_qty,
1124
                                'product_uos_qty': out_move.product_qty - uom_partial_qty,
1125
                            }, context=context)
1994.1.34 by Quentin THEURET
REF-27 [IMP] Change the osv.osv_memory incoming shipment wizard by a osv.osv wizard
1126
                            processed_out_moves.append(new_out_move_id)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1127
                        elif uom_partial_qty == out_move.product_qty:
1128
                            out_values.update({
1129
                                'product_qty': remaining_out_qty,
1130
                                'product_uom': line.uom_id.id,
2207.1.2 by Quentin THEURET
UF-2426 [FIX] Case 3: Fixed problem with 'in_out_updated' value when receive a IN from RW
1131
                                'in_out_updated': in_out_updated,
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1132
                            })
2165.22.14 by Quentin THEURET
UF-2400 [FIX] At IN reception to cross-docking, if the linked draft picking ticket moves are splitted by the first check availability, there was a problem because the link was made only on the first move
1133
                            remaining_out_qty = 0.00
1134
                            move_obj.write(cr, uid, [out_move.id], out_values, context=context)
1135
                            processed_out_moves.append(out_move.id)
1136
                        elif uom_partial_qty > out_move.product_qty and out_moves[out_moves.index(out_move)] != out_moves[-1]:
1137
                            # Just update the out move with the value of the out move with UoM of IN
1138
                            out_qty = out_move.product_qty
1139
                            if line.uom_id.id != out_move.product_uom.id:
1140
                                out_qty = uom_obj._compute_qty(cr, uid, out_move.product_uom.id, out_move.product_qty, line.uom_id.id)
1141
1142
                            out_values.update({
1143
                                'product_qty': out_qty,
1144
                                'product_uom': line.uom_id.id,
2206.3.22 by jf
[MERGE] lp:unifield-wm
1145
                                'in_out_updated': in_out_updated,
2165.22.14 by Quentin THEURET
UF-2400 [FIX] At IN reception to cross-docking, if the linked draft picking ticket moves are splitted by the first check availability, there was a problem because the link was made only on the first move
1146
                            })
1147
                            remaining_out_qty -= out_qty
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1148
                            move_obj.write(cr, uid, [out_move.id], out_values, context=context)
1149
                            processed_out_moves.append(out_move.id)
1150
                        else:
1151
                            # Just update the data of the initial out move
2466.7.2 by Quentin THEURET
US-185 [FIX] In case of reception of less quantities than remaining OUT, split the OUT
1152
                            processed_qty = lst_out_move is out_moves[-1] and uom_partial_qty - minus_qty or out_move.product_qty
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1153
                            out_values.update({
2206.2.3 by Quentin THEURET
UF-2418 [FIX] At reception of IN, if there are some OUT moves linked, dispatch the quantity into these differents OUT moves
1154
                                'product_qty': processed_qty,
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1155
                                'product_uom': line.uom_id.id,
2207.1.2 by Quentin THEURET
UF-2426 [FIX] Case 3: Fixed problem with 'in_out_updated' value when receive a IN from RW
1156
                                'in_out_updated': in_out_updated,
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1157
                            })
1158
                            move_obj.write(cr, uid, [out_move.id], out_values, context=context)
1159
                            processed_out_moves.append(out_move.id)
2207 by jf
UF-2418 [FIX] RW: Remote Warehouse Bugs II
1160
2206.2.3 by Quentin THEURET
UF-2418 [FIX] At reception of IN, if there are some OUT moves linked, dispatch the quantity into these differents OUT moves
1161
                            if line.uom_id.id != out_move.product_uom.id:
1162
                                uom_processed_qty = uom_obj._compute_qty(cr, uid, out_move.product_uom.id, processed_qty, line.uom_id.id)
1163
                            else:
1164
                                uom_processed_qty = processed_qty
1165
1166
                            remaining_out_qty -= uom_processed_qty
1167
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1168
1169
                # Decrement the inital move, cannot be less than zero
1170
                diff_qty = move.product_qty - count
1171
                # If there is remaining quantity for the move, put the ID of the move
1172
                # and the remaining quantity to list of moves to put in backorder
1173
                if diff_qty > 0.00 and move.state != 'cancel':
2703.8.8 by Quentin THEURET
US-802 [FIX] Put the name of the real user in the Product cost price changes at Reception
1174
                    backordered_moves.append((move, diff_qty, average_values, data_back, move_sptc_values))
1175
                else:
1176
                    for sptc_values in move_sptc_values:
1177
                        sptc_obj.track_change(cr, uid, move.product_id.id,
1178
                                              _('Reception %s') % move.picking_id.name,
1179
                                              sptc_values, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1180
2032 by jf
UTP-697 [FIX] Negatives quantities in Inventory Report
1181
                # UTP-967
1994.13.2 by vg at tempo-consulting
UTP-967 [FIX] if procurement order is made from a min/max or threeshold remove the attached stock move only if not a partial IN (no diff qty)
1182
                if move.state != 'cancel' and move.purchase_line_id and move.purchase_line_id.procurement_id:
1994.13.1 by Quentin THEURET
UTP-967 [FIX] If a procurement order is made from a Min/Max rule, don't cancel and/or remove the attached stock move (from procurement to dest location) till the incoming shipment is not done
1183
                    proc = move.purchase_line_id.procurement_id
2165.14.35 by Quentin THEURET
UF-2377 [FIX] Let Me Fix was displayed at IN processing if there is no stock move associated to procurement order on RW instance
1184
                    if proc.move_id and proc.move_id.location_id.id == proc_loc_id:
2058.6.2 by vg at tempo-consulting
REF-59 [FIX] stock.picking do_incoming shipment compute diff qty decrement of original procurement order move for correct virtual stock
1185
                        if diff_qty > 0:
2079 by jf
REF-59 [FIX] Wrong virtual stock for partial reception of incoming coming from Min Stock Rule
1186
                            # REF-59: move of partial in,
2058.6.4 by Quentin THEURET
REF-59 [FIX] Improve the management of stock moves in procurement order in case of partial reception
1187
                            # adapt proc order's move qty (for correct virtual stock)
1188
                            move_obj.write(cr, uid, [proc.move_id.id],
1189
                                {'product_qty': diff_qty}, context=context)
2058.6.2 by vg at tempo-consulting
REF-59 [FIX] stock.picking do_incoming shipment compute diff qty decrement of original procurement order move for correct virtual stock
1190
                        else:
2058.6.6 by vg at tempo-consulting
REF-59 [FIX] Improve the management of stock moves in procurement order in case of partial reception - validation tests done (partial or full IN) and no side effects on UTP-967
1191
                            # note: do not close move until a diff qty is applied above
2058.6.4 by Quentin THEURET
REF-59 [FIX] Improve the management of stock moves in procurement order in case of partial reception
1192
                            move_obj.write(cr, uid, [proc.move_id.id], {'product_qty': 0.00, 'state': 'done'}, context=context)
1193
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
1194
            prog_id = self.update_processing_info(cr, uid, picking, prog_id, {
1195
                'progress_line': _('Done (%s/%s)') % (move_done, total_moves),
1196
            }, context=context)
1197
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1198
            # Create the backorder if needed
1199
            if backordered_moves:
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
1200
                prog_id = self.update_processing_info(cr, uid, picking, prog_id, {
1201
                    'create_bo': _('In progress'),
1202
                }, context=context)
2165.14.17 by dvo at dvo
UF-2415: Set flag for sync the INT/IN in RW
1203
                initial_vals_copy = {
2205 by jf
UF-2377 [IMP] RW: Sync OUTs between RW and main instances
1204
                    'name':sequence_obj.get(cr, uid, 'stock.picking.%s' % (picking.type)),
1205
                    'move_lines':[],
2478.4.3 by Quentin THEURET
US-211 [FIX] At IN processing, if the IN is a DPO IN and processed by the sync. engine, put the processed lines on a new IN and don't put this IN on 'Shipped Availabel' state
1206
                    'state':'draft',
1207
                    'in_dpo': context.get('for_dpo', False),
1208
                }
2205 by jf
UF-2377 [IMP] RW: Sync OUTs between RW and main instances
1209
2359.4.7 by dvo at dvo
UF-2531: Various fix for the creation of RW messages - now create manual frequently to make sure the order and content of messages are kept correctly
1210
                if usb_entity == self.REMOTE_WAREHOUSE and not context.get('sync_message_execution', False): # RW Sync - set the replicated to True for not syncing it again
2165.14.17 by dvo at dvo
UF-2415: Set flag for sync the INT/IN in RW
1211
                    initial_vals_copy.update({
1212
                        'already_replicated': False,
1213
                    })
2205 by jf
UF-2377 [IMP] RW: Sync OUTs between RW and main instances
1214
2478.4.3 by Quentin THEURET
US-211 [FIX] At IN processing, if the IN is a DPO IN and processed by the sync. engine, put the processed lines on a new IN and don't put this IN on 'Shipped Availabel' state
1215
                backorder_id = False
1216
                if context.get('for_dpo', False) and picking.purchase_id:
1217
                    # Look for an available IN for the same purchase order in case of DPO
1218
                    backorder_ids = self.search(cr, uid, [
1219
                        ('purchase_id', '=', picking.purchase_id.id),
1220
                        ('in_dpo', '=', True),
1221
                        ('state', '=', 'assigned'),
1222
                    ], limit=1, context=context)
1223
                    if backorder_ids:
1224
                        backorder_id = backorder_ids[0]
1225
2703.8.8 by Quentin THEURET
US-802 [FIX] Put the name of the real user in the Product cost price changes at Reception
1226
                backorder_name = picking.name
2478.4.3 by Quentin THEURET
US-211 [FIX] At IN processing, if the IN is a DPO IN and processed by the sync. engine, put the processed lines on a new IN and don't put this IN on 'Shipped Availabel' state
1227
                if not backorder_id:
1228
                    backorder_id = self.copy(cr, uid, picking.id, initial_vals_copy, context=context)
2703.8.8 by Quentin THEURET
US-802 [FIX] Put the name of the real user in the Product cost price changes at Reception
1229
                    backorder_name = self.read(cr, uid, backorder_id, ['name'], context=context)['name']
2478.4.3 by Quentin THEURET
US-211 [FIX] At IN processing, if the IN is a DPO IN and processed by the sync. engine, put the processed lines on a new IN and don't put this IN on 'Shipped Availabel' state
1230
1231
                    back_order_post_copy_vals = {}
1232
                    if usb_entity == self.CENTRAL_PLATFORM and context.get('rw_backorder_name', False):
1233
                        new_name = context.get('rw_backorder_name')
1234
                        del context['rw_backorder_name']
1235
                        back_order_post_copy_vals['name'] = new_name
1236
1237
                    if picking.purchase_id:
1238
                        # US-111: in case of partial reception invoice was not linked to PO
1239
                        # => analytic_distribution_supply/stock.py _invoice_hook
1240
                        #    picking.purchase_id was False
1241
                        back_order_post_copy_vals['purchase_id'] = picking.purchase_id.id
1242
1243
                    if back_order_post_copy_vals:
1244
                        self.write(cr, uid, backorder_id, back_order_post_copy_vals, context=context)
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1245
2703.8.8 by Quentin THEURET
US-802 [FIX] Put the name of the real user in the Product cost price changes at Reception
1246
                for bo_move, bo_qty, av_values, data_back, move_sptc_values in backordered_moves:
1247
                    for sptc_values in move_sptc_values:
1248
                        sptc_obj.track_change(cr, uid, move.product_id.id,
1249
                                              _('Reception %s') % backorder_name,
1250
                                              sptc_values, context=context)
2038.1.1 by Quentin THEURET
REF-65 [FIX] Fixed bug when the user doesn't process all lines of an IN (one or more lines have 0.00 as processed qty)
1251
                    if bo_move.product_qty != bo_qty:
1252
                        # Create the corresponding move in the backorder - reset batch - reset asset_id
1253
                        bo_values = {
2703.11.1 by Quentin THEURET
UF-2246 [FIX] Keep batch number, expiry date and asset, if set on the initial IN, to the Backorder
1254
                            'asset_id': data_back['asset_id'],
2038.1.1 by Quentin THEURET
REF-65 [FIX] Fixed bug when the user doesn't process all lines of an IN (one or more lines have 0.00 as processed qty)
1255
                            'product_qty': bo_qty,
1256
                            'product_uos_qty': bo_qty,
1257
                            'product_uom': data_back['product_uom'],
1258
                            'product_uos': data_back['product_uom'],
2308.3.1 by Quentin THEURET
UFTP-330 [FIX] When product was changed in the IN processor, if there are a backorder, the backorder kept the new product instead of original one
1259
                            'product_id': data_back['product_id'],
2629.3.5 by Quentin THEURET
US-604 [IMP] If the destination type is changed at IN reception, keep the inital destiantion type for backordered moves
1260
                            'location_dest_id': data_back['location_dest_id'],
1261
                            'move_cross_docking_ok': data_back['move_cross_docking_ok'],
2703.11.1 by Quentin THEURET
UF-2246 [FIX] Keep batch number, expiry date and asset, if set on the initial IN, to the Backorder
1262
                            'prodlot_id': data_back['prodlot_id'],
1263
                            'expired_date': data_back['expired_date'],
2038.1.1 by Quentin THEURET
REF-65 [FIX] Fixed bug when the user doesn't process all lines of an IN (one or more lines have 0.00 as processed qty)
1264
                            'state': 'assigned',
1265
                            'move_dest_id': False,
1266
                            'change_reason': False,
2478.4.6 by Quentin THEURET
US-211 [FIX] On IN, keep link to the DPO line at coordo to send the message of reception
1267
                            'processed_stock_move': True,
1268
                            'dpo_line_id': bo_move.dpo_line_id,
2359.4.7 by dvo at dvo
UF-2531: Various fix for the creation of RW messages - now create manual frequently to make sure the order and content of messages are kept correctly
1269
                            'purchase_line_id': bo_move.purchase_line_id and bo_move.purchase_line_id.id or False,
2038.1.1 by Quentin THEURET
REF-65 [FIX] Fixed bug when the user doesn't process all lines of an IN (one or more lines have 0.00 as processed qty)
1270
                        }
1271
                        bo_values.update(av_values)
1272
                        context['keepLineNumber'] = True
2359.4.7 by dvo at dvo
UF-2531: Various fix for the creation of RW messages - now create manual frequently to make sure the order and content of messages are kept correctly
1273
                        context['from_button'] = False
2038.1.1 by Quentin THEURET
REF-65 [FIX] Fixed bug when the user doesn't process all lines of an IN (one or more lines have 0.00 as processed qty)
1274
                        move_obj.copy(cr, uid, bo_move.id, bo_values, context=context)
1275
                        context['keepLineNumber'] = False
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1276
1277
                # Put the done moves in this new picking
2478.4.7 by Quentin THEURET
US-211 [FIX] In case of processing of a IN with service with DPO, keep the dpo line number
1278
                done_values = {'picking_id': backorder_id}
1279
                if not context.get('for_dpo'):
1280
                    done_values['dpo_line_id'] = 0
1281
                move_obj.write(cr, uid, done_moves, done_values, context=context)
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
1282
                prog_id = self.update_processing_info(cr, uid, picking, prog_id, {
1283
                    'create_bo': _('Done'),
1284
                    'close_in': _('In progress'),
1285
                }, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1286
1287
                if sync_in:
1288
                    # UF-1617: When it is from the sync., then just send the IN to shipped, then return the backorder_id
2478.4.3 by Quentin THEURET
US-211 [FIX] At IN processing, if the IN is a DPO IN and processed by the sync. engine, put the processed lines on a new IN and don't put this IN on 'Shipped Availabel' state
1289
                    if context.get('for_dpo', False):
1290
                        wf_service.trg_validate(uid, 'stock.picking', backorder_id, 'button_confirm', cr)
1291
                    else:
1292
                        wf_service.trg_validate(uid, 'stock.picking', backorder_id, 'button_shipped', cr)
1293
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1294
                    return backorder_id
1295
1296
                wf_service.trg_validate(uid, 'stock.picking', backorder_id, 'button_confirm', cr)
1297
                # Then we finish the good picking
2165.14.20 by dvo at dvo
UF-2415: Updated the flag to RW sync correctly
1298
                self.write(cr, uid, [picking.id], {'backorder_id': backorder_id,'cd_from_bo': values.get('cd_from_bo', False),}, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1299
                self.action_move(cr, uid, [backorder_id])
1300
                wf_service.trg_validate(uid, 'stock.picking', backorder_id, 'button_done', cr)
1301
                wf_service.trg_write(uid, 'stock.picking', picking.id, cr)
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
1302
                prog_id = self.update_processing_info(cr, uid, picking, prog_id, {
1303
                    'close_in': _('Done'),
1304
                }, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1305
            else:
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
1306
                prog_id = self.update_processing_info(cr, uid, picking, prog_id, {
1307
                    'create_bo': _('N/A'),
1308
                    'close_in': _('In progress'),
1309
                }, context=context)
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1310
                if sync_in:  # If it's from sync, then we just send the pick to become Available Shippde, not completely close!
2478.4.5 by Quentin THEURET
US-211 [FIX] Don't display warning message if IN come from DPO
1311
                    if context.get('for_dpo', False):
1312
                        self.write(cr, uid, [picking.id], {'in_dpo': True}, context=context)
1313
                    else:
2478.4.4 by Quentin THEURET
US-211 [FIX] Don't put the IN to shipped available if all lines come from DPO
1314
                        self.write(cr, uid, [picking.id], {'state': 'shipped'}, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1315
                    return picking.id
1316
                else:
1317
                    self.action_move(cr, uid, [picking.id], context=context)
1318
                    wf_service.trg_validate(uid, 'stock.picking', picking.id, 'button_done', cr)
2165.3.1 by Quentin THEURET
UF-2395 [FIX] When a line is added to a RfQ (from a tender) that source an IR, at IN reception, put the IR as closed
1319
                    if picking.purchase_id:
1320
                        so_ids = self.pool.get('purchase.order').get_so_ids_from_po_ids(cr, uid, picking.purchase_id.id, context=context)
1321
                        for so_id in so_ids:
1322
                            wf_service.trg_write(uid, 'sale.order', so_id, cr)
2359.4.7 by dvo at dvo
UF-2531: Various fix for the creation of RW messages - now create manual frequently to make sure the order and content of messages are kept correctly
1323
                    if usb_entity == self.REMOTE_WAREHOUSE:
2165.14.20 by dvo at dvo
UF-2415: Updated the flag to RW sync correctly
1324
                        self.write(cr, uid, [picking.id], {'already_replicated': False}, context=context)
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
1325
                prog_id = self.update_processing_info(cr, uid, picking, prog_id, {
1326
                    'close_in': _('Done'),
1327
                }, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1328
1994.1.34 by Quentin THEURET
REF-27 [IMP] Change the osv.osv_memory incoming shipment wizard by a osv.osv wizard
1329
            if not sync_in:
1330
                move_obj.action_assign(cr, uid, processed_out_moves)
1331
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
1332
        if not out_picks:
1333
            prog_id = self.update_processing_info(cr, uid, picking, prog_id, {
1334
                'prepare_pick': _('N/A'),
1335
            }, context=context)
1336
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1337
        # Create the first picking ticket if we are on a draft picking ticket
1338
        for picking in self.browse(cr, uid, list(out_picks), context=context):
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
1339
            prog_id = self.update_processing_info(cr, uid, picking, prog_id, {
1340
                'prepare_pick': _('In progress'),
1341
            }, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1342
            wiz = self.create_picking(cr, uid, [picking.id], context=context)
1343
            wiz_obj = self.pool.get(wiz['res_model'])
1994.1.34 by Quentin THEURET
REF-27 [IMP] Change the osv.osv_memory incoming shipment wizard by a osv.osv wizard
1344
            wiz_context = wiz.get('context', {})
1345
            moves_picking = wiz_obj.browse(cr, uid, wiz['res_id'], context=wiz_context).move_ids
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1346
            nb_lines = len(moves_picking)
1347
            # We delete the lines which is not from the IN
1348
#            for line in moves_picking:
1349
#                if line.move_id.id not in pick_moves:
1350
#                    self.pool.get('stock.move.memeroy.picking').unlink(cr, uid, [line.id], context=context)
1351
#                    nb_lines -= 1
1352
1353
            if nb_lines:
1354
                # We copy all data in lines
1994.1.34 by Quentin THEURET
REF-27 [IMP] Change the osv.osv_memory incoming shipment wizard by a osv.osv wizard
1355
                wiz_obj.copy_all(cr, uid, [wiz['res_id']], context=wiz_context)
2375 by jf
UF-2531 [FIX] Remote Warehouse Issues (post TC)
1356
2359.4.8 by duy.vo at msf
UF-2531: Further fixes for the name of PICK in CP when making a partial IN from RW
1357
                #UF-2531: Pass the name of PICKxxx-y when creating a Pick from crossdocking from an IN partial
1358
                if context.get('associate_pick_name', False) and context.get('sync_message_execution', False):
1359
                    wiz_context['associate_pick_name'] = context.get('associate_pick_name')
2375 by jf
UF-2531 [FIX] Remote Warehouse Issues (post TC)
1360
                    del context['associate_pick_name']
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1361
                # We process the creation of the picking
2359.4.8 by duy.vo at msf
UF-2531: Further fixes for the name of PICK in CP when making a partial IN from RW
1362
                res_wiz = wiz_obj.do_create_picking(cr, uid, [wiz['res_id']], context=wiz_context)
1363
                if 'res_id' in res_wiz:
1364
                    new_pick_id = res_wiz['res_id']
1365
                    if backorder_id and new_pick_id:
1366
                        new_pick_name = self.read(cr, uid, new_pick_id, ['name'], context=context)['name']
1367
                        self.write(cr, uid, backorder_id, {'associate_pick_name': new_pick_name,}, context=context)
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1368
2209.5.2 by Quentin THEURET
UTP-1147 [IMP] INcoming shipment :: Processing :: Update values into the processing wizard during the processing
1369
            prog_id = self.update_processing_info(cr, uid, picking, prog_id, {
1370
                'prepare_pick': _('Done'),
1371
            }, context=context)
1372
2209.5.3 by Quentin THEURET
UTP-1147 [IMP] Now, it's possible to check the processing of an Incoming shipment and other actions are blocked (cancel of the IN, cancel of the move)
1373
        for picking in picking_ids:
1374
            prog_id = self.update_processing_info(cr, uid, picking, prog_id, {
1375
                'end_date': time.strftime('%Y-%m-%d %H:%M:%S')
1376
            }, context=context)
2222 by jf
UTP-1139 [IMP] Performance issue of the Orders sourcing tool
1377
2359.4.8 by duy.vo at msf
UF-2531: Further fixes for the name of PICK in CP when making a partial IN from RW
1378
        # UF-2531: Run the creation of message if it's at RW at some important point
1379
        if usb_entity == self.REMOTE_WAREHOUSE and not context.get('sync_message_execution', False):
2359.4.10 by duy.vo at msf
UF-2531: Temp commit: Fixed the returned packs from Shipment - code to be cleaned.
1380
            self._manual_create_rw_messages(cr, uid, context=context)
2359.4.8 by duy.vo at msf
UF-2531: Further fixes for the name of PICK in CP when making a partial IN from RW
1381
2165.14.16 by dvo at dvo
UF-2415: RW: INT and IN
1382
        if context.get('rw_sync', False):
2263.1.1 by Quentin THEURET
[FIX] Fix problen with IN processing wizard and synchronization engine
1383
            prog_id = self.update_processing_info(cr, uid, picking, prog_id, {
1384
                'end_date': time.strftime('%Y-%m-%d %H:%M:%S')
1385
            }, context=context)
2165.14.16 by dvo at dvo
UF-2415: RW: INT and IN
1386
            if backorder_id:
1387
                return backorder_id
1388
            return wizard.picking_id.id
2205 by jf
UF-2377 [IMP] RW: Sync OUTs between RW and main instances
1389
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1390
        if context.get('from_simu_screen'):
1391
            view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'view_picking_in_form')[1]
2630.2.1 by Quentin THEURET
US-612 [FIX] Return to the IN form view if user closed the processing wizard and disallow possibility to process two times the same IN
1392
            tree_view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'view_picking_in_tree')[1]
1393
            src_view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'view_picking_in_search')[1]
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1394
            return {
1395
                'type': 'ir.actions.act_window',
1396
                'res_model': 'stock.picking',
2058.1.1 by Quentin THEURET
REF-86 [FIX] Fixed error of the view returned when the IN coming from import simulation screen (was PICK, now: IN BO or closed IN)
1397
                'res_id': wizard.picking_id.id,
2630.2.1 by Quentin THEURET
US-612 [FIX] Return to the IN form view if user closed the processing wizard and disallow possibility to process two times the same IN
1398
                'view_id': [view_id, tree_view_id],
1399
                'search_view_id': src_view_id,
1994.9.2 by Quentin THEURET
REF-9 [IMP] Improve the do_incoming_shipment method
1400
                'view_mode': 'form, tree',
1401
                'view_type': 'form',
1402
                'target': 'crush',
1403
                'context': context}
1404
1405
        return {'type': 'ir.actions.act_window_close'}
1406
2359.4.10 by duy.vo at msf
UF-2531: Temp commit: Fixed the returned packs from Shipment - code to be cleaned.
1407
    def _manual_create_rw_messages(self, cr, uid, context=None):
2359.4.7 by dvo at dvo
UF-2531: Various fix for the creation of RW messages - now create manual frequently to make sure the order and content of messages are kept correctly
1408
        return
1409
2449.2.3 by duy.vo at msf
US-28: Added a check if the instance is RW, warning when cancel
1410
    @check_rw_warning
451.3.26 by chloups208
uf-655 enter reason wizard
1411
    def enter_reason(self, cr, uid, ids, context=None):
1412
        '''
1413
        open reason wizard
1414
        '''
1415
        # we need the context for the wizard switch
1416
        if context is None:
1417
            context = {}
1418
        # data
1419
        name = _("Enter a Reason for Incoming cancellation")
1420
        model = 'enter.reason'
1421
        step = 'default'
1422
        wiz_obj = self.pool.get('wizard')
1423
        # open the selected wizard
1424
        return wiz_obj.open_wizard(cr, uid, ids, name=name, model=model, step=step, context=dict(context, picking_id=ids[0]))
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1425
451.3.24 by chloups208
uf-655 cancel and update OUT
1426
    def cancel_and_update_out(self, cr, uid, ids, context=None):
1427
        '''
1428
        update corresponding out picking if exists and cancel the picking
1429
        '''
1430
        if context is None:
1431
            context = {}
1432
        if isinstance(ids, (int, long)):
1433
            ids = [ids]
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1434
451.3.24 by chloups208
uf-655 cancel and update OUT
1435
        # objects
1436
        move_obj = self.pool.get('stock.move')
451.3.35 by chloups208
uf-655 created moves see their name updated, tests are updated for new inverted openerp logic for in backorders
1437
        purchase_obj = self.pool.get('purchase.order')
1438
        # workflow
1439
        wf_service = netsvc.LocalService("workflow")
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1440
451.3.24 by chloups208
uf-655 cancel and update OUT
1441
        for obj in self.browse(cr, uid, ids, context=context):
559.7.1 by chloups208
uf-655 state of the workflow automaticly corrected
1442
            # corresponding sale ids to be manually corrected after purchase workflow trigger
1443
            sale_ids = []
451.3.24 by chloups208
uf-655 cancel and update OUT
1444
            for move in obj.move_lines:
2113.2.1 by duy.vo at msf
UFTP-126: Fixed a small but blocker bug
1445
                data_back = move_obj.create_data_back(move)
451.3.24 by chloups208
uf-655 cancel and update OUT
1446
                diff_qty = -data_back['product_qty']
1105.3.10 by chloups208
uf-1191 huge refactoring of related stock picking and stock move process in order to incorporate new sequencing policy
1447
                # update corresponding out move - no move created, no need to handle line sequencing policy
451.3.24 by chloups208
uf-655 cancel and update OUT
1448
                out_move_id = self._update_mirror_move(cr, uid, ids, data_back, diff_qty, out_move=False, context=context)
451.3.35 by chloups208
uf-655 created moves see their name updated, tests are updated for new inverted openerp logic for in backorders
1449
                # for out cancellation, two points:
451.3.38 by chloups208
uf-655 cancel corresponding out move
1450
                # - if pick/pack/ship: check that nothing is in progress
1451
                # - if nothing in progress, and the out picking is canceled, trigger the so to correct the corresponding so manually
1452
                if out_move_id:
1453
                    out_move = move_obj.browse(cr, uid, out_move_id, context=context)
1454
                    cond1 = out_move.picking_id.subtype == 'standard'
2198.4.1 by Quentin THEURET
UTP-1019 [FIX] Fix error when trying to cancel an incoming shipment linked to an OUTgoing delivery
1455
                    cond2 = out_move.picking_id.subtype == 'picking'
1456
                    cond3 = cond2 and out_move.picking_id.has_picking_ticket_in_progress(context=context)[out_move.picking_id.id]
1422.15.9 by Quentin THEURET
UF-1616 [FIX] FIx unit tests
1457
                    if out_move.picking_id.subtype in ('standard', 'picking') and out_move.picking_id.type == 'out' and not out_move.product_qty:
2309.4.8 by Quentin THEURET
UFTP-345 [FIX] Cancel the procurement orders when the OUT have been canceled
1458
                        move_id = False
1459
                        if out_move.picking_id and out_move.sale_line_id:
1460
                            # replace the stock move in the procurement order by the non cancelled stock move
1422.15.9 by Quentin THEURET
UF-1616 [FIX] FIx unit tests
1461
                            sale_id = out_move.picking_id.sale_id.id
2309.4.8 by Quentin THEURET
UFTP-345 [FIX] Cancel the procurement orders when the OUT have been canceled
1462
                            move_domain = [
1463
                                ('picking_id.type', '=', 'out'),
1464
                                ('picking_id.subtype', 'in', ('standard', 'picking')),
1465
                                #('picking_id.sale_id', '=', sale_id),
1466
                                ('sale_line_id', '=', out_move.sale_line_id.id),
1467
                                ('id', '!=', out_move_id),
1468
                                ('processed_stock_move', '=', True),
1469
                            ]
1470
                            move_domain_not_done = move_domain
1471
                            move_domain_not_cancel = move_domain
1472
                            move_domain_not_done.append(('state', 'not in', ['done', 'cancel']))
1473
                            move_domain_not_cancel.append(('state', '!=', 'cancel'))
1474
1475
                            move_id = move_obj.search(cr, uid, move_domain_not_done, context=context)
1476
                            if not move_id:
1477
                                move_id = move_obj.search(cr, uid, move_domain_not_cancel, context=context)
1478
1422.15.9 by Quentin THEURET
UF-1616 [FIX] FIx unit tests
1479
                            if move_id:
1480
                                proc_id = self.pool.get('procurement.order').search(cr, uid, [('move_id', '=', out_move_id)], context=context)
1481
                                self.pool.get('procurement.order').write(cr, uid, proc_id, {'move_id': move_id[0]}, context=context)
2309.4.8 by Quentin THEURET
UFTP-345 [FIX] Cancel the procurement orders when the OUT have been canceled
1482
451.3.38 by chloups208
uf-655 cancel corresponding out move
1483
                        # the corresponding move can be canceled - the OUT picking workflow is triggered automatically if needed
1484
                        move_obj.action_cancel(cr, uid, [out_move_id], context=context)
1485
                        # open points:
1486
                        # - when searching for open picking tickets - we should take into account the specific move (only product id ?)
1487
                        # - and also the state of the move not in (cancel done)
451.3.39 by chloups208
uf-655 sale order workflow integration
1488
                        # correct the corresponding so manually if exists - could be in shipping exception
1489
                        if out_move.picking_id and out_move.picking_id.sale_id:
559.7.1 by chloups208
uf-655 state of the workflow automaticly corrected
1490
                            if out_move.picking_id.sale_id.id not in sale_ids:
1491
                                sale_ids.append(out_move.picking_id.sale_id.id)
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1492
2308.12.1 by duy.vo at msf
UFTP-345: Close the related PICK if IN got cancelled and all PICK lines are done/cancel + qty=0
1493
                    # UFTP-345: Check if all lines from the original pick are either closed or cancel and qty is 0, then close this PICK
2308.12.2 by duy.vo at msf
UFTP-345: Close in case some lines are available but qty=0, and no in progress shipment
1494
                    mirror_pick = out_move.picking_id
2309.4.5 by Quentin THEURET
UFTP-345 [FIX] Fix problem when canceling an IN with batch management products
1495
                    if mirror_pick and mirror_pick.id:
2308.12.2 by duy.vo at msf
UFTP-345: Close in case some lines are available but qty=0, and no in progress shipment
1496
                        ptc = self.browse(cr, uid, mirror_pick.id, context=context)
2308.12.1 by duy.vo at msf
UFTP-345: Close the related PICK if IN got cancelled and all PICK lines are done/cancel + qty=0
1497
                        if all(m.product_qty == 0.00 and m.state in ('done', 'cancel') for m in ptc.move_lines):
1498
                            ptc.action_done(context=context)
2542.13.1 by Quentin THEURET
US-307 [FIX] Fix issue when canceling IN
1499
                        elif mirror_pick.subtype == 'picking' and ptc.state == 'draft':
2308.12.2 by duy.vo at msf
UFTP-345: Close in case some lines are available but qty=0, and no in progress shipment
1500
                            # If there are still some lines available with qty 0, then check if any in progress PICK, if all complete, then close the PICK
2309.4.5 by Quentin THEURET
UFTP-345 [FIX] Fix problem when canceling an IN with batch management products
1501
                            self.validate(cr, uid, [mirror_pick.id], context=context)
1502
2165.5.2 by Quentin THEURET
UFTP-141 [FIX] If an Incoming shipment that comes from a replenishment rules is canceled, cancel also the procurement order
1503
                if move.purchase_line_id and move.purchase_line_id.procurement_id:
1504
                    procurement = move.purchase_line_id.procurement_id
1505
                    if not procurement.sale_id and procurement.move_id:
1506
                        self.pool.get('stock.move').action_cancel(cr, uid, [move.purchase_line_id.procurement_id.move_id.id])
1507
                        wf_service.trg_validate(uid, 'procurement.order', move.purchase_line_id.procurement_id.id, 'button_cancel', cr)
1508
2324 by jf
UFTP-379 [FIX] C&R IN does not work sync well at project
1509
451.3.35 by chloups208
uf-655 created moves see their name updated, tests are updated for new inverted openerp logic for in backorders
1510
            # correct the corresponding po manually if exists - should be in shipping exception
1511
            if obj.purchase_id:
1512
                wf_service.trg_validate(uid, 'purchase.order', obj.purchase_id.id, 'picking_ok', cr)
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
1513
                msg_log = _('The Purchase Order %s is %s%% received.') % (obj.purchase_id.name, round(obj.purchase_id.shipped_rate, 2))
1514
                purchase_obj.log(cr, uid, obj.purchase_id.id, msg_log)
2309.4.7 by Quentin THEURET
UFTP-345 [FIX] If IN Backorder is canceled while the OUT linked to the closed IN is not processed, the FO was closed
1515
559.7.1 by chloups208
uf-655 state of the workflow automaticly corrected
1516
            # correct the corresponding so
1517
            for sale_id in sale_ids:
2309.4.8 by Quentin THEURET
UFTP-345 [FIX] Cancel the procurement orders when the OUT have been canceled
1518
                wf_service.trg_write(uid, 'sale.order', sale_id, cr)
559.7.8 by chloups208
uf-655 all so are manually corrected when multiple so are regrouped within one same po
1519
                wf_service.trg_validate(uid, 'sale.order', sale_id, 'ship_corrected', cr)
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1520
451.3.24 by chloups208
uf-655 cancel and update OUT
1521
        return True
1851.9.2 by Quentin THEURET
UTP-647 [IMP] Create and close automatically the internal move after an incoming shipment direct to stock
1522
2209.5.3 by Quentin THEURET
UTP-1147 [IMP] Now, it's possible to check the processing of an Incoming shipment and other actions are blocked (cancel of the IN, cancel of the move)
1523
    def write(self, cr, uid, ids, vals, context=None):
1524
        '''
1525
        Return True in case of context contains "go_to_processing_wizard" because
2222 by jf
UTP-1139 [IMP] Performance issue of the Orders sourcing tool
1526
        without that, the displaying of the wizard waits that the background
2209.5.3 by Quentin THEURET
UTP-1147 [IMP] Now, it's possible to check the processing of an Incoming shipment and other actions are blocked (cancel of the IN, cancel of the move)
1527
        process (SQL LOCK on row)
1528
        '''
1529
        if context is None:
1530
            context = {}
1531
1532
        if context.get('button', False) == 'go_to_processing_wizard':
1533
            return True
1534
        elif context.get('button', False) == 'enter_reason':
1535
            mem_obj = self.pool.get('stock.picking.processing.info')
1536
            mem_ids = mem_obj.search(cr, uid, [
1537
                ('end_date', '=', False),
1538
                ('picking_id', 'in', ids),
1539
            ], context=context)
1540
            if mem_ids:
1541
                raise osv.except_osv(
1542
                    _('Error'),
1543
                    _('The processing of this picking is in progress - You can\'t cancel it.'),
1544
                )
1545
1546
        return super(stock_picking, self).write(cr, uid, ids, vals, context=context)
1547
1548
451.3.1 by chloups208
uf-655
1549
stock_picking()
451.3.3 by chloups208
uf-655
1550
1551
1552
class purchase_order_line(osv.osv):
1553
    '''
1554
    add the link to procurement order
1555
    '''
1556
    _inherit = 'purchase.order.line'
2038.1.2 by Quentin THEURET
REF-61 [IMP] Clean the code of delivery_mechanism/delivery_mechanism.py
1557
    _columns = {
1558
        'procurement_id': fields.many2one(
1559
            'procurement.order',
1560
            string='Procurement Reference',
1561
            readonly=True,
1562
        ),
1563
    }
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1564
    _defaults = {'procurement_id': False, }
1565
451.3.3 by chloups208
uf-655
1566
purchase_order_line()
1567
1568
1569
class procurement_order(osv.osv):
1570
    '''
1571
    inherit po_values_hook
1572
    '''
1573
    _inherit = 'procurement.order'
1574
1575
    def po_line_values_hook(self, cr, uid, ids, context=None, *args, **kwargs):
1576
        '''
1577
        Please copy this to your module's method also.
1578
        This hook belongs to the make_po method from purchase>purchase.py>procurement_order
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1579
451.3.3 by chloups208
uf-655
1580
        - allow to modify the data for purchase order line creation
1581
        '''
451.3.15 by chloups208
uf-655: change product + tests
1582
        if isinstance(ids, (int, long)):
1583
            ids = [ids]
892.15.19 by matthieu.choplin at msf
removed duplicated data and make workiing the make to order from IR but still a pb: the uom should be the same as the ghost product but the user can select the uom he want
1584
        sale_obj = self.pool.get('sale.order.line')
451.3.3 by chloups208
uf-655
1585
        line = super(procurement_order, self).po_line_values_hook(cr, uid, ids, context=context, *args, **kwargs)
1586
        # give the purchase order line a link to corresponding procurement
1587
        procurement = kwargs['procurement']
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1588
        line.update({'procurement_id': procurement.id, })
892.15.19 by matthieu.choplin at msf
removed duplicated data and make workiing the make to order from IR but still a pb: the uom should be the same as the ghost product but the user can select the uom he want
1589
        # for Internal Request (IR) on make_to_order we update PO line data according to the data of the IR (=sale_order)
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1590
        sale_order_line_ids = sale_obj.search(cr, uid, [('procurement_id', '=', procurement.id)], context=context)
892.15.19 by matthieu.choplin at msf
removed duplicated data and make workiing the make to order from IR but still a pb: the uom should be the same as the ghost product but the user can select the uom he want
1591
        for sol in sale_obj.browse(cr, uid, sale_order_line_ids, context=context):
1592
            if sol.order_id.procurement_request and not sol.product_id and sol.comment:
1593
                line.update({'product_id': False,
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1594
                             'name': 'Description: %s' % sol.comment,
892.15.19 by matthieu.choplin at msf
removed duplicated data and make workiing the make to order from IR but still a pb: the uom should be the same as the ghost product but the user can select the uom he want
1595
                             'comment': sol.comment,
1596
                             'product_qty': sol.product_uom_qty,
1597
                             'price_unit': sol.price_unit,
1598
                             'date_planned': sol.date_planned,
1599
                             'product_uom': sol.product_uom.id,
1600
                             'nomen_manda_0': sol.nomen_manda_0.id,
1601
                             'nomen_manda_1': sol.nomen_manda_1.id or False,
1602
                             'nomen_manda_2': sol.nomen_manda_2.id or False,
1603
                             'nomen_manda_3': sol.nomen_manda_3.id or False,
1604
                             'nomen_sub_0': sol.nomen_sub_0.id or False,
1605
                             'nomen_sub_1': sol.nomen_sub_1.id or False,
1606
                             'nomen_sub_2': sol.nomen_sub_2.id or False,
1607
                             'nomen_sub_3': sol.nomen_sub_3.id or False,
1608
                             'nomen_sub_4': sol.nomen_sub_4.id or False,
1609
                             'nomen_sub_5': sol.nomen_sub_5.id or False})
451.3.3 by chloups208
uf-655
1610
        return line
1994.1.33 by Quentin THEURET
REF-27 [IMP] Call the good method when processing an incoming shipment
1611
451.3.3 by chloups208
uf-655
1612
procurement_order()