111
91
productObj = self.pool.get('product.product')
113
# UF-1411 : Compute the virtual stock on Stock + Input locations
115
wids = self.pool.get('stock.warehouse').search(cr, uid, [], context=context)
116
for w in self.pool.get('stock.warehouse').browse(cr, uid, wids, context=context):
117
location_ids.append(w.lot_stock_id.id)
118
location_ids.append(w.lot_input_id.id)
120
92
# for each sourcing line
121
93
for sl in self.browse(cr, uid, ids, context):
122
product_context = context
123
rts = sl.rts < time.strftime('%Y-%m-%d') and time.strftime('%Y-%m-%d') or sl.rts
124
product_context.update({'location': location_ids, 'to_date': '%s 23:59:59' % rts})
126
product_virtual = productObj.browse(cr, uid, sl.product_id.id, context=product_context)
127
res = product_virtual.virtual_available
95
productId = sl.product_id.id
97
productList = [productId]
100
res = productObj.get_product_available(cr, uid, productList, context={'states': ('confirmed','waiting','assigned','done'),
101
'what': ('in', 'out'),
103
result[sl.id] = res.get(productId, 0.0)
135
107
_name = 'sourcing.line'
136
108
_description = 'Sourcing Line'
138
def _get_sourcing_vals(self, cr, uid, ids, fields, arg, context=None):
140
returns the value from the sale.order
142
if isinstance(fields, str):
145
for obj in self.browse(cr, uid, ids, context=context):
148
result[obj.id].update({f: False,})
149
# gather procurement_request boolean
150
result[obj.id]['procurement_request'] = obj.sale_order_id and obj.sale_order_id.procurement_request or False
151
# gather sale order line state
152
result[obj.id]['state'] = obj.sale_order_line_id and obj.sale_order_line_id.state or False
153
# display confirm button - display if state == draft and not proc or state == progress and proc
154
result[obj.id]['display_confirm_button'] = (obj.state == 'draft' and obj.sale_order_id.state == 'validated')
156
result[obj.id]['sale_order_state'] = False
157
if obj.sale_order_id:
158
result[obj.id]['sale_order_state'] = obj.sale_order_id.state
159
if obj.sale_order_id.state == 'done' and obj.sale_order_id.split_type_sale_order == 'original_sale_order':
160
result[obj.id]['sale_order_state'] = 'split_so'
164
def _get_sale_order_ids(self, cr, uid, ids, context=None):
166
self represents sale.order
167
ids represents the ids of sale.order objects for which procurement_request has changed
169
return the list of ids of sourcing.line object which need to get their procurement_request field updated
171
if isinstance(ids, (int, long)):
173
# list of sourcing lines having sale_order_id within ids
174
result = self.pool.get('sourcing.line').search(cr, uid, [('sale_order_id', 'in', ids)], context=context)
177
def _get_sale_order_line_ids(self, cr, uid, ids, context=None):
179
self represents sale.order.line
180
ids represents the ids of sale.order.line objects for which state has changed
182
return the list of ids of sourcing.line object which need to get their state field updated
184
if isinstance(ids, (int, long)):
186
# list of sourcing lines having sale_order_line_id within ids
187
result = self.pool.get('sourcing.line').search(cr, uid, [('sale_order_line_id', 'in', ids)], context=context)
190
def _get_souring_lines_ids(self, cr, uid, ids, context=None):
192
self represents sourcing.line
193
ids represents the ids of sourcing.line objects for which a field has changed
195
return the list of ids of sourcing.line object which need to get their field updated
197
if isinstance(ids, (int, long)):
203
def _get_fake(self, cr, uid, ids, fields, arg, context=None):
204
if isinstance(ids, (int, long)):
211
def _search_need_sourcing(self, cr, uid, obj, name, args, context=None):
215
if args[0][1] != '=' or not args[0][2]:
216
raise osv.except_osv(_('Error !'), _('Filter not implemented'))
218
return [('state', '=', 'draft'), ('sale_order_state', '=', 'validated')]
220
def _search_sale_order_state(self, cr, uid, obj, name, args, context=None):
227
raise osv.except_osv(_('Error !'), _('Filter not implemented'))
229
if arg[2] == 'progress':
230
newargs.append(('sale_order_state', 'in', ['progress', 'manual']))
232
newargs.append(('sale_order_state', arg[1], arg[2]))
235
def _get_date(self, cr, uid, ids, field_name, args, context=None):
238
for line in self.browse(cr, uid, ids, context=context):
239
res[line.id] = {'estimated_delivery_date': False,
242
delay = self.onChangeSupplier(cr, uid, [line.id], line.supplier.id, context=context).get('value', {}).get('estimated_delivery_date', False)
243
res[line.id]['estimated_delivery_date'] = line.cf_estimated_delivery_date and line.state in ('done', 'confirmed') and line.cf_estimated_delivery_date or delay
245
## tr_lt = line.sale_order_id and line.sale_order_id.est_transport_lead_time or 0.00
246
# ship_lt = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.shipment_lead_time
247
# res[line.id]['rts'] = datetime.strptime(line.sale_order_line_id.date_planned, '%Y-%m-%d') - relativedelta(days=int(tr_lt)) - relativedelta(days=int(ship_lt))
248
# res[line.id]['rts'] = res[line.id]['rts'].strftime('%Y-%m-%d')
249
res[line.id]['rts'] = line.sale_order_id.ready_to_ship_date
254
110
# sequence number
255
111
'name': fields.char('Name', size=128),
256
'sale_order_id': fields.many2one('sale.order', 'Order', on_delete='cascade', readonly=True),
257
'sale_order_line_id': fields.many2one('sale.order.line', 'Order Line', on_delete='cascade', readonly=True),
258
'customer': fields.many2one('res.partner', 'Customer', readonly=True),
112
'sale_order_id': fields.many2one('sale.order', 'Sale Order', on_delete='cascade', readonly=True),
113
'sale_order_line_id': fields.many2one('sale.order.line', 'Sale Order Line', on_delete='cascade', readonly=True),
259
114
'reference': fields.related('sale_order_id', 'name', type='char', size=128, string='Reference', readonly=True),
260
# 'state': fields.related('sale_order_line_id', 'state', type="selection", selection=_SELECTION_SALE_ORDER_LINE_STATE, readonly=True, string="State", store=False),
261
'state': fields.function(_get_sourcing_vals, method=True, type='selection', selection=_SELECTION_SALE_ORDER_LINE_STATE, string='State', multi='get_vals_sourcing',
262
store={'sale.order.line': (_get_sale_order_line_ids, ['state'], 10),
263
'sourcing.line': (_get_souring_lines_ids, ['sale_order_line_id'], 10)}),
115
'state': fields.related('sale_order_line_id', 'state', type="selection", selection=_SELECTION_SALE_ORDER_LINE_STATE, readonly=True, string="State", store=False),
264
116
'priority': fields.selection(ORDER_PRIORITY, string='Priority', readonly=True),
265
117
'categ': fields.selection(ORDER_CATEGORY, string='Category', readonly=True),
266
# I do not directly set the store on state_hidden_sale_order because I did not find definitive clue that dynamic store could be used in cascade
267
'sale_order_state': fields.function(_get_sourcing_vals, method=True, readonly=True, type='selection', selection=_SELECTION_SALE_ORDER_STATE, string='Order State', multi='get_vals_sourcing',
268
store={'sale.order': (_get_sale_order_ids, ['state', 'split_type_sale_order'], 10),
269
'sourcing.line': (_get_souring_lines_ids, ['sale_order_id'], 10)}),
270
# 'sale_order_state': fields.selection(_SELECTION_SALE_ORDER_STATE, string="Order State", readonly=True),
271
'sale_order_state_search': fields.function(_get_fake, string="Order State", type='selection', method=True, selection=[x for x in SALE_ORDER_STATE_SELECTION if x[0] != 'manual'], fnct_search=_search_sale_order_state),
118
'sale_order_state': fields.selection(_SELECTION_SALE_ORDER_STATE, string="Order State", readonly=True),
272
119
'line_number': fields.integer(string='Line', readonly=True),
273
120
'product_id': fields.many2one('product.product', string='Product', readonly=True),
274
121
'qty': fields.related('sale_order_line_id', 'product_uom_qty', type='float', string='Quantity', readonly=True),
275
122
'uom_id': fields.related('sale_order_line_id', 'product_uom', relation='product.uom', type='many2one', string='UoM', readonly=True),
276
#'rts': fields.related('sale_order_id', 'ready_to_ship_date', type='date', string='RTS', readonly=True),
277
'rts': fields.function(_get_date, type='date', method=True, string='RTS', readonly=True, store=False, multi='dates'),
123
'rts': fields.related('sale_order_id', 'delivery_requested_date', type='date', string='RTS', readonly=True),
278
124
'sale_order_line_state': fields.related('sale_order_line_id', 'state', type="selection", selection=_SELECTION_SALE_ORDER_LINE_STATE, readonly=True, store=False),
279
125
'type': fields.selection(_SELECTION_TYPE, string='Procurement Method', readonly=True, states={'draft': [('readonly', False)]}),
280
126
'po_cft': fields.selection(_SELECTION_PO_CFT, string='PO/CFT', readonly=True, states={'draft': [('readonly', False)]}),
281
127
'real_stock': fields.related('product_id', 'qty_available', type='float', string='Real Stock', readonly=True),
128
'available_stock': fields.float('Available Stock', readonly=True),
282
129
'virtual_stock': fields.function(_getVirtualStock, method=True, type='float', string='Virtual Stock', digits_compute=dp.get_precision('Product UoM'), readonly=True),
283
'available_stock': fields.function(_getAvailableStock, method=True, type='float', string='Available Stock', digits_compute=dp.get_precision('Product UoM'), readonly=True),
284
130
'supplier': fields.many2one('res.partner', 'Supplier', readonly=True, states={'draft': [('readonly', False)]}, domain=[('supplier', '=', True)]),
285
'cf_estimated_delivery_date': fields.date(string='Estimated DD', readonly=True),
286
'estimated_delivery_date': fields.function(_get_date, type='date', method=True, store=False, string='Estimated DD', readonly=True, multi='dates'),
287
'company_id': fields.many2one('res.company','Company',select=1),
288
'procurement_request': fields.function(_get_sourcing_vals, method=True, type='boolean', string='Procurement Request', multi='get_vals_sourcing',
289
store={'sale.order': (_get_sale_order_ids, ['procurement_request'], 10),
290
'sourcing.line': (_get_souring_lines_ids, ['sale_order_id'], 10)}),
291
'display_confirm_button': fields.function(_get_sourcing_vals, method=True, type='boolean', string='Display Button', multi='get_vals_sourcing',),
292
'need_sourcing': fields.function(_get_fake, method=True, type='boolean', string='Only for filtering', fnct_search=_search_need_sourcing),
131
'estimated_delivery_date': fields.date(string='Estimated DD', readonly=True),
294
133
_order = 'sale_order_id desc, line_number'
296
135
'name': lambda self, cr, uid, context=None: self.pool.get('ir.sequence').get(cr, uid, 'sourcing.line'),
297
'company_id': lambda obj, cr, uid, context: obj.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id,
300
def _check_line_conditions(self, cr, uid, ids, context=None):
302
Check if the line have good values
306
if context.get('no_check_line', False):
309
if isinstance(ids, (int, long)):
311
for line in self.browse(cr, uid, ids, context=context):
312
if line.type == 'make_to_order' and line.po_cft not in ['cft'] and not line.product_id and \
313
line.sale_order_id.procurement_request and line.supplier and line.supplier.partner_type not in ['internal', 'section', 'intermission']:
314
raise osv.except_osv(_('Warning'), _("""For an Internal Request with a procurement method 'On Order' and without product, the supplier must be either in 'Internal', 'Inter-section' or 'Intermission type."""))
316
if not line.product_id:
317
if line.po_cft == 'cft':
318
raise osv.except_osv(_('Warning'), _("You can't source with 'Tender' if you don't have product."))
319
if line.type == 'make_to_stock':
320
raise osv.except_osv(_('Warning'), _("You can't Source 'from stock' if you don't have product."))
321
if line.supplier and line.supplier.partner_type in ('external', 'esc'):
322
raise osv.except_osv(_('Warning'), _("You can't Source to an '%s' partner if you don't have product.") % (line.supplier.partner_type == 'external' and 'External' or 'ESC'))
326
def open_split_wizard(self, cr, uid, ids, context=None):
328
Open the split line wizard
330
line = self.browse(cr, uid, ids[0], context=context)
331
return self.pool.get('sale.order.line').open_split_wizard(cr, uid, [line.sale_order_line_id.id], context=context)
333
138
def check_supplierinfo(self, cr, uid, ids, partner_id, context=None):
335
140
return the value of delay if the corresponding supplier is in supplier info the product
1001
641
_description = "Procurement"
1003
643
'supplier': fields.many2one('res.partner', 'Supplier'),
1004
'po_cft': fields.selection(_SELECTION_PO_CFT, string="PO/CFT"),
1007
def po_line_values_hook(self, cr, uid, ids, context=None, *args, **kwargs):
1009
Please copy this to your module's method also.
1010
This hook belongs to the make_po method from purchase>purchase.py>procurement_order
1012
- allow to modify the data for purchase order line creation
1014
line = super(procurement_order, self).po_line_values_hook(cr, uid, ids, context=context, *args, **kwargs)
1015
if 'procurement' in kwargs:
1016
order_line_ids = self.pool.get('sale.order.line').search(cr, uid, [('procurement_id', '=', kwargs['procurement'].id)])
1018
origin = self.pool.get('sale.order.line').browse(cr, uid, order_line_ids[0]).order_id.name
1019
line.update({'origin': origin})
1020
if line.get('price_unit', False) == False:
1021
st_price = self.pool.get('product.product').browse(cr, uid, line['product_id']).standard_price
1022
if 'pricelist' in kwargs:
1023
cur_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id
1024
st_price = self.pool.get('res.currency').compute(cr, uid, cur_id, kwargs['pricelist'].currency_id.id, st_price, round=False, context=context)
1025
line.update({'price_unit': st_price})
1028
def action_check_finished(self, cr, uid, ids):
1029
res = super(procurement_order, self).action_check_finished(cr, uid, ids)
1031
# If the procurement has been generated from an internal request, close the order
1032
for order in self.browse(cr, uid, ids):
1033
line_ids = self.pool.get('sale.order.line').search(cr, uid, [('procurement_id', '=', order.id)])
1034
for line in self.pool.get('sale.order.line').browse(cr, uid, line_ids):
1035
if line.order_id.procurement_request:
1040
def create_po_hook(self, cr, uid, ids, context=None, *args, **kwargs):
1042
if a purchase order for the same supplier and the same requested date,
1043
don't create a new one
1045
po_obj = self.pool.get('purchase.order')
1046
procurement = kwargs['procurement']
1047
values = kwargs['values']
1048
# Make the line as price changed manually to do not raise an error on purchase order line creation
1049
# if 'order_line' in values and len(values['order_line']) > 0 and len(values['order_line'][0]) > 2 and 'price_unit' in values['order_line'][0][2]:
1050
# values['order_line'][0][2].update({'change_price_manually': True})
1052
partner = self.pool.get('res.partner').browse(cr, uid, values['partner_id'], context=context)
1054
purchase_domain = [('partner_id', '=', partner.id),
1055
('state', '=', 'draft'),
1056
('rfq_ok', '=', False),
1057
('delivery_requested_date', '=', values.get('delivery_requested_date'))]
1059
if procurement.po_cft == 'dpo':
1060
purchase_domain.append(('order_type', '=', 'direct'))
1062
purchase_domain.append(('order_type', '!=', 'direct'))
1064
if partner.po_by_project == 'project' or procurement.po_cft == 'dpo':
1065
sale_line_ids = self.pool.get('sale.order.line').search(cr, uid, [('procurement_id', '=', procurement.id)], context=context)
1067
line = self.pool.get('sale.order.line').browse(cr, uid, sale_line_ids[0], context=context)
1068
if line.procurement_request:
1069
customer_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.partner_id.id
1071
customer_id = line.order_id.partner_id.id
1072
values.update({'customer_id': customer_id})
1073
purchase_domain.append(('customer_id', '=', customer_id))
1075
# if we are updating the sale order from the corresponding on order purchase order
1076
# the purchase order to merge the new line to is locked and provided in the procurement
1077
if procurement.so_back_update_dest_po_id_procurement_order:
1078
purchase_ids = [procurement.so_back_update_dest_po_id_procurement_order.id]
1080
# search for purchase order according to defined domain
1081
purchase_ids = po_obj.search(cr, uid, purchase_domain, context=context)
1083
# Set the origin of the line with the origin of the Procurement order
1084
if procurement.origin:
1085
values['order_line'][0][2].update({'origin': procurement.origin})
1087
if procurement.tender_id:
1088
if values.get('origin'):
1089
values['origin'] = '%s;%s' % (values['origin'], procurement.tender_id.name)
1091
values['origin'] = procurement.tender_id.name
1093
# Set the analytic distribution on PO line if an analytic distribution is on SO line or SO
1094
sol_ids = self.pool.get('sale.order.line').search(cr, uid, [('procurement_id', '=', procurement.id)], context=context)
1097
sol = self.pool.get('sale.order.line').browse(cr, uid, sol_ids[0], context=context)
1098
if sol.analytic_distribution_id:
1099
new_analytic_distribution_id = self.pool.get('analytic.distribution').copy(cr, uid,
1100
sol.analytic_distribution_id.id, context=context)
1101
values['order_line'][0][2].update({'analytic_distribution_id': new_analytic_distribution_id})
1102
elif sol.order_id.analytic_distribution_id:
1103
new_analytic_distribution_id = self.pool.get('analytic.distribution').copy(cr,
1104
uid, sol.order_id.analytic_distribution_id.id, context=context)
1105
values['order_line'][0][2].update({'analytic_distribution_id': new_analytic_distribution_id})
1106
elif procurement.product_id:
1107
if procurement.product_id.type == 'consu':
1108
location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock_override', 'stock_location_non_stockable')[1]
1109
elif procurement.product_id.type == 'service_recep':
1110
location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'msf_config_locations', 'stock_location_service')[1]
1112
wh_ids = self.pool.get('stock.warehouse').search(cr, uid, [])
1114
location_id = self.pool.get('stock.warehouse').browse(cr, uid, wh_ids[0]).lot_input_id.id
1116
location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'msf_config_locations', 'stock_location_service')[1]
1119
line_values = values['order_line'][0][2]
1120
line_values.update({'order_id': purchase_ids[0],'origin': procurement.origin})
1121
po = self.pool.get('purchase.order').browse(cr, uid, purchase_ids[0], context=context)
1122
# Update the origin of the PO with the origin of the procurement
1123
# and tender name if exist
1124
origins = set([po.origin, procurement.origin, procurement.tender_id and procurement.tender_id.name])
1125
# Add different origin on 'Source document' field if the origin is nat already listed
1126
origin = ';'.join(o for o in list(origins) if o and (not po.origin or o == po.origin or o not in po.origin))
1127
self.pool.get('purchase.order').write(cr, uid, purchase_ids[0], {'origin': origin}, context=context)
1130
self.pool.get('purchase.order').write(cr, uid, purchase_ids[0], {'location_id': location_id, 'cross_docking_ok': False}, context=context)
1131
self.pool.get('purchase.order.line').create(cr, uid, line_values, context=context)
1132
return purchase_ids[0]
1134
if procurement.po_cft == 'dpo':
1135
sol_ids = self.pool.get('sale.order.line').search(cr, uid, [('procurement_id', '=', procurement.id)], context=context)
1137
sol = self.pool.get('sale.order.line').browse(cr, uid, sol_ids[0], context=context)
1138
if not sol.procurement_request:
1139
values.update({'order_type': 'direct',
1140
'dest_partner_id': sol.order_id.partner_id.id,
1141
'dest_address_id': sol.order_id.partner_shipping_id.id})
1143
# Force the destination location of the Po to Input location
1144
company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
1145
warehouse_id = self.pool.get('stock.warehouse').search(cr, uid, [('company_id', '=', company_id)], context=context)
1147
input_id = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id[0], context=context).lot_input_id.id
1148
values.update({'location_id': input_id,})
1149
purchase_id = super(procurement_order, self).create_po_hook(cr, uid, ids, context=context, *args, **kwargs)
1152
646
def write(self, cr, uid, ids, vals, context=None):
1154
648
override for workflow modification
1156
650
return super(procurement_order, self).write(cr, uid, ids, vals, context)
1158
def _partner_check_hook(self, cr, uid, ids, context=None, *args, **kwargs):
1160
check the if supplier is available or not
1162
the new selection field does not exist when the procurement has been produced by
1163
an order_point (minimum stock rules). in this case we take the default supplier from product
1165
same cas if no supplier were selected in the sourcing tool
1167
return True if a supplier is available
1169
procurement = kwargs['procurement']
1170
# add supplier check in procurement object from sourcing tool
1171
result = procurement.supplier or super(procurement_order, self)._partner_check_hook(cr, uid, ids, context=context, *args, **kwargs)
1174
def _partner_get_hook(self, cr, uid, ids, context=None, *args, **kwargs):
1176
returns the partner from procurement or suppinfo
1178
the new selection field does not exist when the procurement has been produced by
1179
an order_point (minimum stock rules). in this case we take the default supplier from product
1181
same cas if no supplier were selected in the sourcing tool
1183
procurement = kwargs['procurement']
1184
# the specified supplier in sourcing tool has priority over suppinfo
1185
partner = procurement.supplier or super(procurement_order, self)._partner_get_hook(cr, uid, ids, context=context, *args, **kwargs)
1186
if partner.id == self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id:
1187
cr.execute('update procurement_order set message=%s where id=%s',
1188
(_('Impossible to make a Purchase Order to your own company !'), procurement.id))
1191
def get_delay_qty(self, cr, uid, ids, partner, product, context=None):
1193
find corresponding values for seller_qty and seller_delay from product supplierinfo or default values
1196
# if the supplier is present in product seller_ids, we take that quantity from supplierinfo
1198
# seller_qty default value
1201
for suppinfo in product.seller_ids:
1202
if suppinfo.name.id == partner.id:
1203
seller_qty = suppinfo.qty
1204
seller_delay = int(suppinfo.delay)
1206
# if not, default delay from supplier (partner.default_delay)
1207
if seller_delay < 0:
1208
seller_delay = partner.default_delay
1210
result.update(seller_qty=seller_qty,
1211
seller_delay=seller_delay,)
652
# @@@override procurement.py > procurement.order > check_buy
653
def check_buy(self, cr, uid, ids):
654
""" Checks product type.
655
@return: True or Product Id.
657
user = self.pool.get('res.users').browse(cr, uid, uid)
658
partner_obj = self.pool.get('res.partner')
659
for procurement in self.browse(cr, uid, ids):
660
if procurement.product_id.product_tmpl_id.supply_method <> 'buy':
662
# use new selection field instead
663
# the new selection field does not exist when the procurement has been produced by
664
# an order_point (minimum stock rules). in this case we take the default supplier from product
665
#if not procurement.product_id.seller_ids:
666
if not procurement.supplier and not procurement.product_id.seller_ids:
667
cr.execute('update procurement_order set message=%s where id=%s',
668
(_('No supplier defined for this product !'), procurement.id))
670
# use new selection field instead, **FIRST** the new one, and if not exist, from product
671
# the new selection field does not exist when the procurement has been produced by
672
# an order_point (minimum stock rules). in this case we take the default supplier from product
673
#partner = procurement.product_id.seller_id #Taken Main Supplier of Product of Procurement.
674
partner = procurement.supplier or procurement.product_id.seller_id
676
if user.company_id and user.company_id.partner_id:
677
if partner.id == user.company_id.partner_id.id:
679
address_id = partner_obj.address_get(cr, uid, [partner.id], ['delivery'])['delivery']
681
cr.execute('update procurement_order set message=%s where id=%s',
682
(_('No address defined for the supplier'), procurement.id))
687
# @@@override purchase>purchase.py>procurement_order
688
def make_po(self, cr, uid, ids, context=None):
689
""" Make purchase order from procurement
690
@return: New created Purchase Orders procurement wise
695
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
696
partner_obj = self.pool.get('res.partner')
697
uom_obj = self.pool.get('product.uom')
698
pricelist_obj = self.pool.get('product.pricelist')
699
prod_obj = self.pool.get('product.product')
700
acc_pos_obj = self.pool.get('account.fiscal.position')
701
po_obj = self.pool.get('purchase.order')
702
for procurement in self.browse(cr, uid, ids, context=context):
703
res_id = procurement.move_id.id
704
# use new selection field instead, **FIRST** the new one, and if not exist, from product
705
# the new selection field does not exist when the procurement has been produced by
706
# an order_point (minimum stock rules). in this case we take the default supplier from product
707
if procurement.supplier:
708
partner = procurement.supplier
709
# if the supplier is present in product seller_ids, we take that quantity from supplierinfo
713
for suppinfo in procurement.product_id.seller_ids:
714
if suppinfo.name.id == partner.id:
715
seller_qty = suppinfo.qty
716
seller_delay = int(suppinfo.delay)
721
# if not, default delay from supplier (partner.default_delay)
723
seller_delay = partner.default_delay
726
partner = procurement.product_id.seller_id # Taken Main Supplier of Product of Procurement.
727
seller_qty = procurement.product_id.seller_qty
728
seller_delay = int(procurement.product_id.seller_delay)
1215
def get_partner_hook(self, cr, uid, ids, context=None, *args, **kwargs):
1217
get data from supplier
1219
return also the price_unit
1221
tender_line_obj = self.pool.get('tender_line')
1222
# get default values
1223
result = super(procurement_order, self).get_partner_hook(cr, uid, ids, context=context, *args, **kwargs)
1224
procurement = kwargs['procurement']
1226
# this is kept here and not moved in the tender_flow module
1227
# because we have no control on the order of inherited function call (do we?)
1228
# and if we have tender and supplier defined and supplier code is ran after
1229
# tender one, the supplier will be use while tender has priority
1230
if procurement.is_tender:
1231
# tender line -> search for info about this product in the corresponding tender
1232
# if nothing found, we keep default values from super
1233
for sol in procurement.sale_order_line_ids:
1234
for tender_line in sol.tender_line_ids:
1235
# if a tender rfq has been selected for this sale order line
1236
if tender_line.purchase_order_line_id:
1237
partner = tender_line.supplier_id
1238
price_unit = tender_line.price_unit
1239
# get corresponding delay and qty
1240
delay_qty = self.get_delay_qty(cr, uid, ids, partner, procurement.product_id, context=None)
1241
seller_delay = delay_qty['seller_delay']
1242
seller_qty = delay_qty['seller_qty']
1243
result.update(partner=partner,
1244
seller_qty=seller_qty,
1245
seller_delay=seller_delay,
1246
price_unit=price_unit)
1248
elif procurement.supplier:
1249
# not tender, we might have a selected supplier from sourcing tool
1250
# if not, we keep default values from super
1251
partner = procurement.supplier
1252
# get corresponding delay and qty
1253
delay_qty = self.get_delay_qty(cr, uid, ids, partner, procurement.product_id, context=None)
1254
seller_delay = delay_qty['seller_delay']
1255
seller_qty = delay_qty['seller_qty']
1256
result.update(partner=partner,
1257
seller_qty=seller_qty,
1258
seller_delay=seller_delay)
730
partner_id = partner.id
731
address_id = partner_obj.address_get(cr, uid, [partner_id], ['delivery'])['delivery']
732
pricelist_id = partner.property_product_pricelist_purchase.id
734
uom_id = procurement.product_id.uom_po_id.id
736
qty = uom_obj._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, uom_id)
738
qty = max(qty,seller_qty)
740
price = pricelist_obj.price_get(cr, uid, [pricelist_id], procurement.product_id.id, qty, partner_id, {'uom': uom_id})[pricelist_id]
742
newdate = datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S')
743
newdate = (newdate - relativedelta(days=company.po_lead)) - relativedelta(days=int(seller_delay))
745
#Passing partner_id to context for purchase order line integrity of Line name
746
context.update({'lang': partner.lang, 'partner_id': partner_id})
748
product = prod_obj.browse(cr, uid, procurement.product_id.id, context=context)
751
'name': product.partner_ref,
753
'product_id': procurement.product_id.id,
754
'product_uom': uom_id,
756
'date_planned': newdate.strftime('%Y-%m-%d %H:%M:%S'),
757
'move_dest_id': res_id,
758
'notes': product.description_purchase,
761
taxes_ids = procurement.product_id.product_tmpl_id.supplier_taxes_id
762
taxes = acc_pos_obj.map_tax(cr, uid, partner.property_account_position, taxes_ids)
764
'taxes_id': [(6,0,taxes)]
766
purchase_id = po_obj.create(cr, uid, {
767
'origin': procurement.origin,
768
'partner_id': partner_id,
769
'partner_address_id': address_id,
770
'location_id': procurement.location_id.id,
771
'pricelist_id': pricelist_id,
772
'order_line': [(0,0,line)],
773
'company_id': procurement.company_id.id,
774
'fiscal_position': partner.property_account_position and partner.property_account_position.id or False
776
res[procurement.id] = purchase_id
777
self.write(cr, uid, [procurement.id], {'state': 'running', 'purchase_id': purchase_id})
1262
781
procurement_order()
1394
886
return super(product_supplierinfo, self).create(cr, uid, values, context)
1396
888
product_supplierinfo()
1399
class res_partner(osv.osv):
1400
_name = 'res.partner'
1401
_inherit = 'res.partner'
1403
def _get_available_for_dpo(self, cr, uid,ids, field_name, args, context=None):
1405
Return for each partner if he's available for DPO selection
1408
company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.partner_id.id
1410
for partner in self.browse(cr, uid, ids, context=context):
1411
res[partner.id] = False
1412
if partner.supplier and partner.id != company_id and partner.partner_type in ('external', 'esc'):
1413
res[partner.id] = True
1417
def _src_available_for_dpo(self, cr, uid, obj, name, args, context=None):
1419
Returns all partners according to args
1423
if len(arg) > 2 and arg[0] == 'available_for_dpo':
1425
raise osv.except_osv(_('Error'), _('Bad operator'))
1426
elif arg[2] == 'dpo':
1427
company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.partner_id.id
1428
res.append(('id', '!=', company_id))
1429
res.append(('partner_type', 'in', ('external', 'esc')))
1430
res.append(('supplier', '=', True))
1434
def _get_fake(self, cr, uid, ids, fields, arg, context=None):
1435
if isinstance(ids, (int, long)):
1442
def _check_partner_type(self, cr, uid, obj, name, args, context=None):
1445
active_id = context.get('active_id', False)
1446
if isinstance(active_id, (int, long)):
1447
active_id = [active_id]
1452
if arg[0] == 'check_partner':
1453
if arg[1] != '=' or not isinstance(arg[2], (int, long)):
1454
raise osv.except_osv(_('Error'), _('Filter check_partner different than (arg[0], =, id) not implemented.'))
1456
so = self.pool.get('sale.order').browse(cr, uid, arg[2])
1457
sl = self.pool.get('sourcing.line').browse(cr, uid, active_id)[0]
1458
if not so.procurement_request:
1459
newargs.append(('partner_type', 'in', ['external', 'esc']))
1460
elif so.procurement_request and not sl.product_id:
1461
newargs.append(('partner_type','in', ['internal', 'section', 'intermission']))
1463
newargs.append(args)
1466
def _check_partner_type_rfq(self, cr, uid, obj, name, args, context=None):
1471
if arg[0] == 'check_partner_rfq':
1472
if arg[1] != '=' or not isinstance(arg[2], (int, long)):
1473
raise osv.except_osv(_('Error'), _('Filter check_partner_rfq different than (arg[0], =, id) not implemented.'))
1475
tender = self.pool.get('tender').browse(cr, uid, arg[2])
1476
if tender.sale_order_id:
1477
newargs.append(('partner_type', 'in', ['external', 'esc']))
1479
newargs.append(args)
1482
def _check_partner_type_ir(self, cr, uid, obj, name, args, context=None):
1485
active_ids = context.get('active_ids', False)
1486
if isinstance(active_ids, (int, long)):
1487
active_ids = [active_ids]
1492
if arg[0] == 'check_partner_ir':
1494
raise osv.except_osv(_('Error'), _('Filter check_partner_ir different than (arg[0], =, id) not implemented.'))
1497
sol = self.pool.get('sale.order.line').browse(cr, uid, active_ids)[0]
1498
if not context.get('product_id', False) and sol.order_id.procurement_request:
1499
newargs.append(('partner_type','in', ['internal', 'section', 'intermission']))
1501
newargs.append(args)
1504
def _check_partner_type_po(self, cr, uid, obj, name, args, context=None):
1506
Create a domain on the field partner_id on the view id="purchase_move_buttons"
1513
partner_obj = self.pool.get('res.partner')
1515
# Search the local market partner id
1516
data_obj = self.pool.get('ir.model.data')
1517
data_id = data_obj.search(cr, uid, [('module', '=', 'order_types'), ('model', '=', 'res.partner'), ('name', '=', 'res_partner_local_market')] )
1519
local_market = data_obj.read(cr, uid, data_id, ['res_id'])[0]['res_id']
1521
if arg[0] == 'check_partner_po':
1523
or arg[2]['order_type'] not in ['regular', 'donation_exp', 'donation_st', 'loan', 'in_kind', 'purchase_list', 'direct']\
1524
or not isinstance(arg[2]['partner_id'], (int, long)):
1525
raise osv.except_osv(_('Error'), _('Filter check_partner_po different than (arg[0], =, %s) not implemented.') % arg[2])
1526
partner_id = arg[2]['partner_id']
1527
order_type = arg[2]['order_type']
1528
# Added by UF-1660 to filter partners
1529
# do nothing on partner_type for loan
1531
if order_type == 'loan':
1532
p_list = ['internal', 'intermission', 'section', 'external']
1533
elif order_type in ['direct', 'in_kind']:
1534
p_list = ['esc', 'external']
1535
elif order_type in ['donation_st', 'donation_exp']:
1536
p_list = ['internal', 'intermission', 'section']
1537
elif order_type in ['purchase_list']:
1538
p_list = ['external']
1539
# show all supplier for non taken cases
1543
newargs.append(('partner_type', 'in', p_list))
1544
# Useless code because if we enter in direct case, we do not enter in this one
1545
# elif partner_id and partner_id != local_market:
1546
# partner = partner_obj.browse(cr, uid, partner_id)
1547
# if partner.partner_type not in ('external', 'esc') and order_type == 'direct':
1548
# newargs.append(('partner_type', 'in', ['esc', 'external']))
1550
newargs.append(args)
1554
'available_for_dpo': fields.function(_get_available_for_dpo, fnct_search=_src_available_for_dpo,
1555
method=True, type='boolean', string='Available for DPO', store=False),
1556
'check_partner': fields.function(_get_fake, method=True, type='boolean', string='Check Partner Type', fnct_search=_check_partner_type),
1557
'check_partner_rfq': fields.function(_get_fake, method=True, type='boolean', string='Check Partner Type', fnct_search=_check_partner_type_rfq),
1558
'check_partner_ir': fields.function(_get_fake, method=True, type='boolean', string='Check Partner Type On IR', fnct_search=_check_partner_type_ir),
1559
'check_partner_po': fields.function(_get_fake, method=True, type='boolean', string='Check Partner Type On PO', fnct_search=_check_partner_type_po),