128
142
_order = 'name desc'
144
def _check_restriction_line(self, cr, uid, ids, context=None):
146
Check if there is no restrictive products in lines
148
if isinstance(ids, (int, long)):
151
line_obj = self.pool.get('tender.line')
154
for tender in self.browse(cr, uid, ids, context=context):
155
res = res and line_obj._check_restriction_line(cr, uid, [x.id for x in tender.tender_line_ids if x.line_state != 'cancel'], context=context)
159
def default_get(self, cr, uid, fields, context=None):
164
partner_obj = self.pool.get('res.partner')
165
user_obj = self.pool.get('res.users')
167
res = super(tender, self).default_get(cr, uid, fields, context=context)
169
# Get the delivery address
170
company = user_obj.browse(cr, uid, uid, context=context).company_id
171
res['delivery_address'] = partner_obj.address_get(cr, uid, company.partner_id.id, ['delivery'])['delivery']
130
175
def _check_tender_from_fo(self, cr, uid, ids, context=None):
150
195
if not vals.get('name', False):
151
196
vals.update({'name': self.pool.get('ir.sequence').get(cr, uid, 'tender')})
152
198
return super(tender, self).create(cr, uid, vals, context=context)
200
def _check_service(self, cr, uid, ids, vals, context=None):
202
Avoid the saving of a Tender with non service products on Service Tender
204
if isinstance(ids, (int, long)):
206
categ = {'transport': _('Transport'),
207
'service': _('Service')}
210
if context.get('import_in_progress'):
212
for tender in self.browse(cr, uid, ids, context=context):
213
for line in tender.tender_line_ids:
214
if line.line_state == 'cancel':
216
if vals.get('categ', tender.categ) == 'transport' and line.product_id and (line.product_id.type not in ('service', 'service_recep') or not line.product_id.transport_ok):
217
raise osv.except_osv(_('Error'), _('The product [%s]%s is not a \'Transport\' product. You can have only \'Transport\' products on a \'Transport\' tender. Please remove this line.') % (line.product_id.default_code, line.product_id.name))
219
elif vals.get('categ', tender.categ) == 'service' and line.product_id and line.product_id.type not in ('service', 'service_recep'):
220
raise osv.except_osv(_('Error'), _('The product [%s] %s is not a \'Service\' product. You can have only \'Service\' products on a \'Service\' tender. Please remove this line.') % (line.product_id.default_code, line.product_id.name))
225
def write(self, cr, uid, ids, vals, context=None):
227
Check consistency between lines and categ of tender
229
self._check_service(cr, uid, ids, vals, context=context)
230
return super(tender, self).write(cr, uid, ids, vals, context=context)
232
def onchange_categ(self, cr, uid, ids, categ, context=None):
233
""" Check that the categ is compatible with the product
234
@param categ: Changed value of categ.
235
@return: Dictionary of values.
237
if isinstance(ids, (int, long)):
240
if ids and categ in ['service', 'transport']:
241
# Avoid selection of non-service producs on Service Tender
242
category = categ=='service' and 'service_recep' or 'transport'
244
if category == 'transport':
245
transport_cat = 'OR p.transport_ok = False'
246
cr.execute('''SELECT p.default_code AS default_code, t.name AS name
248
LEFT JOIN product_product p ON l.product_id = p.id
249
LEFT JOIN product_template pt ON p.product_tmpl_id = pt.id
250
LEFT JOIN tender t ON l.tender_id = t.id
251
WHERE (pt.type != 'service_recep' %s) AND t.id in (%s) LIMIT 1''' % (transport_cat, ','.join(str(x) for x in ids)))
254
cat_name = categ=='service' and 'Service' or 'Transport'
255
message.update({'title': _('Warning'),
256
'message': _('The product [%s] %s is not a \'%s\' product. You can have only \'%s\' products on a \'%s\' tender. Please remove this line before saving.') % (res[0][0], res[0][1], cat_name, cat_name, cat_name)})
258
return {'warning': message}
154
260
def onchange_warehouse(self, cr, uid, ids, warehouse_id, context=None):
156
262
on_change function for the warehouse
270
391
raise osv.except_osv(_('Warning !'), _("Generated RfQs must be Updated or Cancelled."))
272
393
# integrity check, all lines must have purchase_order_line_id
273
if not all([line.purchase_order_line_id.id for line in tender.tender_line_ids]):
394
if not all([line.purchase_order_line_id.id for line in tender.tender_line_ids if line.line_state != 'cancel']):
274
395
raise osv.except_osv(_('Error !'), _('All tender lines must have been compared!'))
397
if tender.sale_order_id:
398
# Update procurement order
399
for line in tender.tender_line_ids:
400
if line.line_state == 'cancel':
401
proc_id = line.sale_order_line_id and line.sale_order_line_id.procurement_id and line.sale_order_line_id.procurement_id.id
403
wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_cancel', cr)
405
vals = {'product_id': line.product_id.id,
406
'product_uom': line.product_uom.id,
407
'product_uos': line.product_uom.id,
408
'product_qty': line.qty,
409
'price_unit': line.price_unit,
410
'product_uos_qty': line.qty}
411
if line.sale_order_line_id and line.sale_order_line_id.procurement_id:
412
proc_id = line.sale_order_line_id.procurement_id.id
413
proc_obj.write(cr, uid, [proc_id], vals, context=context)
414
else: # Create procurement order to add the lines in a PO
415
create_vals = vals.copy()
416
prep_lt = fields_tools.get_field_from_company(cr, uid, object='sale.order', field='preparation_lead_time', context=context)
417
rts = datetime.strptime(tender.sale_order_id.ready_to_ship_date, db_date_format)
418
rts = rts - relativedelta(days=prep_lt or 0)
419
rts = rts.strftime(db_date_format)
420
create_vals.update({'procure_method': 'make_to_order',
422
'tender_id': tender.id,
423
'tender_line_id': line.id,
425
'price_unit': line.price_unit,
427
'origin': tender.sale_order_id.name,
428
'supplier': line.purchase_order_line_id.order_id.partner_id.id,
429
'name': '[%s] %s' % (line.product_id.default_code, line.product_id.name),
430
'location_id': tender.sale_order_id.warehouse_id.lot_stock_id.id,
433
proc_id = proc_obj.create(cr, uid, create_vals, context=context)
434
wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr)
435
wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_check', cr)
276
437
# update product supplierinfo and pricelist
277
438
self.update_supplier_info(cr, uid, ids, context=context, integrity_test=False,)
278
439
# change tender state
471
637
self.done(cr, uid, [tender.id], context=context)
641
def cancel_tender(self, cr, uid, ids, context=None):
643
Ask the user if he wants to re-source all lines
645
wiz_obj = self.pool.get('tender.cancel.wizard')
650
if isinstance(ids, (int, long)):
653
tender = self.read(cr, uid, ids[0], ['state'], context=context)
654
wiz_id = wiz_obj.create(cr, uid, {'tender_id': tender['id'], 'not_draft': tender['state'] != 'draft'}, context=context)
656
return {'type': 'ir.actions.act_window',
657
'res_model': 'tender.cancel.wizard',
475
664
def wkf_action_cancel(self, cr, uid, ids, context=None):
477
666
cancel all corresponding rfqs
479
671
po_obj = self.pool.get('purchase.order')
672
t_line_obj = self.pool.get('tender.line')
480
673
wf_service = netsvc.LocalService("workflow")
482
675
self.write(cr, uid, ids, {'state': 'cancel'}, context=context)
537
733
_SELECTION_TENDER_STATE = [('draft', 'Draft'),('comparison', 'Comparison'), ('done', 'Closed'),]
539
def on_product_change(self, cr, uid, id, product_id, context=None):
735
def on_product_change(self, cr, uid, id, product_id, uom_id, product_qty, context=None):
541
737
product is changed, we update the UoM
543
742
prod_obj = self.pool.get('product.product')
544
743
result = {'value': {}}
546
result['value']['product_uom'] = prod_obj.browse(cr, uid, product_id, context=context).uom_po_id.id
745
# Test the compatibility of the product with a tender
746
result, test = prod_obj._on_change_restriction_error(cr, uid, product_id, field_name='product_id', values=result, vals={'constraints': ['external', 'esc', 'internal']}, context=context)
750
product = prod_obj.browse(cr, uid, product_id, context=context)
751
result['value']['product_uom'] = product.uom_id.id
752
result['value']['text_error'] = False
753
result['value']['to_correct_ok'] = False
755
res_qty = self.onchange_uom_qty(cr, uid, id, uom_id or result.get('value', {}).get('product_uom',False), product_qty)
756
result['value']['qty'] = res_qty.get('value', {}).get('qty', product_qty)
759
result['value']['product_uom'] = uom_id
763
def onchange_uom_qty(self, cr, uid, ids, uom_id, qty):
765
Check round of qty according to the UoM
770
res = self.pool.get('product.uom')._change_round_up_qty(cr, uid, uom_id, qty, 'qty', result=res)
550
774
def _get_total_price(self, cr, uid, ids, field_name, arg, context=None):
595
819
'func_total_price': fields.function(_get_total_price, method=True, type='float', string="Func. Total Price", digits_compute=dp.get_precision('Purchase Price'), multi='total'),
596
820
'func_currency_id': fields.function(_get_total_price, method=True, type='many2one', relation='res.currency', string='Func. Cur.', multi='total'),
597
821
'purchase_order_id': fields.related('purchase_order_line_id', 'order_id', type='many2one', relation='purchase.order', string="Related RfQ", readonly=True,),
598
'purchase_order_line_number': fields.related('purchase_order_line_id', 'line_number', type="integer", string="Related Line Number", readonly=True,),
822
'purchase_order_line_number': fields.related('purchase_order_line_id', 'line_number', type="char", string="Related Line Number", readonly=True,),
599
823
'state': fields.related('tender_id', 'state', type="selection", selection=_SELECTION_TENDER_STATE, string="State",),
824
'line_state': fields.selection([('draft','Draft'), ('cancel', 'Canceled'), ('done', 'Done')], string='State', readonly=True),
600
825
'comment': fields.char(size=128, string='Comment'),
826
'has_to_be_resourced': fields.boolean(string='Has to be resourced'),
827
'created_by_rfq': fields.boolean(string='Created by RfQ'),
602
829
_defaults = {'qty': lambda *a: 1.0,
603
830
'state': lambda *a: 'draft',
831
'line_state': lambda *a: 'draft',
834
def _check_restriction_line(self, cr, uid, ids, context=None):
836
Check if there is no restrictive products in lines
838
if isinstance(ids, (int, long)):
841
for line in self.browse(cr, uid, ids, context=context):
842
if line.tender_id and line.product_id:
843
if not self.pool.get('product.product')._get_restriction_error(cr, uid, line.product_id.id, vals={'constraints': ['external']}, context=context):
606
848
_sql_constraints = [
607
('product_qty_check', 'CHECK( qty > 0 )', 'Product Quantity must be greater than zero.'),
849
# ('product_qty_check', 'CHECK( qty > 0 )', 'Product Quantity must be greater than zero.'),
853
def copy(self, cr, uid, id, default=None, context=None):
857
if not 'created_by_rf' in default:
858
default['created_by_rfq'] = False
860
return super(tender_line, self).copy(cr, uid, id, default, context=context)
862
def cancel_sourcing(self,cr, uid, ids, context=None):
864
Cancel the line and re-source the FO line
867
sol_obj = self.pool.get('sale.order.line')
868
uom_obj = self.pool.get('product.uom')
869
tender_obj = self.pool.get('tender')
872
wf_service = netsvc.LocalService("workflow")
878
tender_to_update = set()
880
for line in self.browse(cr, uid, ids, context=context):
881
tender_to_update.add(line.tender_id.id)
882
if line.sale_order_line_id:
883
so_to_update.add(line.sale_order_line_id.order_id.id)
884
to_cancel.append(line.id)
885
# Get the ID and the product qty of the FO line to re-source
886
diff_qty = uom_obj._compute_qty(cr, uid, line.product_uom.id, line.qty, line.sale_order_line_id.product_uom.id)
888
if line.has_to_be_resourced:
889
sol_ids.update({line.sale_order_line_id.id: diff_qty})
891
sol_to_update.setdefault(line.sale_order_line_id.id, 0.00)
892
sol_to_update[line.sale_order_line_id.id] += diff_qty
893
elif line.tender_id.state == 'draft':
894
to_remove.append(line.id)
896
to_cancel.append(line.id)
899
self.write(cr, uid, to_cancel, {'line_state': 'cancel'}, context=context)
903
sol_obj.add_resource_line(cr, uid, sol, False, sol_ids[sol], context=context)
905
# Update sale order lines
906
for sol in sol_to_update:
907
sol_obj.update_or_cancel_line(cr, uid, sol, sol_to_update[sol], context=context)
909
# Update the FO state
910
for so in so_to_update:
911
wf_service.trg_write(uid, 'sale.order', so, cr)
913
# UF-733: if all tender lines have been compared (have PO Line id), then set the tender to be ready
914
# for proceeding to other actions (create PO, Done etc)
915
for tender in tender_obj.browse(cr, uid, list(tender_to_update), context=context):
916
if tender.internal_state == 'draft':
918
for line in tender.tender_line_ids:
919
if line.line_state != 'cancel' and not line.purchase_order_line_id:
922
tender_obj.write(cr, uid, [tender.id], {'internal_state': 'updated'})
924
if context.get('fake_unlink'):
929
def fake_unlink(self, cr, uid, ids, context=None):
931
Cancel the line if it is linked to a FO line
933
to_remove = self.cancel_sourcing(cr, uid, ids, context=dict(context, fake_unlink=True))
935
return self.unlink(cr, uid, to_remove, context=context)
937
def ask_unlink(self, cr, uid, ids, context=None):
939
Ask user if he wants to re-source the needs
942
wiz_obj = self.pool.get('tender.line.cancel.wizard')
948
if isinstance(ids, (int, long)):
952
for line in self.browse(cr, uid, ids, context=context):
953
tender_id = line.tender_id.id
954
if line.sale_order_line_id:
955
wiz_id = wiz_obj.create(cr, uid, {'tender_line_id': line.id}, context=context)
957
return {'type': 'ir.actions.act_window',
958
'res_model': 'tender.line.cancel.wizard',
965
self.fake_unlink(cr, uid, ids, context=context)
967
return {'type': 'ir.actions.act_window',
968
'res_model': 'tender',
970
'view_mode': 'form,tree',
657
1023
_inherit = 'procurement.order'
659
def _is_tender(self, cr, uid, ids, field_name, arg, context=None):
1025
def _is_tender_rfq(self, cr, uid, ids, field_name, arg, context=None):
661
tell if the corresponding sale order line is tender sourcing or not
1027
tell if the corresponding sale order line is tender/rfq sourcing or not
667
1030
for proc in self.browse(cr, uid, ids, context=context):
1031
result[proc.id] = {'is_tender': False, 'is_rfq': False}
668
1032
for line in proc.sale_order_line_ids:
669
result[proc.id] = line.po_cft == 'cft'
1033
result[proc.id]['is_tender'] = line.po_cft == 'cft'
1034
result[proc.id]['is_rfq'] = line.po_cft == 'rfq'
673
_columns = {'is_tender': fields.function(_is_tender, method=True, type='boolean', string='Is Tender', readonly=True,),
1038
_columns = {'is_tender': fields.function(_is_tender_rfq, method=True, type='boolean', string='Is Tender', readonly=True, multi='tender_rfq'),
1039
'is_rfq': fields.function(_is_tender_rfq, method=True, type='boolean', string='Is RfQ', readonly=True, multi='tender_rfq'),
674
1040
'sale_order_line_ids': fields.one2many('sale.order.line', 'procurement_id', string="Sale Order Lines"),
675
1041
'tender_id': fields.many2one('tender', string='Tender', readonly=True),
1042
'tender_line_id': fields.many2one('tender.line', string='Tender line', readonly=True),
676
1043
'is_tender_done': fields.boolean(string="Tender Closed"),
1044
'rfq_id': fields.many2one('purchase.order', string='RfQ', readonly=True),
1045
'rfq_line_id': fields.many2one('purchase.order.line', string='RfQ line', readonly=True),
1046
'is_rfq_done': fields.boolean(string="RfQ Closed"),
677
1047
'state': fields.selection([('draft','Draft'),
678
1048
('confirmed','Confirmed'),
679
1049
('exception','Exception'),
682
1052
('ready','Ready'),
683
1053
('done','Closed'),
684
1054
('tender', 'Tender'),
1055
('rfq', 'Request for Quotation'),
685
1056
('waiting','Waiting'),], 'State', required=True,
686
1057
help='When a procurement is created the state is set to \'Draft\'.\n If the procurement is confirmed, the state is set to \'Confirmed\'.\
687
1058
\nAfter confirming the state is set to \'Running\'.\n If any exception arises in the order then the state is set to \'Exception\'.\n Once the exception is removed the state becomes \'Ready\'.\n It is in \'Waiting\'. state when the procurement is waiting for another one to finish.'),
688
1059
'price_unit': fields.float('Unit Price from Tender', digits_compute=dp.get_precision('Purchase Price Computation')),
690
_defaults = {'is_tender_done': False,}
1062
'is_tender_done': False,
1063
'is_rfq_done': False,
1066
def no_address_error(self, cr, uid, ids, context=None):
1068
Put the procurement order in exception state with the good error message
1070
for proc in self.browse(cr, uid, ids, context=context):
1071
if proc.supplier and not proc.supplier.address:
1072
self.write(cr, uid, [proc.id], {
1073
'state': 'exception',
1074
'message': _('The supplier "%s" has no address defined!')%(proc.supplier.name,),
1079
def wkf_action_rfq_create(self, cr, uid, ids, context=None):
1081
creation of rfq from procurement workflow
1083
rfq_obj = self.pool.get('purchase.order')
1084
rfq_line_obj = self.pool.get('purchase.order.line')
1085
partner_obj = self.pool.get('res.partner')
1090
# find the corresponding sale order id for rfq
1091
for proc in self.browse(cr, uid, ids, context=context):
1095
sale_order_line = False
1096
for sol in proc.sale_order_line_ids:
1097
sale_order = sol.order_id
1098
sale_order_line = sol
1102
# UTP-934: If source rfq to different supplier, different rfq must be created, and cannot be using the same rfq
1103
rfq_ids = rfq_obj.search(cr, uid, [('sale_order_id', '=', sale_order.id),('partner_id', '=', proc.supplier.id), ('state', '=', 'draft'), ('rfq_ok', '=', True),], context=context)
1106
# create if not found
1108
supplier = proc.supplier
1109
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
1110
pricelist_id = supplier.property_product_pricelist_purchase.id
1111
address_id = partner_obj.address_get(cr, uid, [supplier.id], ['default'])['default']
1113
self.write(cr, uid, [proc.id], {
1114
'message': _('The supplier "%s" has no address defined!')%(supplier.name,),
1118
context['rfq_ok'] = True
1119
rfq_id = rfq_obj.create(cr, uid, {'sale_order_id': sale_order.id,
1120
'categ': sale_order.categ,
1121
'priority': sale_order.priority,
1122
'fiscal_position': supplier.property_account_position and supplier.property_account_position.id or False,
1123
'rfq_delivery_address': partner_obj.address_get(cr, uid, company.partner_id.id, ['delivery'])['delivery'],
1124
'warehouse_id': sale_order.shop_id.warehouse_id.id,
1125
'location_id': proc.location_id.id,
1126
'partner_id': supplier.id,
1127
'partner_address_id': address_id,
1128
'pricelist_id': pricelist_id,
1130
'from_procurement': True,
1131
'order_type': sale_order.order_type,
1132
'origin': sale_order.name,}, context=context)
1134
# add a line to the RfQ
1135
rfq_line_id = rfq_line_obj.create(cr, uid, {'product_id': proc.product_id.id,
1136
'comment': sale_order_line.comment,
1137
'name': sale_order_line.name,
1139
'product_qty': proc.product_qty,
1140
'origin': sale_order.name,
1142
'sale_order_line_id': sale_order_line.id,
1143
'location_id': proc.location_id.id,
1144
'product_uom': proc.product_uom.id,
1145
'procurement_id': proc.id,
1146
#'date_planned': proc.date_planned, # function at line level
1149
self.write(cr, uid, ids, {'rfq_id': rfq_id, 'rfq_line_id': rfq_line_id}, context=context)
1151
# log message concerning RfQ creation
1152
rfq_obj.log(cr, uid, rfq_id, "The Request for Quotation '%s' has been created and must be completed before purchase order creation."%rfq_obj.browse(cr, uid, rfq_id, context=context).name, context={'rfq_ok': 1})
1153
# state of procurement is Tender
1154
self.write(cr, uid, ids, {'state': 'rfq'}, context=context)
692
1158
def wkf_action_tender_create(self, cr, uid, ids, context=None):
717
1185
'requested_date': proc.date_planned,
718
1186
}, context=context)
719
1187
# add a line to the tender
720
tender_line_obj.create(cr, uid, {'product_id': proc.product_id.id,
721
'comment': sale_order_line.comment,
722
'qty': proc.product_qty,
723
'tender_id': tender_id,
724
'sale_order_line_id': sale_order_line.id,
725
'location_id': proc.location_id.id,
726
'product_uom': proc.product_uom.id,
727
#'date_planned': proc.date_planned, # function at line level
1188
tender_line_id = tender_line_obj.create(cr, uid, {'product_id': proc.product_id.id,
1189
'comment': sale_order_line.comment,
1190
'qty': proc.product_qty,
1191
'tender_id': tender_id,
1192
'sale_order_line_id': sale_order_line.id,
1193
'location_id': proc.location_id.id,
1194
'product_uom': proc.product_uom.id,
1195
#'date_planned': proc.date_planned, # function at line level
730
self.write(cr, uid, ids, {'tender_id': tender_id}, context=context)
1198
self.write(cr, uid, ids, {'tender_id': tender_id, 'tender_line_id': tender_line_id}, context=context)
732
1200
# log message concerning tender creation
733
1201
tender_obj.log(cr, uid, tender_id, "The tender '%s' has been created and must be completed before purchase order creation."%tender_obj.browse(cr, uid, tender_id, context=context).name)
801
1289
if obj.state == 'rfq_updated' and not obj.valid_till:
804
1293
_columns = {'tender_id': fields.many2one('tender', string="Tender", readonly=True),
1294
'rfq_delivery_address': fields.many2one('res.partner.address', string='Delivery address'),
805
1295
'origin_tender_id': fields.many2one('tender', string='Tender', readonly=True),
1296
'from_procurement': fields.boolean(string='RfQ created by a procurement order'),
806
1297
'rfq_ok': fields.boolean(string='Is RfQ ?'),
807
1298
'state': fields.selection(PURCHASE_ORDER_STATE_SELECTION, 'State', readonly=True, help="The state of the purchase order or the quotation request. A quotation is a purchase order in a 'Draft' state. Then the order has to be confirmed by the user, the state switch to 'Confirmed'. Then the supplier must confirm the order to change the state to 'Approved'. When the purchase order is paid and received, the state becomes 'Closed'. If a cancel action occurs in the invoice or in the reception of goods, the state becomes in exception.", select=True),
808
1299
'valid_till': fields.date(string='Valid Till', states={'rfq_updated': [('required', True), ('readonly', True)], 'rfq_sent':[('required',False), ('readonly', False),]}, readonly=True,),
809
1300
# add readonly when state is Done
1301
'sale_order_id': fields.many2one('sale.order', string='Link between RfQ and FO', readonly=True),
1506
def wkf_act_rfq_done(self, cr, uid, ids, context=None):
1508
Set the state to done and update the price unit in the procurement order
1510
wf_service = netsvc.LocalService("workflow")
1511
proc_obj = self.pool.get('procurement.order')
1512
date_tools = self.pool.get('date.tools')
1513
fields_tools = self.pool.get('fields.tools')
1514
db_date_format = date_tools.get_db_date_format(cr, uid, context=context)
1516
if isinstance(ids, (int, long)):
1519
for rfq in self.browse(cr, uid, ids, context=context):
1520
if rfq.from_procurement:
1521
for line in rfq.order_line:
1522
if line.procurement_id:
1523
self.pool.get('procurement.order').write(cr, uid, [line.procurement_id.id], {'price_unit': line.price_unit}, context=context)
1524
elif not rfq.tender_id:
1525
prep_lt = fields_tools.get_field_from_company(cr, uid, object='sale.order', field='preparation_lead_time', context=context)
1526
rts = datetime.strptime(rfq.sale_order_id.ready_to_ship_date, db_date_format)
1527
rts = rts - relativedelta(days=prep_lt or 0)
1528
rts = rts.strftime(db_date_format)
1529
vals = {'product_id': line.product_id.id,
1530
'product_uom': line.product_uom.id,
1531
'product_uos': line.product_uom.id,
1532
'product_qty': line.product_qty,
1533
'product_uos_qty': line.product_qty,
1534
'price_unit': line.price_unit,
1535
'procure_method': 'make_to_order',
1538
'rfq_line_id': line.id,
1541
'tender_line_id': False,
1542
'date_planned': rts,
1543
'origin': rfq.sale_order_id.name,
1544
'supplier': rfq.partner_id.id,
1545
'name': '[%s] %s' % (line.product_id.default_code, line.product_id.name),
1546
'location_id': rfq.sale_order_id.warehouse_id.lot_stock_id.id,
1549
proc_id = proc_obj.create(cr, uid, vals, context=context)
1550
wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr)
1551
wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_check', cr)
1553
return self.write(cr, uid, ids, {'state': 'done'}, context=context)
962
1555
purchase_order()
1031
1637
pricelist_partnerinfo()
1640
class tender_line_cancel_wizard(osv.osv_memory):
1641
_name = 'tender.line.cancel.wizard'
1644
'tender_line_id': fields.many2one('tender.line', string='Tender line', required=True),
1648
def just_cancel(self, cr, uid, ids, context=None):
1653
line_obj = self.pool.get('tender.line')
1654
tender_obj = self.pool.get('tender')
1655
data_obj = self.pool.get('ir.model.data')
1656
tender_wiz_obj = self.pool.get('tender.cancel.wizard')
1662
if isinstance(ids, (int, long)):
1667
for wiz in self.browse(cr, uid, ids, context=context):
1668
tender_ids.add(wiz.tender_line_id.tender_id.id)
1669
line_ids.append(wiz.tender_line_id.id)
1671
if context.get('has_to_be_resourced'):
1672
line_obj.write(cr, uid, line_ids, {'has_to_be_resourced': True}, context=context)
1674
line_obj.fake_unlink(cr, uid, line_ids, context=context)
1676
for tender in tender_obj.browse(cr, uid, list(tender_ids), context=context):
1677
if all(x.line_state in ('cancel', 'done') for x in tender.tender_line_ids):
1678
wiz_id = tender_wiz_obj.create(cr, uid, {'tender_id': tender.id}, context=context)
1679
view_id = data_obj.get_object_reference(cr, uid, 'tender_flow', 'ask_tender_cancel_wizard_form_view')[1]
1680
return {'type': 'ir.actions.act_window',
1681
'res_model': 'tender.cancel.wizard',
1682
'view_type': 'form',
1683
'view_mode': 'form',
1684
'view_id': [view_id],
1689
return {'type': 'ir.actions.act_window_close'}
1691
def cancel_and_resource(self, cr, uid, ids, context=None):
1693
Flag the line to be re-sourced and run cancel method
1699
context['has_to_be_resourced'] = True
1701
return self.just_cancel(cr, uid, ids, context=context)
1703
tender_line_cancel_wizard()
1706
class tender_cancel_wizard(osv.osv_memory):
1707
_name = 'tender.cancel.wizard'
1710
'tender_id': fields.many2one('tender', string='Tender', required=True),
1711
'not_draft': fields.boolean(string='Tender not draft'),
1714
def just_cancel(self, cr, uid, ids, context=None):
1716
Just cancel the wizard and the lines
1719
line_obj = self.pool.get('tender.line')
1725
if isinstance(ids, (int, long)):
1728
wf_service = netsvc.LocalService("workflow")
1732
for wiz in self.browse(cr, uid, ids, context=context):
1733
tender_ids.append(wiz.tender_id.id)
1734
for line in wiz.tender_id.tender_line_ids:
1735
line_ids.append(line.id)
1736
for rfq in wiz.tender_id.rfq_ids:
1737
rfq_ids.append(rfq.id)
1739
if context.get('has_to_be_resourced'):
1740
line_obj.write(cr, uid, line_ids, {'has_to_be_resourced': True}, context=context)
1742
line_obj.fake_unlink(cr, uid, line_ids, context=context)
1745
wf_service.trg_validate(uid, 'purchase.order', rfq, 'purchase_cancel', cr)
1747
for tender in tender_ids:
1748
wf_service.trg_validate(uid, 'tender', tender, 'tender_cancel', cr)
1750
return {'type': 'ir.actions.act_window_close'}
1752
def cancel_and_resource(self, cr, uid, ids, context=None):
1754
Flag the line to be re-sourced and run cancel method
1760
context['has_to_be_resourced'] = True
1762
return self.just_cancel(cr, uid, ids, context=context)
1764
def close_window(self, cr, uid, ids, context=None):
1766
Just close the wizard and reload the tender
1768
return {'type': 'ir.actions.act_window_close'}
1770
tender_cancel_wizard()
1033
1774
class ir_values(osv.osv):
1034
1775
_name = 'ir.values'
1035
1776
_inherit = 'ir.values'