[enhancement] request for quotation
This commit is contained in:
parent
6d1b5d618a
commit
a1064a6149
@ -16,7 +16,7 @@ class DuplicatePartyAccountError(frappe.ValidationError): pass
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_party_details(party=None, account=None, party_type="Customer", company=None,
|
||||
posting_date=None, price_list=None, currency=None, doctype=None):
|
||||
posting_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False):
|
||||
|
||||
if not party:
|
||||
return {}
|
||||
@ -25,7 +25,7 @@ def get_party_details(party=None, account=None, party_type="Customer", company=N
|
||||
frappe.throw(_("{0}: {1} does not exists").format(party_type, party))
|
||||
|
||||
return _get_party_details(party, account, party_type,
|
||||
company, posting_date, price_list, currency, doctype)
|
||||
company, posting_date, price_list, currency, doctype, ignore_permissions)
|
||||
|
||||
def _get_party_details(party=None, account=None, party_type="Customer", company=None,
|
||||
posting_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False):
|
||||
|
@ -6,26 +6,30 @@
|
||||
|
||||
frappe.require("assets/erpnext/js/utils.js");
|
||||
|
||||
erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.extend({
|
||||
refresh: function() {
|
||||
this._super();
|
||||
|
||||
if (this.frm.doc.docstatus === 1) {
|
||||
cur_frm.add_custom_button(__("Supplier Quotation"), this.make_suppplier_quotation,
|
||||
__("Make"));
|
||||
cur_frm.page.set_inner_btn_group_as_primary(__("Make"));
|
||||
frappe.ui.form.on("Request for Quotation",{
|
||||
setup: function(frm){
|
||||
frm.fields_dict["suppliers"].grid.get_field("contact_person").get_query = function(doc, cdt, cdn){
|
||||
var d =locals[cdt][cdn];
|
||||
return {
|
||||
filters: {'supplier': d.supplier}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
calculate_taxes_and_totals: function() {
|
||||
return;
|
||||
onload: function(frm){
|
||||
frm.add_fetch('standard_reply', 'response', 'response');
|
||||
},
|
||||
|
||||
tc_name: function() {
|
||||
this.get_terms();
|
||||
refresh: function(frm, cdt, cdn){
|
||||
if (frm.doc.docstatus === 1) {
|
||||
frm.add_custom_button(__("Supplier Quotation"), function(){ frm.trigger("make_suppplier_quotation") },
|
||||
__("Make"));
|
||||
frm.page.set_inner_btn_group_as_primary(__("Make"));
|
||||
}
|
||||
},
|
||||
|
||||
make_suppplier_quotation: function() {
|
||||
make_suppplier_quotation: function(frm){
|
||||
var doc = frm.doc;
|
||||
var dialog = new frappe.ui.Dialog({
|
||||
title: __("For Supplier"),
|
||||
fields: [
|
||||
@ -33,7 +37,7 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e
|
||||
"get_query": function () {
|
||||
return {
|
||||
query:"erpnext.buying.doctype.request_for_quotation.request_for_quotation.get_supplier",
|
||||
filters: {'parent': cur_frm.doc.name}
|
||||
filters: {'parent': doc.name}
|
||||
}
|
||||
}, "reqd": 1 },
|
||||
{"fieldtype": "Button", "label": __("Make Supplier Quotation"), "fieldname": "make_supplier_quotation", "cssClass": "btn-primary"},
|
||||
@ -48,7 +52,7 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e
|
||||
type: "GET",
|
||||
method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.make_supplier_quotation",
|
||||
args: {
|
||||
"source_name": cur_frm.doc.name,
|
||||
"source_name": doc.name,
|
||||
"for_supplier": args.supplier
|
||||
},
|
||||
freeze: true,
|
||||
@ -62,8 +66,22 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e
|
||||
});
|
||||
dialog.show()
|
||||
}
|
||||
})
|
||||
|
||||
erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.extend({
|
||||
refresh: function() {
|
||||
this._super();
|
||||
},
|
||||
|
||||
calculate_taxes_and_totals: function() {
|
||||
return;
|
||||
},
|
||||
|
||||
tc_name: function() {
|
||||
this.get_terms();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// for backward compatibility: combine new and previous states
|
||||
$.extend(cur_frm.cscript, new erpnext.buying.RequestforQuotationController({frm: cur_frm}));
|
||||
|
@ -9,32 +9,6 @@
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "section_break_1",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@ -150,14 +124,14 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "section_break_2",
|
||||
"fieldname": "suppliers_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Supplier Detail",
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@ -188,7 +162,7 @@
|
||||
"options": "RFQ Supplier",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@ -208,7 +182,7 @@
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Items",
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldtype": "Section Break",
|
||||
@ -256,7 +230,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "section_break_3",
|
||||
"fieldname": "supplier_response_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@ -281,16 +255,17 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "message_for_supplier",
|
||||
"fieldtype": "Small Text",
|
||||
"fieldname": "standard_reply",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Message for Supplier",
|
||||
"label": "Standard Reply",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Standard Reply",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -306,22 +281,23 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break2",
|
||||
"fieldtype": "Column Break",
|
||||
"fieldname": "response",
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Message for Supplier",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -633,7 +609,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-03-02 18:50:02.603258",
|
||||
"modified": "2016-03-25 01:14:01.194848",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Request for Quotation",
|
||||
|
@ -3,28 +3,107 @@
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import frappe, json
|
||||
from frappe import _
|
||||
from frappe.utils import get_url, cint
|
||||
from frappe.utils.user import get_user_fullname
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from erpnext.stock.doctype.material_request.material_request import set_missing_values
|
||||
from frappe.model.document import Document
|
||||
from erpnext.controllers.buying_controller import BuyingController
|
||||
|
||||
class RequestforQuotation(Document):
|
||||
STANDARD_USERS = ("Guest", "Administrator")
|
||||
|
||||
class RequestforQuotation(BuyingController):
|
||||
def validate(self):
|
||||
self.validate_duplicate_supplier()
|
||||
self.validate_common()
|
||||
|
||||
def validate_duplicate_supplier(self):
|
||||
supplier_list = [d.supplier for d in self.suppliers]
|
||||
if len(supplier_list) != len(set(supplier_list)):
|
||||
frappe.throw(_("Same supplier has been entered multiple times"))
|
||||
|
||||
def validate_common(self):
|
||||
pc = frappe.get_doc('Purchase Common')
|
||||
pc.validate_for_items(self)
|
||||
|
||||
def on_submit(self):
|
||||
frappe.db.set(self, 'status', 'Submitted')
|
||||
self.send_to_supplier()
|
||||
|
||||
def on_cancel(self):
|
||||
frappe.db.set(self, 'status', 'Cancelled')
|
||||
|
||||
def send_to_supplier(self):
|
||||
link = get_url("/rfq/" + self.name)
|
||||
for supplier_data in self.suppliers:
|
||||
if supplier_data.email_id and cint(supplier_data.sent_email_to_supplier)==1:
|
||||
update_password_link = self.create_supplier_user(supplier_data, link)
|
||||
self.supplier_rfq_mail(supplier_data, update_password_link, link)
|
||||
|
||||
def create_supplier_user(self, supplier_data, link):
|
||||
from frappe.utils import random_string, get_url
|
||||
|
||||
update_password_link = ''
|
||||
if not supplier_data.user_id:
|
||||
user = self.create_user(supplier_data)
|
||||
key = random_string(32)
|
||||
user.reset_password_key = key
|
||||
user.redirect_url = link
|
||||
user.save(ignore_permissions=True)
|
||||
|
||||
update_password_link = get_url("/update-password?key=" + key)
|
||||
frappe.get_doc('Contact', supplier_data.contact_person).save()
|
||||
|
||||
return update_password_link
|
||||
|
||||
def create_user(self, supplier_data):
|
||||
user = frappe.get_doc({
|
||||
'doctype': 'User',
|
||||
'send_welcome_email': 0,
|
||||
'email': supplier_data.email_id,
|
||||
'first_name': supplier_data.supplier_name,
|
||||
'user_type': 'Website User'
|
||||
})
|
||||
|
||||
return user
|
||||
|
||||
def supplier_rfq_mail(self, data, update_password_link, rfq_link):
|
||||
full_name = get_user_fullname(frappe.session['user'])
|
||||
if full_name == "Guest":
|
||||
full_name = "Administrator"
|
||||
|
||||
args = {
|
||||
'update_password_link': update_password_link,
|
||||
'message': frappe.render_template(self.response, data.as_dict()),
|
||||
'rfq_link': rfq_link,
|
||||
'user_fullname': full_name
|
||||
}
|
||||
|
||||
subject = _("Request for Quotation")
|
||||
template = "templates/emails/request_for_quotation.html"
|
||||
sender = frappe.session.user not in STANDARD_USERS and frappe.session.user or None
|
||||
|
||||
frappe.sendmail(recipients=data.email_id, sender=sender, subject=subject,
|
||||
message=frappe.get_template(template).render(args),
|
||||
attachments = [frappe.attach_print('Request for Quotation', self.name)],as_bulk=True)
|
||||
|
||||
frappe.msgprint(_("Email sent to supplier {0}").format(data.supplier))
|
||||
|
||||
def get_list_context(context=None):
|
||||
from erpnext.controllers.website_list_for_contact import get_list_context
|
||||
list_context = get_list_context(context)
|
||||
return list_context
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_supplier(doctype, txt, searchfield, start, page_len, filters):
|
||||
query = """ Select supplier from `tabRFQ Supplier` where parent = '{parent}' and supplier like %s
|
||||
limit {start}, {page_len} """
|
||||
query = """Select supplier from `tabRFQ Supplier` where parent = %(parent)s and supplier like %(txt)s
|
||||
limit %(start)s, %(page_len)s """
|
||||
|
||||
return frappe.db.sql(query.format(parent=filters.get('parent'), start=start, page_len=page_len), '%{0}%'.format(txt))
|
||||
return frappe.db.sql(query, {'parent': filters.get('parent'),
|
||||
'start': start, 'page_len': page_len, 'txt': "%%%s%%" % frappe.db.escape(txt)})
|
||||
|
||||
# This method is used to make supplier quotation from material request form.
|
||||
@frappe.whitelist()
|
||||
def make_supplier_quotation(source_name, for_supplier, target_doc=None):
|
||||
def postprocess(source, target_doc):
|
||||
@ -49,3 +128,50 @@ def make_supplier_quotation(source_name, for_supplier, target_doc=None):
|
||||
}, target_doc, postprocess)
|
||||
|
||||
return doclist
|
||||
|
||||
# This method is used to make supplier quotation from supplier's portal.
|
||||
@frappe.whitelist()
|
||||
def create_supplier_quotation(doc):
|
||||
if isinstance(doc, basestring):
|
||||
doc = json.loads(doc)
|
||||
|
||||
supplier = frappe.get_doc('Supplier', doc.get('supplier'))
|
||||
|
||||
try:
|
||||
sq_doc = frappe.get_doc({
|
||||
"doctype": "Supplier Quotation",
|
||||
"supplier": supplier.name,
|
||||
"terms": doc.get("terms"),
|
||||
"company": doc.get("company"),
|
||||
"currency": supplier.default_currency,
|
||||
"buying_price_list": supplier.default_price_list or frappe.db.get_value('Buying Settings', None, 'buying_price_list')
|
||||
})
|
||||
add_items(sq_doc, supplier, doc.get('items'))
|
||||
sq_doc.flags.ignore_permissions = True
|
||||
sq_doc.run_method("set_missing_values")
|
||||
sq_doc.save()
|
||||
frappe.msgprint(_("Supplier Quotation {0} created").format(sq_doc.name))
|
||||
return sq_doc.name
|
||||
except Exception:
|
||||
return
|
||||
|
||||
def add_items(sq_doc, supplier, items):
|
||||
for data in items:
|
||||
if data.get("qty") > 0:
|
||||
if isinstance(data, dict):
|
||||
data = frappe._dict(data)
|
||||
|
||||
create_rfq_items(sq_doc, supplier, data)
|
||||
|
||||
def create_rfq_items(sq_doc, supplier, data):
|
||||
sq_doc.append('items', {
|
||||
"item_code": data.item_code,
|
||||
"item_name": data.item_name,
|
||||
"description": data.description,
|
||||
"qty": data.qty,
|
||||
"rate": data.rate,
|
||||
"supplier_part_no": frappe.db.get_value("Item Supplier", {'parent': data.item_code, 'supplier': supplier}, "supplier_part_no"),
|
||||
"warehouse": data.warehouse or '',
|
||||
"request_for_quotation_item": data.name,
|
||||
"request_for_quotation": data.parent
|
||||
})
|
||||
|
@ -12,33 +12,48 @@ class TestRequestforQuotation(unittest.TestCase):
|
||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
|
||||
rfq = make_request_for_quotation()
|
||||
|
||||
sq = make_supplier_quotation(rfq.name)
|
||||
sq.supplier = rfq.get('supplier_detail')[0].supplier
|
||||
sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier)
|
||||
sq.submit()
|
||||
|
||||
sq1 = make_supplier_quotation(rfq.name)
|
||||
sq1.supplier = rfq.get('supplier_detail')[1].supplier
|
||||
sq1 = make_supplier_quotation(rfq.name, rfq.get('suppliers')[1].supplier)
|
||||
sq1.submit()
|
||||
|
||||
self.assertEquals(sq.supplier, rfq.get('supplier_detail')[0].supplier)
|
||||
self.assertEquals(sq.supplier, rfq.get('suppliers')[0].supplier)
|
||||
self.assertEquals(sq.get('items')[0].request_for_quotation, rfq.name)
|
||||
self.assertEquals(sq.get('items')[0].item_code, "_Test Item")
|
||||
self.assertEquals(sq.get('items')[0].qty, 5)
|
||||
|
||||
self.assertEquals(sq1.supplier, rfq.get('supplier_detail')[1].supplier)
|
||||
self.assertEquals(sq1.supplier, rfq.get('suppliers')[1].supplier)
|
||||
self.assertEquals(sq1.get('items')[0].request_for_quotation, rfq.name)
|
||||
self.assertEquals(sq1.get('items')[0].item_code, "_Test Item")
|
||||
self.assertEquals(sq1.get('items')[0].qty, 5)
|
||||
|
||||
def test_make_supplier_quotation_from_portal(self):
|
||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation
|
||||
rfq = make_request_for_quotation()
|
||||
rfq.get('items')[0].rate = 100
|
||||
rfq.supplier = rfq.suppliers[0].supplier
|
||||
supplier_quotation_name = create_supplier_quotation(rfq)
|
||||
|
||||
supplier_quotation_doc = frappe.get_doc('Supplier Quotation', supplier_quotation_name)
|
||||
|
||||
self.assertEquals(supplier_quotation_doc.supplier, rfq.get('suppliers')[0].supplier)
|
||||
self.assertEquals(supplier_quotation_doc.get('items')[0].request_for_quotation, rfq.name)
|
||||
self.assertEquals(supplier_quotation_doc.get('items')[0].item_code, "_Test Item")
|
||||
self.assertEquals(supplier_quotation_doc.get('items')[0].qty, 5)
|
||||
self.assertEquals(supplier_quotation_doc.get('items')[0].amount, 500)
|
||||
|
||||
|
||||
def make_request_for_quotation():
|
||||
supplier_data = get_supplier_data()
|
||||
rfq = frappe.new_doc('Request for Quotation')
|
||||
rfq.transaction_date = nowdate()
|
||||
rfq.status = 'Draft'
|
||||
rfq.company = '_Test Company'
|
||||
rfq.response = 'Test Data'
|
||||
|
||||
for data in supplier_data:
|
||||
rfq.append('supplier_detail', data)
|
||||
rfq.append('suppliers', data)
|
||||
|
||||
rfq.append("items", {
|
||||
"item_code": "_Test Item",
|
||||
|
@ -28,7 +28,7 @@
|
||||
"options": "Item",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@ -37,32 +37,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "",
|
||||
"fieldname": "supplier_part_no",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Supplier Part Number",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@ -105,7 +79,7 @@
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@ -474,7 +448,7 @@
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@ -624,7 +598,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-03-03 13:42:11.020082",
|
||||
"modified": "2016-03-25 01:14:38.490488",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Request for Quotation Item",
|
||||
|
@ -29,6 +29,83 @@
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "contact_person",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Contact Person",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Contact",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": "1",
|
||||
"description": "Send Request for Quotation to Supplier",
|
||||
"fieldname": "sent_email_to_supplier",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Sent Email to Supplier",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
@ -45,7 +122,7 @@
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Name",
|
||||
"label": "Supplier Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "supplier.supplier_name",
|
||||
@ -59,6 +136,58 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "email_id",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Email Id",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "contact_person.email_id",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "user_id",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "User Id",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "contact_person.user",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
@ -70,7 +199,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-03-03 12:52:45.937140",
|
||||
"modified": "2016-03-25 13:18:11.017660",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "RFQ Supplier",
|
||||
|
@ -1885,6 +1885,26 @@
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 1,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "All",
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
}
|
||||
],
|
||||
"read_only": 0,
|
||||
|
@ -879,6 +879,32 @@
|
||||
"unique": 0,
|
||||
"width": "120px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "request_for_quotation",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Request for Quotation",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Request for Quotation",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@ -928,32 +954,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "request_for_quotation",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Request for Quotation",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Request for Quotation",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@ -970,9 +970,9 @@
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@ -1097,7 +1097,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-03-18 05:15:03.936587",
|
||||
"modified": "2016-03-25 17:01:59.632826",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Quotation Item",
|
||||
|
@ -20,6 +20,7 @@ class BuyingController(StockController):
|
||||
}
|
||||
|
||||
def get_feed(self):
|
||||
if self.get("supplier_name"):
|
||||
return _("From {0} | {1} {2}").format(self.supplier_name, self.currency,
|
||||
self.grand_total)
|
||||
|
||||
@ -40,7 +41,7 @@ class BuyingController(StockController):
|
||||
|
||||
# set contact and address details for supplier, if they are not mentioned
|
||||
if getattr(self, "supplier", None):
|
||||
self.update_if_missing(get_party_details(self.supplier, party_type="Supplier"))
|
||||
self.update_if_missing(get_party_details(self.supplier, party_type="Supplier", ignore_permissions=self.flags.ignore_permissions))
|
||||
|
||||
self.set_missing_item_details()
|
||||
|
||||
|
@ -28,15 +28,14 @@ def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_p
|
||||
filters.append((doctype, "docstatus", "=", 1))
|
||||
|
||||
if user != "Guest" and is_website_user():
|
||||
parties_doctype = 'RFQ Supplier' if doctype == 'Request for Quotation' else doctype
|
||||
# find party for this contact
|
||||
customers, suppliers = get_customers_suppliers(doctype, user)
|
||||
customers, suppliers = get_customers_suppliers(parties_doctype, user)
|
||||
key, parties = get_party_details(customers, suppliers)
|
||||
|
||||
if customers:
|
||||
key, parties = "customer", customers
|
||||
elif suppliers:
|
||||
key, parties = "supplier", suppliers
|
||||
else:
|
||||
key, parties = "customer", []
|
||||
if doctype == 'Request for Quotation':
|
||||
if key == 'customer': frappe.throw(_("Not Permitted"), frappe.PermissionError)
|
||||
return rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length)
|
||||
|
||||
filters.append((doctype, key, "in", parties))
|
||||
|
||||
@ -52,6 +51,23 @@ def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_p
|
||||
return post_process(doctype, get_list(doctype, txt, filters, limit_start, limit_page_length,
|
||||
fields="name", order_by = "modified desc"))
|
||||
|
||||
def get_party_details(customers, suppliers):
|
||||
if customers:
|
||||
key, parties = "customer", customers
|
||||
elif suppliers:
|
||||
key, parties = "supplier", suppliers
|
||||
else:
|
||||
key, parties = "customer", []
|
||||
|
||||
return key, parties
|
||||
|
||||
def rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length):
|
||||
data = frappe.db.sql("""select distinct parent as name, supplier from `tab{doctype}`
|
||||
where supplier = '{supplier}' and docstatus=1 order by modified desc limit {start}, {len}""".
|
||||
format(doctype=parties_doctype, supplier=parties[0], start=limit_start, len = limit_page_length), as_dict=1)
|
||||
|
||||
return post_process(doctype, data)
|
||||
|
||||
def post_process(doctype, data):
|
||||
result = []
|
||||
for d in data:
|
||||
|
@ -71,6 +71,13 @@ website_route_rules = [
|
||||
"parents": [{"title": _("Shipments"), "name": "shipments"}]
|
||||
}
|
||||
},
|
||||
{"from_route": "/rfq", "to_route": "Request for Quotation"},
|
||||
{"from_route": "/rfq/<path:name>", "to_route": "rfq",
|
||||
"defaults": {
|
||||
"doctype": "Request for Quotation",
|
||||
"parents": [{"title": _("Request for Quotation"), "name": "rfq"}]
|
||||
}
|
||||
},
|
||||
{"from_route": "/jobs", "to_route": "Job Opening"},
|
||||
]
|
||||
|
||||
|
@ -16,6 +16,8 @@ def show_cart_count():
|
||||
return False
|
||||
|
||||
def set_cart_count(login_manager):
|
||||
role, parties = check_customer_or_supplier()
|
||||
if role == 'Supplier': return
|
||||
if show_cart_count():
|
||||
from erpnext.shopping_cart.cart import set_cart_count
|
||||
set_cart_count()
|
||||
@ -29,6 +31,19 @@ def update_website_context(context):
|
||||
context["shopping_cart_enabled"] = cart_enabled
|
||||
|
||||
def update_my_account_context(context):
|
||||
check_user_role, parties = check_customer_or_supplier()
|
||||
|
||||
if check_user_role == 'Supplier':
|
||||
get_supplier_context(context)
|
||||
else:
|
||||
get_customer_context(context)
|
||||
|
||||
def get_supplier_context(context):
|
||||
context["my_account_list"].extend([
|
||||
{"label": _("Request for Quotations"), "url": "rfq"},
|
||||
])
|
||||
|
||||
def get_customer_context(context):
|
||||
context["my_account_list"].extend([
|
||||
{"label": _("Projects"), "url": "project"},
|
||||
{"label": _("Orders"), "url": "orders"},
|
||||
@ -37,3 +52,15 @@ def update_my_account_context(context):
|
||||
{"label": _("Issues"), "url": "issues"},
|
||||
{"label": _("Addresses"), "url": "addresses"}
|
||||
])
|
||||
|
||||
def check_customer_or_supplier():
|
||||
if frappe.session.user:
|
||||
contacts = frappe.get_all("Contact", fields=["customer", "supplier", "email_id"],
|
||||
filters={"email_id": frappe.session.user})
|
||||
|
||||
customer = [d.customer for d in contacts if d.customer] or None
|
||||
supplier = [d.supplier for d in contacts if d.supplier] or None
|
||||
|
||||
if customer: return 'Customer', customer
|
||||
if supplier : return 'Supplier', supplier
|
||||
return 'Customer', None
|
@ -32,6 +32,9 @@ def get_notification_config():
|
||||
"status": ("not in", ("Stopped",)),
|
||||
"per_ordered": ("<", 100)
|
||||
},
|
||||
"Request for Quotation": {
|
||||
"docstatus": 0
|
||||
},
|
||||
"Purchase Order": {
|
||||
"status": ("not in", ("Completed", "Closed")),
|
||||
"docstatus": ("<", 2)
|
||||
|
@ -48,8 +48,10 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
|
||||
if(doc.material_request_type === "Purchase")
|
||||
cur_frm.add_custom_button(__('Purchase Order'),
|
||||
this.make_purchase_order, __("Make"));
|
||||
|
||||
if(doc.material_request_type === "Purchase")
|
||||
cur_frm.add_custom_button(__("Request for Quotation"),
|
||||
this.make_request_for_quotation, __("Make"))
|
||||
this.make_request_for_quotation, __("Make"));
|
||||
|
||||
if(doc.material_request_type === "Purchase")
|
||||
cur_frm.add_custom_button(__("Supplier Quotation"),
|
||||
|
12
erpnext/templates/emails/request_for_quotation.html
Normal file
12
erpnext/templates/emails/request_for_quotation.html
Normal file
@ -0,0 +1,12 @@
|
||||
<h3>{{_("Request for Quotation")}}</h3>
|
||||
<br>
|
||||
<p>{{ message }}</p>
|
||||
{% if update_password_link %}
|
||||
<p>{{_("Please click on the following link to set your new password")}}:</p>
|
||||
<p><a href="{{ update_password_link }}">{{ update_password_link }}</a></p>
|
||||
{% else %}
|
||||
<p>{{_("Request for quotation can be access by clicking following link")}}:</p>
|
||||
<p><a href="{{ rfq_link }}">{{ rfq_link }}</a></p>
|
||||
{% endif %}
|
||||
<p>{{_("Thank you")}},<br>
|
||||
{{ user_fullname }}</p>
|
84
erpnext/templates/includes/rfq.js
Normal file
84
erpnext/templates/includes/rfq.js
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
window.doc={{ doc.as_json() }};
|
||||
|
||||
$(document).ready(function() {
|
||||
new rfq();
|
||||
doc.supplier = "{{ doc.supplier }}"
|
||||
});
|
||||
|
||||
rfq = Class.extend({
|
||||
init: function(){
|
||||
this.onfocus_select_all();
|
||||
this.change_qty();
|
||||
this.change_rate();
|
||||
this.terms();
|
||||
this.submit_rfq();
|
||||
},
|
||||
|
||||
onfocus_select_all: function(){
|
||||
$("input").click(function(){
|
||||
$(this).select();
|
||||
})
|
||||
},
|
||||
|
||||
change_qty: function(){
|
||||
var me = this;
|
||||
$('.rfq-items').on("change", ".rfq-qty", function(){
|
||||
me.idx = parseFloat($(this).attr('data-idx'));
|
||||
me.qty = parseFloat($(this).val());
|
||||
me.rate = parseFloat($(repl('.rfq-rate[data-idx=%(idx)s]',{'idx': me.idx})).val());
|
||||
me.update_qty_rate();
|
||||
})
|
||||
},
|
||||
|
||||
change_rate: function(){
|
||||
var me = this;
|
||||
$(".rfq-items").on("change", ".rfq-rate", function(){
|
||||
me.idx = parseFloat($(this).attr('data-idx'));
|
||||
me.rate = parseFloat($(this).val());
|
||||
me.qty = parseFloat($(repl('.rfq-qty[data-idx=%(idx)s]',{'idx': me.idx})).val());
|
||||
me.update_qty_rate();
|
||||
})
|
||||
},
|
||||
|
||||
terms: function(){
|
||||
$(".terms").on("change", ".terms-feedback", function(){
|
||||
doc.terms = $(this).val();
|
||||
})
|
||||
},
|
||||
|
||||
update_qty_rate: function(){
|
||||
var me = this;
|
||||
doc.grand_total = 0.0;
|
||||
$.each(doc.items, function(idx, data){
|
||||
if(data.idx == me.idx){
|
||||
data.qty = me.qty;
|
||||
data.rate = me.rate;
|
||||
data.amount = (me.rate * me.qty) || 0.0;
|
||||
$(repl('.rfq-amount[data-idx=%(idx)s]',{'idx': me.idx})).text(data.amount.toFixed(2));
|
||||
}
|
||||
|
||||
doc.grand_total += flt(data.amount);
|
||||
$('.tax-grand-total').text(doc.grand_total.toFixed(2));
|
||||
})
|
||||
},
|
||||
|
||||
submit_rfq: function(){
|
||||
$('.btn-sm').click(function(){
|
||||
frappe.freeze();
|
||||
frappe.call({
|
||||
type: "POST",
|
||||
method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.create_supplier_quotation",
|
||||
args: {
|
||||
doc: doc
|
||||
},
|
||||
btn: this,
|
||||
callback: function(r){
|
||||
frappe.unfreeze();
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
30
erpnext/templates/includes/rfq/rfq_items.html
Normal file
30
erpnext/templates/includes/rfq/rfq_items.html
Normal file
@ -0,0 +1,30 @@
|
||||
{% from "erpnext/templates/includes/rfq/rfq_macros.html" import item_name_and_description %}
|
||||
|
||||
{% for d in doc.items %}
|
||||
<div class="rfq-item">
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-xs-6" style="margin-bottom: 10px;margin-top: 5px;">
|
||||
{{ item_name_and_description(d, doc) }}
|
||||
</div>
|
||||
<!-- <div class="col-sm-2 col-xs-2" style="margin-bottom: 10px;">
|
||||
<textarea type="text" style="margin-top: 5px;" class="input-with-feedback form-control rfq-offer_detail" ></textarea>
|
||||
</div> -->
|
||||
<div class="col-sm-2 col-xs-2 text-right">
|
||||
<input type="number" class="form-control text-right rfq-qty" style="margin-top: 5px; max-width: 70px;display: inline-block"
|
||||
value = "{{ d.get_formatted('qty') }}"
|
||||
data-idx="{{ d.idx }}">
|
||||
<p class="text-muted small" style="margin-top: 10px;">
|
||||
{{_("UOM") + ": "+ d.uom}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-sm-2 col-xs-2 text-right">
|
||||
<input type="number" class="form-control text-right rfq-rate"
|
||||
style="margin-top: 5px; max-width: 70px;display: inline-block" value="0.00"
|
||||
data-idx="{{ d.idx }}">
|
||||
</div>
|
||||
<div class="col-sm-2 col-xs-2 text-right">
|
||||
<span class="rfq-amount" data-idx="{{ d.idx }}">0.00</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
21
erpnext/templates/includes/rfq/rfq_macros.html
Normal file
21
erpnext/templates/includes/rfq/rfq_macros.html
Normal file
@ -0,0 +1,21 @@
|
||||
{% from "erpnext/templates/includes/macros.html" import product_image_square %}
|
||||
|
||||
{% macro item_name_and_description(d, doc) %}
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-sm-2 order-image-col">
|
||||
<div class="order-image">
|
||||
{{ product_image_square(d.image) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-8 col-sm-10">
|
||||
{{ d.item_code }}
|
||||
<p class="text-muted small">{{ d.description }}</p>
|
||||
{% set supplier_part_no = frappe.db.get_value("Item Supplier", {'parent': d.item_code, 'supplier': doc.supplier}, "supplier_part_no") %}
|
||||
<p class="text-muted small supplier-part-no">
|
||||
{% if supplier_part_no %}
|
||||
{{_("Supplier Part No") + ": "+ supplier_part_no}}
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
83
erpnext/templates/pages/rfq.html
Normal file
83
erpnext/templates/pages/rfq.html
Normal file
@ -0,0 +1,83 @@
|
||||
{% extends "templates/web.html" %}
|
||||
|
||||
{% block header %}
|
||||
<h1>{{ doc.name }}</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script>{% include "templates/includes/rfq.js" %}</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{% include "templates/includes/breadcrumbs.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block style %}
|
||||
<style>
|
||||
{% include "templates/includes/order/order.css" %}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block header_actions %}
|
||||
{% if doc.items %}
|
||||
<button class="btn btn-primary btn-sm"
|
||||
type="button">
|
||||
{{ _("Submit") }}</button>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<div class="rfq-supplier">{{ doc.supplier }}</div>
|
||||
</div>
|
||||
<div class="col-xs-6 text-muted text-right h6">
|
||||
{{ doc.get_formatted("transaction_date") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rfq-content">
|
||||
<div id="order-container">
|
||||
<div id="rfq-items">
|
||||
<div class="row cart-item-header">
|
||||
<div class="col-sm-6 col-xs-6">
|
||||
Items
|
||||
</div>
|
||||
<div class="col-sm-2 col-xs-2 text-right">
|
||||
Qty
|
||||
</div>
|
||||
<div class="col-sm-2 col-xs-2 text-right">
|
||||
Rate
|
||||
</div>
|
||||
<div class="col-sm-2 col-xs-2 text-right">
|
||||
Amount
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
{% if doc.items %}
|
||||
<div class="rfq-items">
|
||||
{% include "templates/includes/rfq/rfq_items.html" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if doc.items %}
|
||||
<div class="row grand-total-row">
|
||||
<div class="col-xs-10 text-right">{{ _("Grand Total") }}</div>
|
||||
<div class="col-xs-2 text-right">
|
||||
<span class="tax-grand-total">0.0</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row terms">
|
||||
<div class="col-xs-5 text-left text-muted">{{ _("Terms and Conditions: ") }}</div>
|
||||
</div>
|
||||
<div class="row terms">
|
||||
<div class="col-xs-5 text-left text-muted">
|
||||
<textarea class="form-control terms-feedback" style="border:1px solid #cccccc; padding:4px"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- no-sidebar -->
|
||||
{% endblock %}
|
31
erpnext/templates/pages/rfq.py
Normal file
31
erpnext/templates/pages/rfq.py
Normal file
@ -0,0 +1,31 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
context.doc = frappe.get_doc(frappe.form_dict.doctype, frappe.form_dict.name)
|
||||
context.parents = frappe.form_dict.parents
|
||||
context.doc.supplier = get_supplier()
|
||||
unauthrized_user(context.doc.supplier)
|
||||
context["title"] = frappe.form_dict.name
|
||||
|
||||
def unauthrized_user(supplier):
|
||||
status = check_supplier_has_docname_access(supplier)
|
||||
if status == False:
|
||||
frappe.throw(_("Not Permitted"), frappe.PermissionError)
|
||||
|
||||
def get_supplier():
|
||||
from erpnext.shopping_cart.utils import check_customer_or_supplier
|
||||
key, parties = check_customer_or_supplier()
|
||||
return parties[0] if key == 'Supplier' else ''
|
||||
|
||||
def check_supplier_has_docname_access(supplier):
|
||||
status = True
|
||||
if frappe.form_dict.name not in frappe.db.sql_list("""select parent from `tabRFQ Supplier`
|
||||
where supplier = '{supplier}'""".format(supplier=supplier)):
|
||||
status = False
|
||||
return status
|
Loading…
x
Reference in New Issue
Block a user