Merge pull request #21122 from deepeshgarg007/quotation_blanket_order

feat: Link blanket order and quotation
This commit is contained in:
Marica 2020-04-03 00:20:17 +05:30 committed by GitHub
commit 13712c45e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 94 additions and 56 deletions

View File

@ -14,27 +14,37 @@ frappe.ui.form.on('Blanket Order', {
refresh: function(frm) { refresh: function(frm) {
erpnext.hide_company(); erpnext.hide_company();
if (frm.doc.customer && frm.doc.docstatus === 1) { if (frm.doc.customer && frm.doc.docstatus === 1) {
frm.add_custom_button(__('View Orders'), function() { frm.add_custom_button(__("Sales Order"), function() {
frappe.set_route('List', 'Sales Order', {blanket_order: frm.doc.name});
});
frm.add_custom_button(__("Create Sales Order"), function(){
frappe.model.open_mapped_doc({ frappe.model.open_mapped_doc({
method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_sales_order", method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_order",
frm: frm frm: frm,
args: {
doctype: 'Sales Order'
}
}); });
}).addClass("btn-primary"); }, __('Create'));
frm.add_custom_button(__("Quotation"), function() {
frappe.model.open_mapped_doc({
method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_order",
frm: frm,
args: {
doctype: 'Quotation'
}
});
}, __('Create'));
} }
if (frm.doc.supplier && frm.doc.docstatus === 1) { if (frm.doc.supplier && frm.doc.docstatus === 1) {
frm.add_custom_button(__('View Orders'), function() { frm.add_custom_button(__("Purchase Order"), function(){
frappe.set_route('List', 'Purchase Order', {blanket_order: frm.doc.name});
});
frm.add_custom_button(__("Create Purchase Order"), function(){
frappe.model.open_mapped_doc({ frappe.model.open_mapped_doc({
method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_purchase_order", method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_order",
frm: frm frm: frm,
args: {
doctype: 'Purchase Order'
}
}); });
}).addClass("btn-primary"); }, __('Create'));
} }
}, },

View File

@ -14,11 +14,19 @@ from erpnext.stock.doctype.item.item import get_item_defaults
class BlanketOrder(Document): class BlanketOrder(Document):
def validate(self): def validate(self):
self.validate_dates() self.validate_dates()
self.validate_duplicate_items()
def validate_dates(self): def validate_dates(self):
if getdate(self.from_date) > getdate(self.to_date): if getdate(self.from_date) > getdate(self.to_date):
frappe.throw(_("From date cannot be greater than To date")) frappe.throw(_("From date cannot be greater than To date"))
def validate_duplicate_items(self):
item_list = []
for item in self.items:
if item.item_code in item_list:
frappe.throw(_("Note: Item {0} added multiple times").format(frappe.bold(item.item_code)))
item_list.append(item.item_code)
def update_ordered_qty(self): def update_ordered_qty(self):
ref_doctype = "Sales Order" if self.blanket_order_type == "Selling" else "Purchase Order" ref_doctype = "Sales Order" if self.blanket_order_type == "Selling" else "Purchase Order"
item_ordered_qty = frappe._dict(frappe.db.sql(""" item_ordered_qty = frappe._dict(frappe.db.sql("""
@ -35,7 +43,14 @@ class BlanketOrder(Document):
d.db_set("ordered_qty", item_ordered_qty.get(d.item_code, 0)) d.db_set("ordered_qty", item_ordered_qty.get(d.item_code, 0))
@frappe.whitelist() @frappe.whitelist()
def make_sales_order(source_name): def make_order(source_name):
doctype = frappe.flags.args.doctype
def update_doc(source_doc, target_doc, source_parent):
if doctype == 'Quotation':
target_doc.quotation_to = 'Customer'
target_doc.party_name = source_doc.customer
def update_item(source, target, source_parent): def update_item(source, target, source_parent):
target_qty = source.get("qty") - source.get("ordered_qty") target_qty = source.get("qty") - source.get("ordered_qty")
target.qty = target_qty if not flt(target_qty) < 0 else 0 target.qty = target_qty if not flt(target_qty) < 0 else 0
@ -49,39 +64,11 @@ def make_sales_order(source_name):
target_doc = get_mapped_doc("Blanket Order", source_name, { target_doc = get_mapped_doc("Blanket Order", source_name, {
"Blanket Order": { "Blanket Order": {
"doctype": "Sales Order" "doctype": doctype,
"postprocess": update_doc
}, },
"Blanket Order Item": { "Blanket Order Item": {
"doctype": "Sales Order Item", "doctype": doctype + " Item",
"field_map": {
"rate": "blanket_order_rate",
"parent": "blanket_order"
},
"postprocess": update_item
}
})
return target_doc
@frappe.whitelist()
def make_purchase_order(source_name):
def update_item(source, target, source_parent):
target_qty = source.get("qty") - source.get("ordered_qty")
target.qty = target_qty if not flt(target_qty) < 0 else 0
item = get_item_defaults(target.item_code, source_parent.company)
if item:
target.item_name = item.get("item_name")
target.description = item.get("description")
target.uom = item.get("stock_uom")
target.warehouse = item.get("default_warehouse")
target.against_blanket_order = 1
target.blanket_order = source_name
target_doc = get_mapped_doc("Blanket Order", source_name, {
"Blanket Order": {
"doctype": "Purchase Order"
},
"Blanket Order Item": {
"doctype": "Purchase Order Item",
"field_map": { "field_map": {
"rate": "blanket_order_rate", "rate": "blanket_order_rate",
"parent": "blanket_order" "parent": "blanket_order"

View File

@ -6,7 +6,7 @@ def get_data():
'fieldname': 'blanket_order', 'fieldname': 'blanket_order',
'transactions': [ 'transactions': [
{ {
'items': ['Purchase Order', 'Sales Order'] 'items': ['Purchase Order', 'Sales Order', 'Quotation']
} }
] ]
} }

View File

@ -7,13 +7,17 @@ import frappe
import unittest import unittest
from frappe.utils import add_months, today from frappe.utils import add_months, today
from erpnext import get_company_currency from erpnext import get_company_currency
from .blanket_order import make_sales_order, make_purchase_order from .blanket_order import make_order
class TestBlanketOrder(unittest.TestCase): class TestBlanketOrder(unittest.TestCase):
def setUp(self):
frappe.flags.args = frappe._dict()
def test_sales_order_creation(self): def test_sales_order_creation(self):
bo = make_blanket_order(blanket_order_type="Selling") bo = make_blanket_order(blanket_order_type="Selling")
so = make_sales_order(bo.name) frappe.flags.args.doctype = 'Sales Order'
so = make_order(bo.name)
so.currency = get_company_currency(so.company) so.currency = get_company_currency(so.company)
so.delivery_date = today() so.delivery_date = today()
so.items[0].qty = 10 so.items[0].qty = 10
@ -29,7 +33,8 @@ class TestBlanketOrder(unittest.TestCase):
self.assertEqual(so.items[0].qty, bo.items[0].ordered_qty) self.assertEqual(so.items[0].qty, bo.items[0].ordered_qty)
# test the quantity # test the quantity
so1 = make_sales_order(bo.name) frappe.flags.args.doctype = 'Sales Order'
so1 = make_order(bo.name)
so1.currency = get_company_currency(so1.company) so1.currency = get_company_currency(so1.company)
self.assertEqual(so1.items[0].qty, (bo.items[0].qty-bo.items[0].ordered_qty)) self.assertEqual(so1.items[0].qty, (bo.items[0].qty-bo.items[0].ordered_qty))
@ -37,7 +42,8 @@ class TestBlanketOrder(unittest.TestCase):
def test_purchase_order_creation(self): def test_purchase_order_creation(self):
bo = make_blanket_order(blanket_order_type="Purchasing") bo = make_blanket_order(blanket_order_type="Purchasing")
po = make_purchase_order(bo.name) frappe.flags.args.doctype = 'Purchase Order'
po = make_order(bo.name)
po.currency = get_company_currency(po.company) po.currency = get_company_currency(po.company)
po.schedule_date = today() po.schedule_date = today()
po.items[0].qty = 10 po.items[0].qty = 10
@ -53,7 +59,8 @@ class TestBlanketOrder(unittest.TestCase):
self.assertEqual(po.items[0].qty, bo.items[0].ordered_qty) self.assertEqual(po.items[0].qty, bo.items[0].ordered_qty)
# test the quantity # test the quantity
po1 = make_sales_order(bo.name) frappe.flags.args.doctype = 'Purchase Order'
po1 = make_order(bo.name)
po1.currency = get_company_currency(po1.company) po1.currency = get_company_currency(po1.company)
self.assertEqual(po1.items[0].qty, (bo.items[0].qty-bo.items[0].ordered_qty)) self.assertEqual(po1.items[0].qty, (bo.items[0].qty-bo.items[0].ordered_qty))

View File

@ -6,7 +6,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
apply_pricing_rule_on_item: function(item){ apply_pricing_rule_on_item: function(item){
let effective_item_rate = item.price_list_rate; let effective_item_rate = item.price_list_rate;
if (item.parenttype === "Sales Order" && item.blanket_order_rate) { if (in_list(["Sales Order", "Quotation"], item.parenttype) && item.blanket_order_rate) {
effective_item_rate = item.blanket_order_rate; effective_item_rate = item.blanket_order_rate;
} }
if(item.margin_type == "Percentage"){ if(item.margin_type == "Percentage"){

View File

@ -155,6 +155,11 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False):
def update_item(obj, target, source_parent): def update_item(obj, target, source_parent):
target.stock_qty = flt(obj.qty) * flt(obj.conversion_factor) target.stock_qty = flt(obj.qty) * flt(obj.conversion_factor)
if obj.against_blanket_order:
target.against_blanket_order = obj.against_blanket_order
target.blanket_order = obj.blanket_order
target.blanket_order_rate = obj.blanket_order_rate
doclist = get_mapped_doc("Quotation", source_name, { doclist = get_mapped_doc("Quotation", source_name, {
"Quotation": { "Quotation": {
"doctype": "Sales Order", "doctype": "Sales Order",

View File

@ -55,6 +55,9 @@
"weight_uom", "weight_uom",
"reference", "reference",
"warehouse", "warehouse",
"against_blanket_order",
"blanket_order",
"blanket_order_rate",
"column_break_30", "column_break_30",
"prevdoc_doctype", "prevdoc_doctype",
"prevdoc_docname", "prevdoc_docname",
@ -573,12 +576,38 @@
"fieldname": "image_section", "fieldname": "image_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Image" "label": "Image"
},
{
"depends_on": "eval:doc.against_blanket_order",
"fieldname": "blanket_order",
"fieldtype": "Link",
"label": "Blanket Order",
"no_copy": 1,
"options": "Blanket Order",
"print_hide": 1
},
{
"depends_on": "eval:doc.against_blanket_order",
"fieldname": "blanket_order_rate",
"fieldtype": "Currency",
"label": "Blanket Order Rate",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
},
{
"default": "0",
"fieldname": "against_blanket_order",
"fieldtype": "Check",
"label": "Against Blanket Order",
"no_copy": 1,
"print_hide": 1
} }
], ],
"idx": 1, "idx": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2020-03-05 14:18:58.783751", "modified": "2020-03-30 18:40:28.782720",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Selling", "module": "Selling",
"name": "Quotation Item", "name": "Quotation Item",