[enhancement] request for quotation
diff --git a/erpnext/templates/emails/request_for_quotation.html b/erpnext/templates/emails/request_for_quotation.html
new file mode 100644
index 0000000..91bdd6b
--- /dev/null
+++ b/erpnext/templates/emails/request_for_quotation.html
@@ -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>
\ No newline at end of file
diff --git a/erpnext/templates/includes/rfq.js b/erpnext/templates/includes/rfq.js
new file mode 100644
index 0000000..3623d77
--- /dev/null
+++ b/erpnext/templates/includes/rfq.js
@@ -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();
+ }
+ })
+ })
+ }
+})
diff --git a/erpnext/templates/includes/rfq/rfq_items.html b/erpnext/templates/includes/rfq/rfq_items.html
new file mode 100644
index 0000000..de9a95f
--- /dev/null
+++ b/erpnext/templates/includes/rfq/rfq_items.html
@@ -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 %}
\ No newline at end of file
diff --git a/erpnext/templates/includes/rfq/rfq_macros.html b/erpnext/templates/includes/rfq/rfq_macros.html
new file mode 100644
index 0000000..95bbcfe
--- /dev/null
+++ b/erpnext/templates/includes/rfq/rfq_macros.html
@@ -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 %}
diff --git a/erpnext/templates/pages/rfq.html b/erpnext/templates/pages/rfq.html
new file mode 100644
index 0000000..5556d26
--- /dev/null
+++ b/erpnext/templates/pages/rfq.html
@@ -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 %}
diff --git a/erpnext/templates/pages/rfq.py b/erpnext/templates/pages/rfq.py
new file mode 100644
index 0000000..fbdd6db
--- /dev/null
+++ b/erpnext/templates/pages/rfq.py
@@ -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