diff --git a/addons/purchase_requisition/models/purchase_requisition.py b/addons/purchase_requisition/models/purchase_requisition.py
index ec8cf2d826e..dffda14ab6e 100644
--- a/addons/purchase_requisition/models/purchase_requisition.py
+++ b/addons/purchase_requisition/models/purchase_requisition.py
@@ -50,9 +50,9 @@ class PurchaseRequisition(models.Model):
order_count = fields.Integer(compute='_compute_orders_number', string='Number of Orders')
vendor_id = fields.Many2one('res.partner', string="Vendor")
type_id = fields.Many2one('purchase.requisition.type', string="Agreement Type", required=True, default=_get_type_id)
- ordering_date = fields.Date(string="Ordering Date")
- date_end = fields.Datetime(string='Agreement Deadline')
- schedule_date = fields.Date(string='Delivery Date', index=True, help="The expected and scheduled delivery date where all the products are received")
+ ordering_date = fields.Date(string="Ordering Date", track_visibility='onchange')
+ date_end = fields.Datetime(string='Agreement Deadline', track_visibility='onchange')
+ schedule_date = fields.Date(string='Delivery Date', index=True, help="The expected and scheduled delivery date where all the products are received", track_visibility='onchange')
user_id = fields.Many2one('res.users', string='Purchase Representative', default= lambda self: self.env.user)
description = fields.Text()
company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env['res.company']._company_default_get('purchase.requisition'))
@@ -104,6 +104,8 @@ class PurchaseRequisition(models.Model):
def action_cancel(self):
# try to set all associated quotations to cancel state
for requisition in self:
+ for requisition_line in requisition.line_ids:
+ requisition_line.supplier_info_ids.unlink()
requisition.purchase_ids.button_cancel()
for po in requisition.purchase_ids:
po.message_post(body=_('Cancelled by the agreement associated to this quotation.'))
@@ -112,7 +114,15 @@ class PurchaseRequisition(models.Model):
@api.multi
def action_in_progress(self):
if not all(obj.line_ids for obj in self):
- raise UserError(_('You cannot confirm call because there is no product line.'))
+ raise UserError(_('You cannot confirm agreement because there is no product line.'))
+ for requisition in self:
+ if requisition.type_id.quantity_copy == 'none' and requisition.vendor_id:
+ for requisition_line in requisition.line_ids:
+ if requisition_line.price_unit <= 0.0:
+ raise UserError(_('You cannot confirm the blanket order without price.'))
+ if requisition_line.product_qty <= 0.0:
+ raise UserError(_('You cannot confirm the blanket order without quantity.'))
+ requisition_line.create_supplier_info()
self.write({'state': 'in_progress'})
@api.multi
@@ -130,6 +140,9 @@ class PurchaseRequisition(models.Model):
"""
if any(purchase_order.state in ['draft', 'sent', 'to approve'] for purchase_order in self.mapped('purchase_ids')):
raise UserError(_('You have to cancel or validate every RfQ before closing the purchase requisition.'))
+ for requisition in self:
+ for requisition_line in requisition.line_ids:
+ requisition_line.supplier_info_ids.unlink()
self.write({'state': 'done'})
def _prepare_tender_values(self, product_id, product_qty, product_uom, location_id, name, origin, values):
@@ -146,6 +159,18 @@ class PurchaseRequisition(models.Model):
})],
}
+ def unlink(self):
+ if any(requisition.state not in ('draft', 'cancel') for requisition in self):
+ raise UserError(_('You can only delete draft requisitions.'))
+ # Draft requisitions could have some requisition lines.
+ self.mapped('requisition_line_ids').unlink()
+ return super(PurchaseRequisition, self).unlink()
+
+class SupplierInfo(models.Model):
+ _inherit = "product.supplierinfo"
+ purchase_requisition_id = fields.Many2one('purchase.requisition', related='purchase_requisition_line_id.requisition_id', string='Blanket order')
+ purchase_requisition_line_id = fields.Many2one('purchase.requisition.line')
+
class PurchaseRequisitionLine(models.Model):
_name = "purchase.requisition.line"
@@ -157,11 +182,50 @@ class PurchaseRequisitionLine(models.Model):
product_qty = fields.Float(string='Quantity', digits=dp.get_precision('Product Unit of Measure'))
price_unit = fields.Float(string='Unit Price', digits=dp.get_precision('Product Price'))
qty_ordered = fields.Float(compute='_compute_ordered_qty', string='Ordered Quantities')
- requisition_id = fields.Many2one('purchase.requisition', string='Purchase Agreement', ondelete='cascade')
+ requisition_id = fields.Many2one('purchase.requisition', required=True, string='Purchase Agreement', ondelete='cascade')
company_id = fields.Many2one('res.company', related='requisition_id.company_id', string='Company', store=True, readonly=True, default= lambda self: self.env['res.company']._company_default_get('purchase.requisition.line'))
account_analytic_id = fields.Many2one('account.analytic.account', string='Analytic Account')
schedule_date = fields.Date(string='Scheduled Date')
move_dest_id = fields.Many2one('stock.move', 'Downstream Move')
+ supplier_info_ids = fields.One2many('product.supplierinfo', 'purchase_requisition_line_id')
+
+ @api.multi
+ def create(self,vals):
+ res = super(PurchaseRequisitionLine, self).create(vals)
+ if res.requisition_id.state not in ['draft', 'cancel', 'done'] and res.requisition_id.is_quantity_copy == 'none':
+ supplier_infos = self.env['product.supplierinfo'].search([
+ ('product_id', '=', vals.get('product_id')),
+ ('name', '=', res.requisition_id.vendor_id.id),
+ ])
+ if not [s.requisition_id for s in supplier_infos]:
+ res.create_supplier_info()
+ return res
+
+ @api.multi
+ def write(self, vals):
+ res = super(PurchaseRequisitionLine, self).write(vals)
+ if 'price_unit' in vals:
+ # If the price is updated, we have to update the related SupplierInfo
+ self.supplier_info_ids.write({'price': vals['price_unit']})
+ return res
+
+ def unlink(self):
+ if self.requisition_id.state not in ['draft', 'cancel', 'done']:
+ self.supplier_info_ids.unlink()
+ return super(PurchaseRequisitionLine, self).unlink()
+
+ def create_supplier_info(self):
+ purchase_requisition = self.requisition_id
+ if purchase_requisition.type_id.quantity_copy == 'none' and purchase_requisition.vendor_id:
+ # create a supplier_info only in case of blanket order
+ self.env['product.supplierinfo'].create({
+ 'name': purchase_requisition.vendor_id.id,
+ 'product_id': self.product_id.id,
+ 'product_tmpl_id': self.product_id.product_tmpl_id.id,
+ 'price': self.price_unit,
+ 'purchase_requisition_id': purchase_requisition.id,
+ 'purchase_requisition_line_id': self.id,
+ })
@api.multi
@api.depends('requisition_id.purchase_ids.state')
diff --git a/addons/purchase_requisition/tests/test_purchase_requisition.py b/addons/purchase_requisition/tests/test_purchase_requisition.py
index 1ddbed67bf8..537d1121e24 100644
--- a/addons/purchase_requisition/tests/test_purchase_requisition.py
+++ b/addons/purchase_requisition/tests/test_purchase_requisition.py
@@ -72,3 +72,50 @@ class TestPurchaseRequisition(common.TransactionCase):
po_dict = purchase_order._convert_to_write({name: purchase_order[name] for name in purchase_order._cache})
self.po_requisition = PurchaseOrder.create(po_dict)
self.assertEqual(len(self.po_requisition.order_line), 1, 'Purchase order should have one line')
+
+ def test_03_purchase_requisition(self):
+ price_product09 = 34
+ price_product13 = 62
+ quantity = 26
+ # Create a pruchase requisition with type blanket order and two product
+ line1 = (0, 0, {'product_id': self.product_09_id, 'product_qty': quantity, 'product_uom_id': self.product_09_uom_id, 'price_unit': price_product09})
+
+ self.product_13_uom_id = self.ref('product.product_uom_unit')
+ line2 = (0, 0, {'product_id': self.product_13_id, 'product_qty': quantity, 'product_uom_id': self.product_13_uom_id, 'price_unit': price_product13})
+
+ requisition_type = self.env['purchase.requisition.type'].create({
+ 'name': 'Blanket test',
+ 'quantity_copy': 'none'
+ })
+ requisition_blanket = self.env['purchase.requisition'].create({
+ 'line_ids': [line1, line2],
+ 'type_id': requisition_type.id,
+ 'vendor_id': self.res_partner_1_id
+ })
+
+ # confirm the requisition
+ requisition_blanket.action_in_progress()
+
+ # Check for both product that the new supplier info(purchase.requisition.vendor_id) is added to the puchase tab
+ # and check the quantity
+ seller_partner1 = self.env['res.partner'].browse(self.res_partner_1_id)
+ supplierinfo09 = self.env['product.supplierinfo'].search([
+ ('name', '=', seller_partner1.id),
+ ('product_id', '=', self.product_09_id)
+ ])
+ self.assertEqual(supplierinfo09.name, seller_partner1, 'The supplierinfo is not the good one')
+ self.assertEqual(supplierinfo09.price, price_product09, 'The supplierinfo is not the good one')
+
+ supplierinfo13 = self.env['product.supplierinfo'].search([
+ ('name', '=', seller_partner1.id),
+ ('product_id', '=', self.product_13_id)
+ ])
+ self.assertEqual(supplierinfo13.name, seller_partner1, 'The supplierinfo is not the good one')
+ self.assertEqual(supplierinfo13.price, price_product13, 'The supplierinfo is not the good one')
+
+ # Put the requisition in done Status
+ requisition_blanket.action_in_progress()
+ requisition_blanket.action_done()
+
+ self.assertFalse(self.env['product.supplierinfo'].search([('id', '=', supplierinfo09.id)]), 'The supplier info should be removed')
+ self.assertFalse(self.env['product.supplierinfo'].search([('id', '=', supplierinfo13.id)]), 'The supplier info should be removed')
diff --git a/addons/purchase_requisition/views/purchase_requisition_views.xml b/addons/purchase_requisition/views/purchase_requisition_views.xml
index 1134250cfcd..e1f17b6dc5b 100644
--- a/addons/purchase_requisition/views/purchase_requisition_views.xml
+++ b/addons/purchase_requisition/views/purchase_requisition_views.xml
@@ -85,6 +85,19 @@
+
+ product.supplierinfo.requisition.view
+ product.supplierinfo
+
+
+
+
+
+
+
+
purchase.order.list.select.inherit
purchase.order
@@ -324,6 +337,17 @@
+
+ product.template.product.form.inherit
+ product.supplierinfo
+
+
+
+
+
+
+
+