Merge pull request #5044 from rohitwaghchaure/add_margin_feature
[Enhancement] Add margin in sales flow.
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index a67f109..0e47a75 100755
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -2692,7 +2692,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2016-03-21 13:13:43.694604",
+ "modified": "2016-03-25 07:32:03.043734",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
@@ -2739,26 +2739,6 @@
"write": 0
},
{
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Supplier",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
- {
"amend": 1,
"apply_user_permissions": 0,
"cancel": 1,
@@ -2825,5 +2805,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "supplier",
- "title_field": "title"
+ "title_field": "title",
+ "track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 20b8d1b..af690fb 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -3418,7 +3418,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2016-03-21 13:12:12.430038",
+ "modified": "2016-03-25 07:31:46.017116",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
@@ -3470,26 +3470,6 @@
"cancel": 0,
"create": 0,
"delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Customer",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
@@ -3531,5 +3511,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "customer",
- "title_field": "title"
+ "title_field": "title",
+ "track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 0c8d999..244d39e 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -16,7 +16,7 @@
@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 @@
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):
diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js
index 9a9a865..6dcc865 100644
--- a/erpnext/buying/doctype/purchase_common/purchase_common.js
+++ b/erpnext/buying/doctype/purchase_common/purchase_common.js
@@ -178,6 +178,9 @@
&& !this.frm.doc.shipping_address) {
erpnext.utils.get_shipping_address(this.frm)
}
+
+ var company_doc = frappe.get_doc(":Company", me.frm.doc.company);
+ me.frm.set_value("letter_head", company_doc.default_letter_head);
},
shipping_address: function(){
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 617beff..78924e9 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -47,7 +47,7 @@
if(is_drop_ship && doc.status!="Delivered"){
cur_frm.add_custom_button(__('Delivered'),
- this.delivered_by_supplier, __("Status"));
+ this.delivered_by_supplier, __("Status"));
cur_frm.page.set_inner_btn_group_as_primary(__("Status"));
}
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 2b4b989..7a3202f 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -2693,7 +2693,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-03-21 13:13:07.334625",
+ "modified": "2016-03-25 07:32:01.820327",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
@@ -2765,26 +2765,6 @@
"cancel": 0,
"create": 0,
"delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Supplier",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
@@ -2806,5 +2786,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "supplier",
- "title_field": "title"
+ "title_field": "title",
+ "track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/buying/doctype/request_for_quotation/__init__.py b/erpnext/buying/doctype/request_for_quotation/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/buying/doctype/request_for_quotation/__init__.py
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
new file mode 100644
index 0000000..0d509e2
--- /dev/null
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -0,0 +1,87 @@
+// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+// License: GNU General Public License v3. See license.txt
+
+
+{% include 'buying/doctype/purchase_common/purchase_common.js' %};
+
+frappe.require("assets/erpnext/js/utils.js");
+
+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}
+ }
+ }
+ },
+
+ onload: function(frm){
+ frm.add_fetch('standard_reply', 'response', 'response');
+ },
+
+ 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(frm){
+ var doc = frm.doc;
+ var dialog = new frappe.ui.Dialog({
+ title: __("For Supplier"),
+ fields: [
+ {"fieldtype": "Link", "label": __("Supplier"), "fieldname": "supplier", "options":"Supplier",
+ "get_query": function () {
+ return {
+ query:"erpnext.buying.doctype.request_for_quotation.request_for_quotation.get_supplier",
+ filters: {'parent': doc.name}
+ }
+ }, "reqd": 1 },
+ {"fieldtype": "Button", "label": __("Make Supplier Quotation"), "fieldname": "make_supplier_quotation", "cssClass": "btn-primary"},
+ ]
+ });
+
+ dialog.fields_dict.make_supplier_quotation.$input.click(function(){
+ args = dialog.get_values();
+ if(!args) return;
+ dialog.hide();
+ return frappe.call({
+ type: "GET",
+ method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.make_supplier_quotation",
+ args: {
+ "source_name": doc.name,
+ "for_supplier": args.supplier
+ },
+ freeze: true,
+ callback: function(r) {
+ if(!r.exc) {
+ var doc = frappe.model.sync(r.message);
+ frappe.set_route("Form", r.message.doctype, r.message.name);
+ }
+ }
+ });
+ });
+ 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}));
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
new file mode 100644
index 0000000..88a91a0
--- /dev/null
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
@@ -0,0 +1,767 @@
+{
+ "allow_copy": 0,
+ "allow_import": 1,
+ "allow_rename": 0,
+ "autoname": "naming_series:",
+ "creation": "2016-02-25 01:24:07.224790",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "Document",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Series",
+ "length": 0,
+ "no_copy": 1,
+ "oldfieldname": "naming_series",
+ "oldfieldtype": "Select",
+ "options": "RFQ-",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "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,
+ "description": "",
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_list_view": 0,
+ "label": "Company",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "company",
+ "oldfieldtype": "Link",
+ "options": "Company",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 1,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "column_break1",
+ "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,
+ "oldfieldtype": "Column Break",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "print_width": "50%",
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0,
+ "width": "50%"
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "transaction_date",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_list_view": 0,
+ "label": "Date",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "transaction_date",
+ "oldfieldtype": "Date",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 1,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "suppliers_section",
+ "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,
+ "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": "suppliers",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Supplier Detail",
+ "length": 0,
+ "no_copy": 0,
+ "options": "RFQ Supplier",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "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": "items_section",
+ "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,
+ "oldfieldtype": "Section Break",
+ "options": "icon-shopping-cart",
+ "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": "items",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Items",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "po_details",
+ "oldfieldtype": "Table",
+ "options": "Request for Quotation Item",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "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": "supplier_response_section",
+ "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,
+ "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": "standard_reply",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Standard Reply",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Standard Reply",
+ "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": "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": 1,
+ "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": 1,
+ "collapsible_depends_on": "terms",
+ "fieldname": "terms_section_break",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Terms and Conditions",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldtype": "Section Break",
+ "options": "icon-legal",
+ "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": "tc_name",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Terms",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "tc_name",
+ "oldfieldtype": "Link",
+ "options": "Terms and Conditions",
+ "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
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "terms",
+ "fieldtype": "Text Editor",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Terms and Conditions",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "terms",
+ "oldfieldtype": "Text Editor",
+ "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": 1,
+ "fieldname": "printing_settings",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Printing Settings",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 1,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "select_print_heading",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Print Heading",
+ "length": 0,
+ "no_copy": 1,
+ "oldfieldname": "select_print_heading",
+ "oldfieldtype": "Link",
+ "options": "Print Heading",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 1,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 1,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "letter_head",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Letter Head",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "letter_head",
+ "oldfieldtype": "Select",
+ "options": "Letter Head",
+ "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
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 1,
+ "fieldname": "more_info",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "More Information",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldtype": "Section Break",
+ "options": "icon-file-text",
+ "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": "status",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_list_view": 0,
+ "label": "Status",
+ "length": 0,
+ "no_copy": 1,
+ "oldfieldname": "status",
+ "oldfieldtype": "Select",
+ "options": "\nDraft\nSubmitted\nCancelled",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 1,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "fiscal_year",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_list_view": 0,
+ "label": "Fiscal Year",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "fiscal_year",
+ "oldfieldtype": "Select",
+ "options": "Fiscal Year",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 1,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "column_break3",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Amended From",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Request for Quotation",
+ "permlevel": 0,
+ "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
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "icon": "icon-shopping-cart",
+ "idx": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 1,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2016-03-25 01:14:01.194848",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Request for Quotation",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 1,
+ "apply_user_permissions": 0,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Manufacturing Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "apply_user_permissions": 0,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Purchase Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 0,
+ "email": 1,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Purchase User",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 0,
+ "delete": 0,
+ "email": 1,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Stock User",
+ "set_user_permissions": 0,
+ "share": 0,
+ "submit": 0,
+ "write": 0
+ },
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 0,
+ "delete": 0,
+ "email": 1,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Supplier",
+ "set_user_permissions": 0,
+ "share": 0,
+ "submit": 0,
+ "write": 0
+ },
+ {
+ "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": "Purchase Manager",
+ "set_user_permissions": 0,
+ "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,
+ "read_only_onload": 1,
+ "search_fields": "status, transaction_date",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "timeline_field": "",
+ "title_field": ""
+}
\ No newline at end of file
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
new file mode 100644
index 0000000..92089e4
--- /dev/null
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
@@ -0,0 +1,177 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+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 erpnext.controllers.buying_controller import BuyingController
+
+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)s and supplier like %(txt)s
+ limit %(start)s, %(page_len)s """
+
+ 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):
+ target_doc.supplier = for_supplier
+ set_missing_values(source, target_doc)
+
+ doclist = get_mapped_doc("Request for Quotation", source_name, {
+ "Request for Quotation": {
+ "doctype": "Supplier Quotation",
+ "validation": {
+ "docstatus": ["=", 1]
+ }
+ },
+ "Request for Quotation Item": {
+ "doctype": "Supplier Quotation Item",
+ "field_map": [
+ ["name", "request_for_quotation_item"],
+ ["parent", "request_for_quotation"],
+ ["uom", "uom"]
+ ],
+ }
+ }, 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
+ })
diff --git a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py
new file mode 100644
index 0000000..d643a05
--- /dev/null
+++ b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from frappe.utils import nowdate
+
+class TestRequestforQuotation(unittest.TestCase):
+ def test_make_supplier_quotation(self):
+ 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, rfq.get('suppliers')[0].supplier)
+ sq.submit()
+
+ sq1 = make_supplier_quotation(rfq.name, rfq.get('suppliers')[1].supplier)
+ sq1.submit()
+
+ 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('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('suppliers', data)
+
+ rfq.append("items", {
+ "item_code": "_Test Item",
+ "description": "_Test Item",
+ "uom": "_Test UOM",
+ "qty": 5,
+ "warehouse": "_Test Warehouse - _TC",
+ "schedule_date": nowdate()
+ })
+
+ rfq.submit()
+
+ return rfq
+
+def get_supplier_data():
+ return [{
+ "supplier": "_Test Supplier",
+ "supplier_name": "_Test Supplier"
+ },
+ {
+ "supplier": "_Test Supplier 1",
+ "supplier_name": "_Test Supplier 1"
+ }]
\ No newline at end of file
diff --git a/erpnext/buying/doctype/request_for_quotation_item/__init__.py b/erpnext/buying/doctype/request_for_quotation_item/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/buying/doctype/request_for_quotation_item/__init__.py
diff --git a/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.json b/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.json
new file mode 100644
index 0000000..305253c
--- /dev/null
+++ b/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.json
@@ -0,0 +1,612 @@
+{
+ "allow_copy": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "hash",
+ "creation": "2016-02-25 08:04:02.452958",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 1,
+ "collapsible": 0,
+ "fieldname": "item_code",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_list_view": 1,
+ "label": "Item Code",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "item_code",
+ "oldfieldtype": "Link",
+ "options": "Item",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 1,
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_list_view": 1,
+ "label": "Item Name",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "item_name",
+ "oldfieldtype": "Data",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 1,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 1,
+ "fieldname": "section_break_5",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Description",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "description",
+ "fieldtype": "Text Editor",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Description",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "description",
+ "oldfieldtype": "Small Text",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "print_width": "300px",
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0,
+ "width": "300px"
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "col_break1",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "image",
+ "fieldtype": "Attach",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Image",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "image_view",
+ "fieldtype": "Image",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Image View",
+ "length": 0,
+ "no_copy": 0,
+ "options": "image",
+ "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
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "quantity",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Quantity",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 1,
+ "collapsible": 0,
+ "fieldname": "qty",
+ "fieldtype": "Float",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Quantity",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "qty",
+ "oldfieldtype": "Currency",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "print_width": "60px",
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0,
+ "width": "60px"
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "col_break2",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "schedule_date",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Required Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "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": "uom",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "UOM",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "uom",
+ "oldfieldtype": "Link",
+ "options": "UOM",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "print_width": "100px",
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0,
+ "width": "100px"
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "warehouse_and_reference",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Warehouse and Reference",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "warehouse",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Warehouse",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "warehouse",
+ "oldfieldtype": "Link",
+ "options": "Warehouse",
+ "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
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "project_name",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_list_view": 0,
+ "label": "Project Name",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Project",
+ "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
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "material_request",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Material Request",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Material Request",
+ "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,
+ "collapsible": 0,
+ "fieldname": "col_break4",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "material_request_item",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Material Request Item",
+ "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": "brand",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Brand",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "brand",
+ "oldfieldtype": "Link",
+ "options": "Brand",
+ "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,
+ "collapsible": 0,
+ "description": "",
+ "fieldname": "item_group",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_list_view": 0,
+ "label": "Item Group",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "item_group",
+ "oldfieldtype": "Link",
+ "options": "Item Group",
+ "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": 1,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "page_break",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Page Break",
+ "length": 0,
+ "no_copy": 1,
+ "oldfieldname": "page_break",
+ "oldfieldtype": "Check",
+ "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,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2016-03-25 01:14:38.490488",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Request for Quotation Item",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.py b/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.py
new file mode 100644
index 0000000..cc897af
--- /dev/null
+++ b/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class RequestforQuotationItem(Document):
+ pass
diff --git a/erpnext/buying/doctype/rfq_supplier/__init__.py b/erpnext/buying/doctype/rfq_supplier/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/buying/doctype/rfq_supplier/__init__.py
diff --git a/erpnext/buying/doctype/rfq_supplier/rfq_supplier.json b/erpnext/buying/doctype/rfq_supplier/rfq_supplier.json
new file mode 100644
index 0000000..02a6f0b
--- /dev/null
+++ b/erpnext/buying/doctype/rfq_supplier/rfq_supplier.json
@@ -0,0 +1,213 @@
+{
+ "allow_copy": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "creation": "2016-02-29 17:31:02.993221",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "supplier",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Supplier",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Supplier",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "supplier_name",
+ "fieldtype": "Read Only",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Supplier Name",
+ "length": 0,
+ "no_copy": 0,
+ "options": "supplier.supplier_name",
+ "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": "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,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2016-03-25 13:18:11.017660",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "RFQ Supplier",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/buying/doctype/rfq_supplier/rfq_supplier.py b/erpnext/buying/doctype/rfq_supplier/rfq_supplier.py
new file mode 100644
index 0000000..a7ba65c
--- /dev/null
+++ b/erpnext/buying/doctype/rfq_supplier/rfq_supplier.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class RFQSupplier(Document):
+ pass
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
index 6466643..c9bcc46 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
@@ -1780,7 +1780,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2016-03-16 15:36:05.481917",
+ "modified": "2016-03-25 07:32:02.711099",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation",
@@ -1872,19 +1872,19 @@
"cancel": 0,
"create": 0,
"delete": 0,
- "email": 1,
+ "email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
- "permlevel": 0,
- "print": 1,
+ "permlevel": 1,
+ "print": 0,
"read": 1,
- "report": 1,
- "role": "Supplier",
+ "report": 0,
+ "role": "Purchase Manager",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
- "write": 0
+ "write": 1
},
{
"amend": 0,
@@ -1900,11 +1900,11 @@
"print": 0,
"read": 1,
"report": 0,
- "role": "Purchase Manager",
+ "role": "All",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
- "write": 1
+ "write": 0
}
],
"read_only": 0,
@@ -1913,5 +1913,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "supplier",
- "title_field": "title"
+ "title_field": "title",
+ "track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
index b09667b..1275fcd 100644
--- a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
+++ b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
@@ -883,6 +883,32 @@
"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,
+ "collapsible": 0,
"fieldname": "col_break4",
"fieldtype": "Column Break",
"hidden": 0,
@@ -932,6 +958,31 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "fieldname": "request_for_quotation_item",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Request for Quotation Item",
+ "length": 0,
+ "no_copy": 1,
+ "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,
+ "collapsible": 0,
"fieldname": "brand",
"fieldtype": "Link",
"hidden": 0,
@@ -1046,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",
diff --git a/erpnext/config/buying.py b/erpnext/config/buying.py
index c259f06..0dc51f6 100644
--- a/erpnext/config/buying.py
+++ b/erpnext/config/buying.py
@@ -14,6 +14,11 @@
},
{
"type": "doctype",
+ "name": "Request for Quotation",
+ "description": _("Request for quotation."),
+ },
+ {
+ "type": "doctype",
"name": "Supplier Quotation",
"description": _("Quotations received from Suppliers."),
},
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index c9b660d..5361126 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -20,8 +20,9 @@
}
def get_feed(self):
- return _("From {0} | {1} {2}").format(self.supplier_name, self.currency,
- self.grand_total)
+ if self.get("supplier_name"):
+ return _("From {0} | {1} {2}").format(self.supplier_name, self.currency,
+ self.grand_total)
def validate(self):
super(BuyingController, self).validate()
@@ -40,7 +41,7 @@
# 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()
diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py
index ae6e9e4..5882578 100644
--- a/erpnext/controllers/website_list_for_contact.py
+++ b/erpnext/controllers/website_list_for_contact.py
@@ -28,15 +28,14 @@
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 @@
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:
diff --git a/erpnext/docs/assets/img/buying/make-supplier-quotation-from-rfq.png b/erpnext/docs/assets/img/buying/make-supplier-quotation-from-rfq.png
new file mode 100644
index 0000000..135e9fc
--- /dev/null
+++ b/erpnext/docs/assets/img/buying/make-supplier-quotation-from-rfq.png
Binary files differ
diff --git a/erpnext/docs/assets/img/buying/request-for-quotation.png b/erpnext/docs/assets/img/buying/request-for-quotation.png
new file mode 100644
index 0000000..b8b1ec2
--- /dev/null
+++ b/erpnext/docs/assets/img/buying/request-for-quotation.png
Binary files differ
diff --git a/erpnext/docs/user/manual/en/buying/index.txt b/erpnext/docs/user/manual/en/buying/index.txt
index a12bb06..25c8797 100644
--- a/erpnext/docs/user/manual/en/buying/index.txt
+++ b/erpnext/docs/user/manual/en/buying/index.txt
@@ -1,4 +1,5 @@
supplier
+request-for-quotation
supplier-quotation
purchase-order
setup
diff --git a/erpnext/docs/user/manual/en/buying/request-for-quotation.md b/erpnext/docs/user/manual/en/buying/request-for-quotation.md
new file mode 100644
index 0000000..379cdb5
--- /dev/null
+++ b/erpnext/docs/user/manual/en/buying/request-for-quotation.md
@@ -0,0 +1,14 @@
+A Request for Quotation is a document that an organization submits to one or more suppliers eliciting quotation for items.
+
+In ERPNext, You can create request for quotation directly by going to:
+
+`Buying > Documents > Request for Quotation > New Request for Quotation`
+
+Create Request for Quotation:
+
+
+
+Create Supplier Quotation from Request for Quotation form:
+
+
+
\ No newline at end of file
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 6e86d84..0ccc82a 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -71,6 +71,13 @@
"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"},
]
@@ -143,3 +150,7 @@
get_translated_dict = {
("doctype", "Global Defaults"): "frappe.geo.country_info.get_translated_dict"
}
+
+bot_parsers = [
+ 'erpnext.utilities.bot.FindItemBot',
+]
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index efcceb3..d0b738f 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -257,4 +257,5 @@
execute:frappe.delete_doc_if_exists("Web Form", "contact") #2016-03-10
erpnext.patches.v6_20x.remove_fiscal_year_from_holiday_list
erpnext.patches.v6_24.map_customer_address_to_shipping_address_on_po
-erpnext.patches.v6_27.fix_recurring_order_status
\ No newline at end of file
+erpnext.patches.v6_27.fix_recurring_order_status
+erpnext.patches.v6_20x.remove_customer_supplier_roles
\ No newline at end of file
diff --git a/erpnext/patches/v6_20x/remove_customer_supplier_roles.py b/erpnext/patches/v6_20x/remove_customer_supplier_roles.py
new file mode 100644
index 0000000..e5e3d3f
--- /dev/null
+++ b/erpnext/patches/v6_20x/remove_customer_supplier_roles.py
@@ -0,0 +1,18 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ for role in ('Customer', 'Supplier'):
+ frappe.db.sql('''delete from `tabUserRole`
+ where role=%s and parent in ("Administrator", "Guest")''', role)
+
+ if not frappe.db.sql('select name from `tabUserRole` where role=%s', role):
+
+ # delete DocPerm
+ for doctype in frappe.db.sql('select parent from tabDocPerm where role=%s', role):
+ d = frappe.get_doc("DocType", doctype[0])
+ d.permissions = [p for p in d.permissions if p.role != role]
+ d.save()
+
+ # delete Role
+ frappe.delete_doc_if_exists('Role', role)
diff --git a/erpnext/projects/doctype/project/project.json b/erpnext/projects/doctype/project/project.json
index 02a3fd0..34bb36f 100644
--- a/erpnext/projects/doctype/project/project.json
+++ b/erpnext/projects/doctype/project/project.json
@@ -326,6 +326,57 @@
{
"allow_on_submit": 0,
"bold": 0,
+ "collapsible": 1,
+ "fieldname": "users_section",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Users",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "users",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Users",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Project User",
+ "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": "sb_milestones",
"fieldtype": "Section Break",
@@ -921,7 +972,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 4,
- "modified": "2016-03-15 05:10:21.779365",
+ "modified": "2016-03-25 06:46:29.485193",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project",
@@ -972,5 +1023,6 @@
"read_only_onload": 0,
"search_fields": "customer, status, priority, is_active",
"sort_order": "DESC",
- "timeline_field": "customer"
+ "timeline_field": "customer",
+ "track_seen": 1
}
\ No newline at end of file
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index c2b8fb1..fa2f6b4 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -123,19 +123,30 @@
from `tabPurchase Invoice Item` where project = %s and docstatus=1""", self.name)
self.total_purchase_cost = total_purchase_cost and total_purchase_cost[0][0] or 0
-
-
+
+
def get_project_list(doctype, txt, filters, limit_start, limit_page_length=20):
- from frappe.templates.pages.list import get_list
- return get_list(doctype, txt, filters, limit_start, limit_page_length, ignore_permissions=True)
-
+ return frappe.db.sql('''select distinct project.*
+ from tabProject project, `tabProject User` project_user
+ where
+ (project_user.user = %(user)s
+ and project_user.parent = project.name)
+ or project.owner = %(user)s
+ order by project.modified desc
+ limit {0}, {1}
+ '''.format(limit_start, limit_page_length),
+ {'user':frappe.session.user},
+ as_dict=True,
+ update={'doctype':'Project'})
+
def get_list_context(context=None):
return {
"title": _("My Projects"),
"get_list": get_project_list,
"row_template": "templates/includes/project_row.html"
}
+
@frappe.whitelist()
def get_cost_center_name(project):
return frappe.db.get_value("Project", project, "cost_center")
diff --git a/erpnext/projects/doctype/project_user/__init__.py b/erpnext/projects/doctype/project_user/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/projects/doctype/project_user/__init__.py
diff --git a/erpnext/projects/doctype/project_user/project_user.json b/erpnext/projects/doctype/project_user/project_user.json
new file mode 100644
index 0000000..f808701
--- /dev/null
+++ b/erpnext/projects/doctype/project_user/project_user.json
@@ -0,0 +1,58 @@
+{
+ "allow_copy": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "creation": "2016-03-25 02:52:19.283003",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "user",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "User",
+ "length": 0,
+ "no_copy": 0,
+ "options": "User",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 1,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2016-03-25 03:01:08.629640",
+ "modified_by": "Administrator",
+ "module": "Projects",
+ "name": "Project User",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/projects/doctype/project_user/project_user.py b/erpnext/projects/doctype/project_user/project_user.py
new file mode 100644
index 0000000..3198f3b
--- /dev/null
+++ b/erpnext/projects/doctype/project_user/project_user.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class ProjectUser(Document):
+ pass
diff --git a/erpnext/projects/doctype/task/task.json b/erpnext/projects/doctype/task/task.json
index 9816df8..443ddba 100644
--- a/erpnext/projects/doctype/task/task.json
+++ b/erpnext/projects/doctype/task/task.json
@@ -17,6 +17,7 @@
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Subject",
@@ -42,6 +43,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Project",
@@ -68,6 +70,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -93,6 +96,7 @@
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Status",
@@ -119,6 +123,7 @@
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Priority",
@@ -145,6 +150,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -168,6 +174,7 @@
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Expected Start Date",
@@ -195,6 +202,7 @@
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Expected Time (in hours)",
@@ -220,6 +228,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -243,6 +252,7 @@
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Expected End Date",
@@ -268,6 +278,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -292,6 +303,7 @@
"fieldtype": "Text Editor",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Details",
@@ -319,6 +331,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Depends On",
@@ -343,6 +356,7 @@
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "depends_on",
@@ -369,6 +383,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
@@ -395,6 +410,7 @@
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Actual Start Date (via Time Logs)",
@@ -422,6 +438,7 @@
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Actual Time (in hours)",
@@ -447,6 +464,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -470,6 +488,7 @@
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Actual End Date (via Time Logs)",
@@ -495,6 +514,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -518,6 +538,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Total Costing Amount (via Time Logs)",
@@ -544,6 +565,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Total Expense Claim (via Expense Claim)",
@@ -569,6 +591,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -592,6 +615,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Total Billing Amount (via Time Logs)",
@@ -616,6 +640,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
@@ -640,6 +665,7 @@
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Review Date",
@@ -666,6 +692,7 @@
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Closing Date",
@@ -691,6 +718,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -713,6 +741,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Company",
@@ -741,7 +770,7 @@
"istable": 0,
"max_attachments": 5,
"menu_index": 0,
- "modified": "2016-02-03 01:11:46.043538",
+ "modified": "2016-03-25 05:27:03.346334",
"modified_by": "Administrator",
"module": "Projects",
"name": "Task",
@@ -773,5 +802,6 @@
"search_fields": "subject",
"sort_order": "DESC",
"timeline_field": "project",
- "title_field": "subject"
+ "title_field": "subject",
+ "track_seen": 1
}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json
index 0a3d5b5..7cfee77 100644
--- a/erpnext/selling/doctype/quotation/quotation.json
+++ b/erpnext/selling/doctype/quotation/quotation.json
@@ -2129,7 +2129,7 @@
"istable": 0,
"max_attachments": 1,
"menu_index": 0,
- "modified": "2016-03-03 06:30:26.308629",
+ "modified": "2016-03-25 07:31:44.251525",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation",
@@ -2182,27 +2182,6 @@
"cancel": 0,
"create": 0,
"delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "match": "",
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Customer",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
@@ -2327,5 +2306,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "customer",
- "title_field": "title"
+ "title_field": "title",
+ "track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index 7e37cb7..c0cb201 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -3018,7 +3018,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-03-21 13:11:32.654873",
+ "modified": "2016-03-25 07:31:45.471702",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",
@@ -3110,26 +3110,6 @@
"cancel": 0,
"create": 0,
"delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 0,
- "role": "Customer",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
@@ -3171,5 +3151,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "customer",
- "title_field": "title"
+ "title_field": "title",
+ "track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/shopping_cart/utils.py b/erpnext/shopping_cart/utils.py
index 3e1afe2..7cd269d 100644
--- a/erpnext/shopping_cart/utils.py
+++ b/erpnext/shopping_cart/utils.py
@@ -16,6 +16,8 @@
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 @@
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 @@
{"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
\ No newline at end of file
diff --git a/erpnext/startup/notifications.py b/erpnext/startup/notifications.py
index 7555312..75e55b5 100644
--- a/erpnext/startup/notifications.py
+++ b/erpnext/startup/notifications.py
@@ -32,6 +32,9 @@
"status": ("not in", ("Stopped",)),
"per_ordered": ("<", 100)
},
+ "Request for Quotation": {
+ "docstatus": 0
+ },
"Purchase Order": {
"status": ("not in", ("Completed", "Closed")),
"docstatus": ("<", 2)
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index b4bb456..11890dc 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -2799,7 +2799,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2016-03-18 05:10:56.813113",
+ "modified": "2016-03-25 07:31:44.919162",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note",
@@ -2891,26 +2891,6 @@
"cancel": 0,
"create": 0,
"delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Customer",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
@@ -2932,5 +2912,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "customer",
- "title_field": "title"
+ "title_field": "title",
+ "track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index c4b4b0e..982534d 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -50,6 +50,10 @@
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"));
+
+ if(doc.material_request_type === "Purchase")
cur_frm.add_custom_button(__("Supplier Quotation"),
this.make_supplier_quotation, __("Make"));
@@ -158,6 +162,14 @@
run_link_triggers: true
});
},
+
+ make_request_for_quotation: function(){
+ frappe.model.open_mapped_doc({
+ method: "erpnext.stock.doctype.material_request.material_request.make_request_for_quotation",
+ frm: cur_frm,
+ run_link_triggers: true
+ });
+ },
make_supplier_quotation: function() {
frappe.model.open_mapped_doc({
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 679bd2d..6456d03 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -212,6 +212,28 @@
}, target_doc, postprocess)
return doclist
+
+@frappe.whitelist()
+def make_request_for_quotation(source_name, target_doc=None):
+ doclist = get_mapped_doc("Material Request", source_name, {
+ "Material Request": {
+ "doctype": "Request for Quotation",
+ "validation": {
+ "docstatus": ["=", 1],
+ "material_request_type": ["=", "Purchase"]
+ }
+ },
+ "Material Request Item": {
+ "doctype": "Request for Quotation Item",
+ "field_map": [
+ ["name", "material_request_item"],
+ ["parent", "material_request"],
+ ["uom", "uom"]
+ ]
+ }
+ }, target_doc)
+
+ return doclist
@frappe.whitelist()
def make_purchase_order_based_on_supplier(source_name, target_doc=None):
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index b14a700..3c5780a 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -2416,7 +2416,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2016-03-16 15:52:17.581445",
+ "modified": "2016-03-25 07:32:02.276482",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt",
@@ -2508,26 +2508,6 @@
"cancel": 0,
"create": 0,
"delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Supplier",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
@@ -2549,5 +2529,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "supplier",
- "title_field": "title"
+ "title_field": "title",
+ "track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/support/doctype/issue/issue.json b/erpnext/support/doctype/issue/issue.json
index e0b38a8..2591937 100644
--- a/erpnext/support/doctype/issue/issue.json
+++ b/erpnext/support/doctype/issue/issue.json
@@ -702,7 +702,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-03-23 07:40:21.423217",
+ "modified": "2016-03-25 07:31:44.715945",
"modified_by": "Administrator",
"module": "Support",
"name": "Issue",
@@ -710,26 +710,6 @@
"permissions": [
{
"amend": 0,
- "apply_user_permissions": 1,
- "cancel": 0,
- "create": 1,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Customer",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- },
- {
- "amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
@@ -754,5 +734,6 @@
"search_fields": "status,customer,subject,raised_by",
"sort_order": "ASC",
"timeline_field": "customer",
- "title_field": "subject"
+ "title_field": "subject",
+ "track_seen": 0
}
\ No newline at end of file
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/generators/job_opening.html b/erpnext/templates/generators/job_opening.html
index 9cfa888..bbc5fee 100644
--- a/erpnext/templates/generators/job_opening.html
+++ b/erpnext/templates/generators/job_opening.html
@@ -12,8 +12,10 @@
<div>{{ description }}</div>
-<a class='btn btn-primary'
- href='/job_application?job_title={{ doc.job_title }}'>
+<p>
+ <a class='btn btn-primary'
+ href='/job_application?job_title={{ doc.name }}'>
{{ _("Apply Now") }}</a>
+</p>
{% endblock %}
diff --git a/erpnext/templates/includes/projects.css b/erpnext/templates/includes/projects.css
index 6ad3246..99ec4c8 100644
--- a/erpnext/templates/includes/projects.css
+++ b/erpnext/templates/includes/projects.css
@@ -13,6 +13,18 @@
padding-bottom: 5px;
}
+#project-search {
+ border: none;
+}
+
+.task-link {
+ font-weight: bold;
+}
+
+.task-link.seen {
+ font-weight: normal;
+}
+
.row-header {
font-size: 14px;
font-weight: 500;
@@ -85,7 +97,7 @@
.timeline-centered .timeline-entry .timeline-entry-inner .timeline-icon {
- margin-top:10px;
+ margin-top:14px;
background: #fff;
color: #737881;
display: block;
@@ -136,7 +148,7 @@
color: #fff;
}
-
+
.timeline-centered .timeline-entry .timeline-entry-inner .timeline-label {
position: relative;
background: #f5f5f6;
diff --git a/erpnext/templates/includes/projects/macros.html b/erpnext/templates/includes/projects/macros.html
index eb2b8db..5b22583 100644
--- a/erpnext/templates/includes/projects/macros.html
+++ b/erpnext/templates/includes/projects/macros.html
@@ -1 +1,2 @@
-{% macro back_link(doc) %}&back-to=/projects?project={{ doc.name }}|{{ doc.project_name }}{% endmacro %}
+{% macro back_link(doc) %}&back-to=/projects?project={{ doc.name }}&back-to-title={{ doc.project_name }}{% endmacro %}
+
diff --git a/erpnext/templates/includes/projects/project_issues.html b/erpnext/templates/includes/projects/project_issues.html
index 0d569d8..f8924f5 100644
--- a/erpnext/templates/includes/projects/project_issues.html
+++ b/erpnext/templates/includes/projects/project_issues.html
@@ -22,12 +22,7 @@
<span class="avatar avatar-small avatar-empty"></span>
{% endif %}
</div>
- <div class='pull-right' style='padding-right:10px;'>
- {% if issue.status != "Closed" %}
- <span class="text-extra-muted "> <i class="octicon octicon-x issue-x" title="Close" id = "{{issue.name}}"></i> </span>
- {% endif %}
- </div>
</div>
</div>
</div>
-{% endfor %}
+{% endfor %}
\ No newline at end of file
diff --git a/erpnext/templates/includes/project_search_box.html b/erpnext/templates/includes/projects/project_search_box.html
similarity index 70%
rename from erpnext/templates/includes/project_search_box.html
rename to erpnext/templates/includes/projects/project_search_box.html
index 8788fcd..59ebaa4 100644
--- a/erpnext/templates/includes/project_search_box.html
+++ b/erpnext/templates/includes/projects/project_search_box.html
@@ -1,7 +1,8 @@
<div class="project-search">
<input type="text" id="project-search"
- placeholder="Search..."><span style="position:relative;
- left:-19px;"> <a href="/projects?project={{doc.name}}" class="octicon octicon-x text-extra-muted" title="Clear" ></a> </span>
+ placeholder="Search...">
+ <span style="position:relative;
+ left:-19px;"> <a href="/projects?project={{doc.name}}" class="octicon octicon-x text-extra-muted" title="Clear" ></a> </span>
</div>
<script>
diff --git a/erpnext/templates/includes/projects/project_tasks.html b/erpnext/templates/includes/projects/project_tasks.html
index a951712..3db5a68 100644
--- a/erpnext/templates/includes/projects/project_tasks.html
+++ b/erpnext/templates/includes/projects/project_tasks.html
@@ -4,28 +4,20 @@
<div class='task'>
<div class='row project-item'>
<div class='col-xs-9'>
- <a class="no-decoration" href="/tasks?name={{ task.name }}{{ back_link(doc) }}">
- <span class="indicator {{ "orange" if task.status=="Open" else "green" }}">
- {% if task.status == "Closed" %}
- {{ task.subject }} completed on {{ task.closing_date }}
- {% else %}
- {{ task.subject }}
- {% endif %}
- </span>
- </a>
- </div>
- <div class='col-xs-3'>
- <div class='pull-right'>
- {% if task.todo %} <span class="avatar avatar-small" title="{{ task.todo.owner }}"> <img src="{{ task.todo.user_image }}"></span>
+ {% if task.todo %}
+ <span class="avatar avatar-small" title="{{ task.todo.owner }}">
+ <img src="{{ task.todo.user_image }}">
+ </span>
+ {% else %}
+ <span class="avatar avatar-small avatar-empty"></span>
+ {% endif %}
+ <a class="no-decoration task-link {{ task.css_seen }}" href="/tasks?name={{ task.name }}{{ back_link(doc) }}">
+ {% if task.status == "Closed" %}
+ {{ task.subject }} completed on {{ task.closing_date }}
{% else %}
- <span class="avatar avatar-small avatar-empty"></span>
+ {{ task.subject }}
{% endif %}
- </div>
- <div class='pull-right' style='padding-right:10px;'>
- {% if task.status != "Closed" %}
- <span class="text-extra-muted "> <i class="octicon octicon-x task-x" title="Close" id = "{{task.name}}"></i> </span>
- {% endif %}
- </div>
+ </a>
</div>
</div>
</div>
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/projects.html b/erpnext/templates/pages/projects.html
index b348674..fef79ce 100644
--- a/erpnext/templates/pages/projects.html
+++ b/erpnext/templates/pages/projects.html
@@ -30,9 +30,9 @@
{% block page_content %}
-{% include 'templates/includes/project_search_box.html' %}
+{% include 'templates/includes/projects/project_search_box.html' %}
-{% if frappe.form_dict.q %}
+<!-- {% if frappe.form_dict.q %}
<p class="text-muted"> <a href="/projects?project={{doc.name}}" class="text-muted">
Filtered by "{{ frappe.form_dict.q }}" Clear</a></p>
{% else %}
@@ -43,54 +43,48 @@
{% if doc.timelines|length > 9 %}
<p><a class='more-timelines small underline'>{{ _("More") }}</a><p>
{% endif %}
-{% endif %}
+
+{% endif %} -->
<div class='padding'></div>
<h3>{{ _("Tasks") }}</h3>
+<p>
+<a class='small underline' href='/tasks?new=1&project={{ doc.project_name }}{{ back_link(doc) }}'>New task</a>
+<a class='small underline task-status-switch' data-status='Open'>{{ _("Show closed") }}</a>
+</p>
+
{% if doc.tasks %}
- <div class='project-tasks-section'>
- <div class="btn-group btn-toggle">
- <button class="btn btn-link btn-open-tasks"><span class="indicator orange"></span>Open</button>
- <button class="btn btn-link btn-closed-tasks"><span class="indicator green"></span>Closed</button>
- </div>
- <div class='project-tasks'>
+ <div class='project-task-section'>
+ <div class='project-task'>
{% include "erpnext/templates/includes/projects/project_tasks.html" %}
</div>
-
- {% if doc.tasks|length > 9 %}
- <p><a id= 'more-tasks' class='more-tasks small underline'>{{ _("More") }}</a><p>
- {% endif %}
+ <p><a id= 'more-task' style='display: none;' class='more-tasks small underline'>{{ _("More") }}</a><p>
</div>
{% else %}
<p class="text-muted">No tasks</p>
{% endif %}
-<p><a href='/tasks?new=1&project={{ doc.project_name }}{{ back_link(doc) }}'>Add a new task</a></p>
-<div class='padding'></div>
+<!-- <div class='padding'></div>
<h3>{{ _("Issues") }}</h3>
-{% if doc.issues %}
- <div class='project-issues-section'>
- <div class="btn-group btn-toggle">
- <button class="btn btn-link btn-open-issues"><span class="indicator red"></span>Open</button>
- <button class="btn btn-link btn-closed-issues"><span class="indicator green"></span>Closed</button>
- </div>
- <div class='project-issues'>
- {% include "erpnext/templates/includes/projects/project_issues.html" %}
- </div>
+<p>
+ <a class='small underline' href='/issues?new=1&project={{ doc.project_name }}{{ back_link(doc) }}'>New issue</a>
+ <a class='small underline issue-status-switch' data-status='Open'>{{ _("Show closed") }}</a>
+</p>
- {% if doc.issues|length > 9 %}
- <p><a id='more-issues' class='more-issues small underline'>{{ _("More") }}</a><p>
- {% endif %}
+{% if doc.issues %}
+ <div class='project-issue-section'>
+ <div class='project-issue'>
+ {% include "erpnext/templates/includes/projects/project_issues.html" %}
+ </div>
+ <p><a id='more-issue' style='display: none;' class='more-issues small underline'>{{ _("More") }}</a><p>
</div>
{% else %}
<p class="text-muted">No Issues</p>
-{% endif %}
-
-<p> <a href='/issues?new=1&project={{ doc.project_name }}{{ back_link(doc) }}'>Add a new issue</a></p>
+{% endif %} -->
<div class='padding'></div>
diff --git a/erpnext/templates/pages/projects.js b/erpnext/templates/pages/projects.js
index 331c2d4..a0e0ee0 100644
--- a/erpnext/templates/pages/projects.js
+++ b/erpnext/templates/pages/projects.js
@@ -1,53 +1,60 @@
frappe.ready(function() {
- $( window ).load(function() {
- $(".btn-open-tasks").click();
- $(".btn-open-issues").click();
- });
-
- $('.btn-closed-tasks').click(function() {
- reload_items('closed','tasks');
- });
-
- $('.btn-open-tasks').click(function() {
- reload_items('open','tasks');
- });
- $('.btn-closed-issues').click(function() {
- reload_items('closed','issues');
- });
-
- $('.btn-open-issues').click(function() {
- reload_items('open','issues');
- });
+ $('.task-status-switch').on('click', function() {
+ var $btn = $(this);
+ if($btn.attr('data-status')==='Open') {
+ reload_items('closed', 'task', $btn);
+ } else {
+ reload_items('open', 'task', $btn);
+ }
+ })
+
+
+ $('.issue-status-switch').on('click', function() {
+ var $btn = $(this);
+ if($btn.attr('data-status')==='Open') {
+ reload_items('closed', 'issue', $btn);
+ } else {
+ reload_items('open', 'issue', $btn);
+ }
+ })
+
+ //
+ // $('.btn-closed-tasks').click(function() {
+ // reload_items('closed','tasks');
+ // });
+ //
+ // $('.btn-open-tasks').click(function() {
+ // reload_items('open','tasks');
+ // });
+ //
+ // $('.btn-closed-issues').click(function() {
+ // reload_items('closed','issues');
+ // });
+ //
+ // $('.btn-open-issues').click(function() {
+ // reload_items('open','issues');
+ // });
var start = 10;
$(".more-tasks").click(function() {
- more_items('tasks', true);
- });
-
+ more_items('task', true);
+ });
+
$(".more-issues").click(function() {
- more_items('issues', true);
- });
-
+ more_items('issue', true);
+ });
+
$(".more-timelogs").click(function() {
- more_items('timelogs', false);
- });
-
+ more_items('timelog', false);
+ });
+
$(".more-timelines").click(function() {
- more_items('timelines', false);
- });
-
- $( ".project-tasks" ).on('click', '.task-x', function() {
- var item_name = $(this).attr('id');
- close_item('task', item_name);
- });
-
- $( ".project-issues" ).on('click', '.issue-x', function() {
- var item_name = $(this).attr('id');
- close_item('issue', item_name);
- });
-
- var reload_items = function(item_status, item) {
+ more_items('timeline', false);
+ });
+
+
+ var reload_items = function(item_status, item, $btn) {
$.ajax({
method: "GET",
url: "/",
@@ -59,20 +66,28 @@
},
dataType: "json",
success: function(data) {
+ if(typeof data.message == 'undefined') {
+ $('.project-'+ item).html("No "+ item_status +" "+ item);
+ $(".more-"+ item).toggle(false);
+ }
$('.project-'+ item).html(data.message);
-
- $('.project-'+ item +'-section .btn-group .bold').removeClass('bold');
- $('.btn-'+ item_status +'-'+ item).addClass( "bold" );
$(".more-"+ item).toggle(true);
+
+ // update status
+ if(item_status==='open') {
+ $btn.html(__('Show closed')).attr('data-status', 'Open');
+ } else {
+ $btn.html(__('Show open')).attr('data-status', 'Closed');
+ }
}
- });
-
+ });
+
}
-
+
var more_items = function(item, item_status){
if(item_status)
{
- var item_status = $('.project-'+ item +'-section .btn-group .btn-primary').hasClass('btn-closed-'+ item)
+ var item_status = $('.project-'+ item +'-section .btn-group .bold').hasClass('btn-closed-'+ item)
? 'closed' : 'open';
}
$.ajax({
@@ -87,20 +102,21 @@
},
dataType: "json",
success: function(data) {
+
$(data.message).appendTo('.project-'+ item);
- if(typeof data.message == 'undefined') {
- $(".more-"+ item).toggle(false);
+ if(typeof data.message == 'undefined') {
+ $(".more-"+ item).toggle(false);
}
start = start+10;
}
- });
+ });
}
-
+
var close_item = function(item, item_name){
var args = {
project: '{{ doc.name }}',
item_name: item_name,
- }
+ }
frappe.call({
btn: this,
type: "POST",
diff --git a/erpnext/templates/pages/projects.py b/erpnext/templates/pages/projects.py
index 8cec2b7..c2cb6c7 100644
--- a/erpnext/templates/pages/projects.py
+++ b/erpnext/templates/pages/projects.py
@@ -15,11 +15,14 @@
context.issues = frappe.get_all('Issue', filters={'project': project.project_name},
fields=['subject', 'opening_date', 'resolution_date', 'status', 'name', 'resolution_details','modified','modified_by'])
- project.tasks = get_tasks(project.name, start=0, search=frappe.form_dict.get("q"))
+ project.tasks = get_tasks(project.name, start=0, item_status='open',
+ search=frappe.form_dict.get("q"))
- project.timelogs = get_timelogs(project.name, start=0, search=frappe.form_dict.get("q"))
+ project.issues = get_issues(project.name, start=0, item_status='open',
+ search=frappe.form_dict.get("q"))
- project.issues = get_issues(project.name, start=0, search=frappe.form_dict.get("q"))
+ project.timelogs = get_timelogs(project.name, start=0,
+ search=frappe.form_dict.get("q"))
project.timelines = get_timeline(project.project_name, start=0)
@@ -60,36 +63,53 @@
@frappe.whitelist()
def get_timelines_html(project, start=0):
return frappe.render_template("erpnext/templates/includes/projects/timeline.html",
- {"doc": {"timelines": get_timeline(project, start)}}, is_path=True)
+ {"doc": {
+ "timelines": get_timeline(project, start)}
+ }, is_path=True)
def get_issue_list(project):
return [issue.name for issue in get_issues(project)]
+
+
def get_tasks(project, start=0, search=None, item_status=None):
filters = {"project": project}
if search:
filters["subject"] = ("like", "%{0}%".format(search))
if item_status:
- filters = {"status": item_status}
+ filters["status"] = item_status
tasks = frappe.get_all("Task", filters=filters,
- fields=["name", "subject", "status", "exp_start_date", "exp_end_date", "priority"],
+ fields=["name", "subject", "status", "exp_start_date", "exp_end_date", "priority", "_seen"],
limit_start=start, limit_page_length=10)
for task in tasks:
- print task._comments
task.todo = frappe.get_all('ToDo',filters={'reference_name':task.name, 'reference_type':'Task'},
fields=["assigned_by", "owner", "modified", "modified_by"])
+
if task.todo:
task.todo=task.todo[0]
task.todo.user_image = frappe.db.get_value('User', task.todo.owner, 'user_image')
+
if task._comments:
task.comment_count = len(json.loads(task._comments or "[]"))
+
+ task.css_seen = ''
+ if task._seen:
+ if frappe.session.user in json.loads(task._seen):
+ task.css_seen = 'seen'
+
return tasks
@frappe.whitelist()
-def get_tasks_html(project, start=0, item_status=None):
+def get_task_html(project, start=0, item_status=None):
return frappe.render_template("erpnext/templates/includes/projects/project_tasks.html",
- {"doc": {"tasks": get_tasks(project, start, item_status=item_status)}}, is_path=True)
+ {"doc": {
+ "name": project,
+ "project_name": project,
+ "tasks": get_tasks(project, start, item_status=item_status)}
+ }, is_path=True)
+
+
def get_issues(project, start=0, search=None, item_status=None):
@@ -97,7 +117,7 @@
if search:
filters["subject"] = ("like", "%{0}%".format(search))
if item_status:
- filters = {"status": item_status}
+ filters["status"] = item_status
issues = frappe.get_all("Issue", filters=filters,
fields=["name", "subject", "status", "opening_date", "resolution_date", "resolution_details"],
order_by='modified desc',
@@ -113,9 +133,17 @@
return issues
@frappe.whitelist()
-def get_issues_html(project, start=0, item_status=None):
+def get_issue_html(project, start=0, item_status=None):
return frappe.render_template("erpnext/templates/includes/projects/project_issues.html",
- {"doc": {"issues": get_issues(project, start, item_status=item_status)}}, is_path=True)
+ {"doc": {
+ "name": project,
+ "project_name": project,
+ "issues": get_issues(project, start, item_status=item_status)}
+ }, is_path=True)
+
+
+
+
def get_timelogs(project, start=0, search=None):
filters = {"project": project}
@@ -130,19 +158,7 @@
return timelogs
@frappe.whitelist()
-def get_timelogs_html(project, start=0):
+def get_timelog_html(project, start=0):
return frappe.render_template("erpnext/templates/includes/projects/project_timelogs.html",
{"doc": {"timelogs": get_timelogs(project, start)}}, is_path=True)
-@frappe.whitelist()
-def set_task_status(project, item_name):
- task = frappe.get_doc("Task", item_name)
- task.status = 'Closed'
- task.save(ignore_permissions=True)
-
-@frappe.whitelist()
-def set_issue_status(project, item_name):
- issue = frappe.get_doc("Issue", item_name)
- issue.status = 'Closed'
- issue.save(ignore_permissions=True)
-
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
diff --git a/erpnext/utilities/bot.py b/erpnext/utilities/bot.py
new file mode 100644
index 0000000..e1f3d00
--- /dev/null
+++ b/erpnext/utilities/bot.py
@@ -0,0 +1,36 @@
+# Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+
+from __future__ import unicode_literals
+
+from frappe.utils.bot import BotParser
+
+import frappe
+from frappe import _
+
+class FindItemBot(BotParser):
+ def get_reply(self):
+ if self.startswith('where is', 'find item', 'locate'):
+ item = '%{0}%'.format(self.strip_words(self.query, 'where is', 'find item', 'locate'))
+ items = frappe.db.sql('''select name from `tabItem` where item_code like %(txt)s
+ or item_name like %(txt)s or description like %(txt)s''', dict(txt=item))
+
+ if items:
+ out = []
+ warehouses = frappe.get_all("Warehouse")
+ for item in items:
+ found = False
+ for warehouse in warehouses:
+ qty = frappe.db.get_value("Bin", {'item_code': item[0], 'warehouse': warehouse.name}, 'actual_qty')
+ if qty:
+ out.append(_('{0} units of [{1}](#Form/Item/{1}) found in [{2}](#Form/Warehouse/{2})').format(qty,
+ item[0], warehouse.name))
+ found = True
+
+ if not found:
+ out.append(_('[{0}](#Form/Item/{0}) is out of stock').format(item[0]))
+
+ return "\n\n".join(out)
+
+ else:
+ return _("Did not find any item called {0}".format(item))
\ No newline at end of file