frappe_docker/frappe-bench/sites/assets/js/erpnext.min.js
2017-07-31 15:51:51 +05:30

2906 lines
133 KiB
JavaScript

frappe.provide('erpnext');
$(document).bind('toolbar_setup', function () {
frappe.app.name = "ERPNext";
frappe.help_feedback_link = '<p><a class="text-muted" \
href="https://discuss.erpnext.com">Feedback</a></p>';
$('.navbar-home').html('<img class="erpnext-icon" src="' + frappe.urllib.get_base_url() + '/assets/erpnext/images/erp-icon.svg" />');
$('[data-link="docs"]').attr("href", "https://frappe.github.io/erpnext/");
$('[data-link="issues"]').attr("href", "https://github.com/frappe/erpnext/issues");
var $help_menu = $('.dropdown-help ul .documentation-links');
$('<li><a data-link-type="forum" href="https://discuss.erpnext.com" \
target="_blank">' + __('User Forum') + '</a></li>').insertBefore($help_menu);
$('<li><a href="https://gitter.im/frappe/erpnext" \
target="_blank">' + __('Chat') + '</a></li>').insertBefore($help_menu);
$('<li><a href="https://github.com/frappe/erpnext/issues" \
target="_blank">' + __('Report an Issue') + '</a></li>').insertBefore($help_menu);
});
$.extend(frappe.create_routes, {
"Customer Group": "Tree/Customer Group",
"Territory": "Tree/Territory",
"Item Group": "Tree/Item Group",
"Sales Person": "Tree/Sales Person",
"Account": "Tree/Account",
"Cost Center": "Tree/Cost Center"
});
$.extend(frappe.breadcrumbs.preferred, {
"Item Group": "Stock",
"Customer Group": "Selling",
"Supplier Type": "Buying",
"Territory": "Selling",
"Sales Person": "Selling",
"Sales Partner": "Selling",
"Brand": "Selling"
});
frappe.provide("erpnext");
frappe.provide("erpnext.utils");
$.extend(erpnext, {
get_currency: function get_currency(company) {
if (!company && cur_frm) company = cur_frm.doc.company;
if (company) return frappe.get_doc(":Company", company).default_currency || frappe.boot.sysdefaults.currency;else return frappe.boot.sysdefaults.currency;
},
toggle_naming_series: function toggle_naming_series() {
if (cur_frm.fields_dict.naming_series) {
cur_frm.toggle_display("naming_series", cur_frm.doc.__islocal ? true : false);
}
},
hide_company: function hide_company() {
if (cur_frm.fields_dict.company) {
var companies = Object.keys(locals[":Company"] || {});
if (companies.length === 1) {
if (!cur_frm.doc.company) cur_frm.set_value("company", companies[0]);
cur_frm.toggle_display("company", false);
} else if (erpnext.last_selected_company) {
if (!cur_frm.doc.company) cur_frm.set_value("company", erpnext.last_selected_company);
}
}
},
is_perpetual_inventory_enabled: function is_perpetual_inventory_enabled(company) {
if (company) {
return frappe.get_doc(":Company", company).enable_perpetual_inventory;
}
},
setup_serial_no: function setup_serial_no() {
var grid_row = cur_frm.open_grid_row();
if (!grid_row || !grid_row.grid_form.fields_dict.serial_no || grid_row.grid_form.fields_dict.serial_no.get_status() !== "Write") return;
var $btn = $('<button class="btn btn-sm btn-default">' + __("Add Serial No") + '</button>').appendTo($("<div>").css({ "margin-bottom": "10px", "margin-top": "10px" }).appendTo(grid_row.grid_form.fields_dict.serial_no.$wrapper));
$btn.on("click", function () {
var d = new frappe.ui.Dialog({
title: __("Add Serial No"),
fields: [{
"fieldtype": "Link",
"fieldname": "serial_no",
"options": "Serial No",
"label": __("Serial No"),
"get_query": function get_query() {
return {
filters: {
item_code: grid_row.doc.item_code,
warehouse: cur_frm.doc.is_return ? null : grid_row.doc.warehouse
}
};
}
}, {
"fieldtype": "Button",
"fieldname": "add",
"label": __("Add")
}]
});
d.get_input("add").on("click", function () {
var serial_no = d.get_value("serial_no");
if (serial_no) {
var val = (grid_row.doc.serial_no || "").split("\n").concat([serial_no]).join("\n");
grid_row.grid_form.fields_dict.serial_no.set_model_value(val.trim());
}
d.hide();
return false;
});
d.show();
});
}
});
$.extend(erpnext.utils, {
set_party_dashboard_indicators: function set_party_dashboard_indicators(frm) {
if (frm.doc.__onload && frm.doc.__onload.dashboard_info) {
var info = frm.doc.__onload.dashboard_info;
frm.dashboard.add_indicator(__('Annual Billing: {0}', [format_currency(info.billing_this_year, info.currency)]), 'blue');
frm.dashboard.add_indicator(__('Total Unpaid: {0}', [format_currency(info.total_unpaid, info.currency)]), info.total_unpaid ? 'orange' : 'green');
}
},
copy_value_in_all_row: function copy_value_in_all_row(doc, dt, dn, table_fieldname, fieldname) {
var d = locals[dt][dn];
if (d[fieldname]) {
var cl = doc[table_fieldname] || [];
for (var i = 0; i < cl.length; i++) {
if (!cl[i][fieldname]) cl[i][fieldname] = d[fieldname];
}
}
refresh_field(table_fieldname);
},
get_terms: function get_terms(tc_name, doc, _callback) {
if (tc_name) {
return frappe.call({
method: 'erpnext.setup.doctype.terms_and_conditions.terms_and_conditions.get_terms_and_conditions',
args: {
template_name: tc_name,
doc: doc
},
callback: function callback(r) {
_callback(r);
}
});
}
}
});
erpnext.utils.map_current_doc = function (opts) {
if (opts.get_query_filters) {
opts.get_query = function () {
return { filters: opts.get_query_filters };
};
}
var _map = function _map() {
if ($.isArray(cur_frm.doc.items) && cur_frm.doc.items.length > 0) {
if (!cur_frm.doc.items[0].item_code) {
cur_frm.doc.items = cur_frm.doc.items.splice(1);
}
var items_doctype = frappe.meta.get_docfield(cur_frm.doctype, 'items').options;
var link_fieldname = null;
frappe.get_meta(items_doctype).fields.forEach(function (d) {
if (d.options === opts.source_doctype) link_fieldname = d.fieldname;
});
var already_set = false;
var item_qty_map = {};
$.each(cur_frm.doc.items, function (i, d) {
opts.source_name.forEach(function (src) {
if (d[link_fieldname] == src) {
already_set = true;
if (item_qty_map[d.item_code]) item_qty_map[d.item_code] += flt(d.qty);else item_qty_map[d.item_code] = flt(d.qty);
}
});
});
if (already_set) {
opts.source_name.forEach(function (src) {
frappe.model.with_doc(opts.source_doctype, src, function (r) {
var source_doc = frappe.model.get_doc(opts.source_doctype, src);
$.each(source_doc.items || [], function (i, row) {
if (row.qty > flt(item_qty_map[row.item_code])) {
already_set = false;
return false;
}
});
});
if (already_set) {
frappe.msgprint(__("You have already selected items from {0} {1}", [opts.source_doctype, src]));
return;
}
});
}
}
return frappe.call({
type: "POST",
method: 'frappe.model.mapper.map_docs',
args: {
"method": opts.method,
"source_names": opts.source_name,
"target_doc": cur_frm.doc
},
callback: function callback(r) {
if (!r.exc) {
var doc = frappe.model.sync(r.message);
cur_frm.refresh();
}
}
});
};
if (opts.source_doctype) {
var d = new frappe.ui.form.MultiSelectDialog({
doctype: opts.source_doctype,
target: opts.target,
date_field: opts.date_field || undefined,
setters: opts.setters,
get_query: opts.get_query,
action: function action(selections, args) {
var values = selections;
if (values.length === 0) {
frappe.msgprint(__("Please select Quotations"));
return;
}
opts.source_name = values;
opts.setters = args;
d.dialog.hide();
_map();
}
});
} else if (opts.source_name) {
opts.source_name = [opts.source_name];
_map();
}
};
frappe.form.link_formatters['Item'] = function (value, doc) {
if (doc && doc.item_name && doc.item_name !== value) {
return value ? value + ': ' + doc.item_name : doc.item_name;
} else {
return value;
}
};
frappe.form.link_formatters['Employee'] = function (value, doc) {
if (doc && doc.employee_name && doc.employee_name !== value) {
return value ? value + ': ' + doc.employee_name : doc.employee_name;
} else {
return value;
}
};
$(document).on('app_ready', function () {
if (!frappe.datetime.is_timezone_same()) {
$.each(["Stock Reconciliation", "Stock Entry", "Stock Ledger Entry", "Delivery Note", "Purchase Receipt", "Sales Invoice"], function (i, d) {
frappe.ui.form.on(d, "onload", function (frm) {
cur_frm.set_df_property("posting_time", "description", frappe.sys_defaults.time_zone);
});
});
}
});
frappe.provide("erpnext.queries");
$.extend(erpnext.queries, {
user: function user() {
return { query: "frappe.core.doctype.user.user.user_query" };
},
lead: function lead() {
return { query: "erpnext.controllers.queries.lead_query" };
},
customer: function customer() {
return { query: "erpnext.controllers.queries.customer_query" };
},
supplier: function supplier() {
return { query: "erpnext.controllers.queries.supplier_query" };
},
item: function item(filters) {
var args = { query: "erpnext.controllers.queries.item_query" };
if (filters) args["filters"] = filters;
return args;
},
bom: function bom() {
return { query: "erpnext.controllers.queries.bom" };
},
task: function task() {
return { query: "erpnext.projects.utils.query_task" };
},
customer_filter: function customer_filter(doc) {
if (!doc.customer) {
frappe.throw(__("Please set {0}", [__(frappe.meta.get_label(doc.doctype, "customer", doc.name))]));
}
return { filters: { customer: doc.customer } };
},
contact_query: function contact_query(doc) {
if (frappe.dynamic_link) {
if (!doc[frappe.dynamic_link.fieldname]) {
frappe.throw(__("Please set {0}", [__(frappe.meta.get_label(doc.doctype, frappe.dynamic_link.fieldname, doc.name))]));
}
return {
query: 'frappe.contacts.doctype.contact.contact.contact_query',
filters: {
link_doctype: frappe.dynamic_link.doctype,
link_name: doc[frappe.dynamic_link.fieldname]
}
};
}
},
address_query: function address_query(doc) {
if (frappe.dynamic_link) {
if (!doc[frappe.dynamic_link.fieldname]) {
frappe.throw(__("Please set {0}", [__(frappe.meta.get_label(doc.doctype, frappe.dynamic_link.fieldname, doc.name))]));
}
return {
query: 'frappe.contacts.doctype.address.address.address_query',
filters: {
link_doctype: frappe.dynamic_link.doctype,
link_name: doc[frappe.dynamic_link.fieldname]
}
};
}
},
company_address_query: function company_address_query(doc) {
return {
query: 'frappe.contacts.doctype.address.address.address_query',
filters: { is_your_company_address: 1, link_doctype: 'Company', link_name: doc.company || '' }
};
},
supplier_filter: function supplier_filter(doc) {
if (!doc.supplier) {
frappe.throw(__("Please set {0}", [__(frappe.meta.get_label(doc.doctype, "supplier", doc.name))]));
}
return { filters: { supplier: doc.supplier } };
},
lead_filter: function lead_filter(doc) {
if (!doc.lead) {
frappe.throw(__("Please specify a {0}", [__(frappe.meta.get_label(doc.doctype, "lead", doc.name))]));
}
return { filters: { lead: doc.lead } };
},
not_a_group_filter: function not_a_group_filter() {
return { filters: { is_group: 0 } };
},
employee: function employee() {
return { query: "erpnext.controllers.queries.employee_query" };
},
warehouse: function warehouse(doc) {
return {
filters: [["Warehouse", "company", "in", ["", cstr(doc.company)]], ["Warehouse", "is_group", "=", 0]]
};
}
});
erpnext.queries.setup_queries = function (frm, options, query_fn) {
var me = this;
var set_query = function set_query(doctype, parentfield) {
var link_fields = frappe.meta.get_docfields(doctype, frm.doc.name, { "fieldtype": "Link", "options": options });
$.each(link_fields, function (i, df) {
if (parentfield) {
frm.set_query(df.fieldname, parentfield, query_fn);
} else {
frm.set_query(df.fieldname, query_fn);
}
});
};
set_query(frm.doc.doctype);
$.each(frappe.meta.get_docfields(frm.doc.doctype, frm.doc.name, { "fieldtype": "Table" }), function (i, df) {
set_query(df.options, df.fieldname);
});
};
erpnext.queries.setup_warehouse_query = function (frm) {
frm.set_query('warehouse', 'items', function (doc, cdt, cdn) {
var row = locals[cdt][cdn];
var filters = erpnext.queries.warehouse(frm.doc);
if (row.item_code) {
$.extend(filters, { "query": "erpnext.controllers.queries.warehouse_query" });
filters["filters"].push(["Bin", "item_code", "=", row.item_code]);
}
return filters;
});
};
erpnext.SMSManager = function SMSManager(doc) {
var me = this;
this.setup = function () {
var default_msg = {
'Lead': '',
'Opportunity': 'Your enquiry has been logged into the system. Ref No: ' + doc.name,
'Quotation': 'Quotation ' + doc.name + ' has been sent via email. Thanks!',
'Sales Order': 'Sales Order ' + doc.name + ' has been created against ' + (doc.quotation_no ? 'Quote No:' + doc.quotation_no : '') + (doc.po_no ? ' for your PO: ' + doc.po_no : ''),
'Delivery Note': 'Items has been delivered against delivery note: ' + doc.name + (doc.po_no ? ' for your PO: ' + doc.po_no : ''),
'Sales Invoice': 'Invoice ' + doc.name + ' has been sent via email ' + (doc.po_no ? ' for your PO: ' + doc.po_no : ''),
'Material Request': 'Material Request ' + doc.name + ' has been raised in the system',
'Purchase Order': 'Purchase Order ' + doc.name + ' has been sent via email',
'Purchase Receipt': 'Items has been received against purchase receipt: ' + doc.name
};
if (in_list(['Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice'], doc.doctype)) this.show(doc.contact_person, 'Customer', doc.customer, '', default_msg[doc.doctype]);else if (in_list(['Purchase Order', 'Purchase Receipt'], doc.doctype)) this.show(doc.contact_person, 'Supplier', doc.supplier, '', default_msg[doc.doctype]);else if (doc.doctype == 'Lead') this.show('', '', '', doc.mobile_no, default_msg[doc.doctype]);else if (doc.doctype == 'Opportunity') this.show('', '', '', doc.contact_no, default_msg[doc.doctype]);else if (doc.doctype == 'Material Request') this.show('', '', '', '', default_msg[doc.doctype]);
};
this.get_contact_number = function (contact, ref_doctype, ref_name) {
frappe.call({
method: "erpnext.setup.doctype.sms_settings.sms_settings.get_contact_number",
args: {
contact_name: contact,
ref_doctype: ref_doctype,
ref_name: ref_name
},
callback: function callback(r) {
if (r.exc) {
frappe.msgprint(r.exc);return;
}
me.number = r.message;
me.show_dialog();
}
});
};
this.show = function (contact, ref_doctype, ref_name, mobile_nos, message) {
this.message = message;
if (mobile_nos) {
me.number = mobile_nos;
me.show_dialog();
} else if (contact) {
this.get_contact_number(contact, ref_doctype, ref_name);
} else {
me.show_dialog();
}
};
this.show_dialog = function () {
if (!me.dialog) me.make_dialog();
me.dialog.set_values({
'message': me.message,
'number': me.number
});
me.dialog.show();
};
this.make_dialog = function () {
var d = new frappe.ui.Dialog({
title: 'Send SMS',
width: 400,
fields: [{ fieldname: 'number', fieldtype: 'Data', label: 'Mobile Number', reqd: 1 }, { fieldname: 'message', fieldtype: 'Text', label: 'Message', reqd: 1 }, { fieldname: 'send', fieldtype: 'Button', label: 'Send' }]
});
d.fields_dict.send.input.onclick = function () {
var btn = d.fields_dict.send.input;
var v = me.dialog.get_values();
if (v) {
$(btn).set_working();
frappe.call({
method: "erpnext.setup.doctype.sms_settings.sms_settings.send_sms",
args: {
receiver_list: [v.number],
msg: v.message
},
callback: function callback(r) {
$(btn).done_working();
if (r.exc) {
frappe.msgprint(r.exc);return;
}
me.dialog.hide();
}
});
}
};
this.dialog = d;
};
this.setup();
};
frappe.provide("erpnext.utils");
erpnext.utils.get_party_details = function (frm, method, args, _callback) {
if (!method) {
method = "erpnext.accounts.party.get_party_details";
}
if (!args) {
if (frm.doctype != "Purchase Order" && frm.doc.customer) {
args = {
party: frm.doc.customer,
party_type: "Customer",
price_list: frm.doc.selling_price_list
};
} else if (frm.doc.supplier) {
args = {
party: frm.doc.supplier,
party_type: "Supplier",
price_list: frm.doc.buying_price_list
};
}
if (args) {
args.posting_date = frm.doc.posting_date || frm.doc.transaction_date;
}
}
if (!args) return;
if (frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
if (!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date", args.posting_date, args.party_type == "Customer" ? "customer" : "supplier")) return;
}
args.currency = frm.doc.currency;
args.company = frm.doc.company;
args.doctype = frm.doc.doctype;
frappe.call({
method: method,
args: args,
callback: function callback(r) {
if (r.message) {
frm.updating_party_details = true;
frappe.run_serially([function () {
return frm.set_value(r.message);
}, function () {
frm.updating_party_details = false;
if (_callback) _callback();
frm.refresh();
erpnext.utils.add_item(frm);
}]);
}
}
});
};
erpnext.utils.add_item = function (frm) {
if (frm.is_new()) {
var prev_route = frappe.get_prev_route();
if (prev_route[1] === 'Item' && !(frm.doc.items && frm.doc.items.length)) {
var item = frm.add_child('items');
frm.refresh_field('items');
frappe.model.set_value(item.doctype, item.name, 'item_code', prev_route[2]);
}
}
};
erpnext.utils.get_address_display = function (frm, address_field, display_field, is_your_company_address) {
if (frm.updating_party_details) return;
if (!address_field) {
if (frm.doctype != "Purchase Order" && frm.doc.customer) {
address_field = "customer_address";
} else if (frm.doc.supplier) {
address_field = "supplier_address";
} else return;
}
if (!display_field) display_field = "address_display";
if (frm.doc[address_field]) {
frappe.call({
method: "frappe.contacts.doctype.address.address.get_address_display",
args: { "address_dict": frm.doc[address_field] },
callback: function callback(r) {
if (r.message) {
frm.set_value(display_field, r.message);
}
erpnext.utils.set_taxes(frm, address_field, display_field, is_your_company_address);
}
});
} else {
frm.set_value(display_field, '');
}
};
erpnext.utils.set_taxes = function (frm, address_field, display_field, is_your_company_address) {
if (frappe.meta.get_docfield(frm.doc.doctype, "taxes") && !is_your_company_address) {
if (!erpnext.utils.validate_mandatory(frm, "Lead/Customer/Supplier", frm.doc.customer || frm.doc.supplier || frm.doc.lead, address_field)) {
return;
}
if (!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date", frm.doc.posting_date || frm.doc.transaction_date, address_field)) {
return;
}
} else {
return;
}
var party_type, party;
if (frm.doc.lead) {
party_type = 'Lead';
party = frm.doc.lead;
} else if (frm.doc.customer) {
party_type = 'Customer';
party = frm.doc.customer;
} else if (frm.doc.supplier) {
party_type = 'Supplier';
party = frm.doc.supplier;
}
frappe.call({
method: "erpnext.accounts.party.set_taxes",
args: {
"party": party,
"party_type": party_type,
"posting_date": frm.doc.posting_date || frm.doc.transaction_date,
"company": frm.doc.company,
"billing_address": frm.doc.customer || frm.doc.lead ? frm.doc.customer_address : frm.doc.supplier_address,
"shipping_address": frm.doc.shipping_address_name
},
callback: function callback(r) {
if (r.message) {
frm.set_value("taxes_and_charges", r.message);
}
}
});
};
erpnext.utils.get_contact_details = function (frm) {
if (frm.updating_party_details) return;
if (frm.doc["contact_person"]) {
frappe.call({
method: "frappe.contacts.doctype.contact.contact.get_contact_details",
args: { contact: frm.doc.contact_person },
callback: function callback(r) {
if (r.message) frm.set_value(r.message);
}
});
}
};
erpnext.utils.validate_mandatory = function (frm, label, value, trigger_on) {
if (!value) {
frm.doc[trigger_on] = "";
refresh_field(trigger_on);
frappe.msgprint(__("Please enter {0} first", [label]));
return false;
}
return true;
};
erpnext.utils.get_shipping_address = function (frm, _callback2) {
frappe.call({
method: "frappe.contacts.doctype.address.address.get_shipping_address",
args: { company: frm.doc.company },
callback: function callback(r) {
if (r.message) {
frm.set_value("shipping_address", r.message[0]);
frm.set_value("shipping_address_display", r.message[1]);
}
if (_callback2) {
return _callback2();
}
}
});
};frappe.templates['address_list'] = '<div class="clearfix"></div> {% for(var i=0, l=addr_list.length; i<l; i++) { %} <div class="address-box"> <p class="h6"> {%= i+1 %}. {%= addr_list[i].address_type!="Other" ? __(addr_list[i].address_type) : addr_list[i].address_title %} {% if(addr_list[i].is_primary_address) { %} <span class="text-muted">({%= __("Primary") %})</span>{% } %} {% if(addr_list[i].is_shipping_address) { %} <span class="text-muted">({%= __("Shipping") %})</span>{% } %} <a href="#Form/Address/{%= encodeURIComponent(addr_list[i].name) %}" class="btn btn-default btn-xs pull-right" style="margin-top:-3px; margin-right: -5px;"> {%= __("Edit") %}</a> </p> <p>{%= addr_list[i].display %}</p> </div> {% } %} {% if(!addr_list.length) { %} <p class="text-muted small">{%= __("No address added yet.") %}</p> {% } %} <p><button class="btn btn-xs btn-default btn-address">{{ __("New Address") }}</button></p> ';
frappe.templates['contact_list'] = '<div class="clearfix"></div> {% for(var i=0, l=contact_list.length; i<l; i++) { %} <div class="address-box"> <p class="h6"> {%= contact_list[i].first_name %} {%= contact_list[i].last_name %} {% if(contact_list[i].is_primary_contact) { %} <span class="text-muted">({%= __("Primary") %})</span> {% } %} {% if(contact_list[i].designation){ %} <span class="text-muted">&ndash; {%= contact_list[i].designation %}</span> {% } %} <a href="#Form/Contact/{%= encodeURIComponent(contact_list[i].name) %}" class="btn btn-xs btn-default pull-right" style="margin-top:-3px; margin-right: -5px;"> {%= __("Edit") %}</a> </p> {% if (contact_list[i].phone || contact_list[i].mobile_no || contact_list[i].email_id) { %} <p> {% if(contact_list[i].phone) { %} {%= __("Phone") %}: {%= contact_list[i].phone %}<br> {% } %} {% if(contact_list[i].mobile_no) { %} {%= __("Mobile No.") %}: {%= contact_list[i].mobile_no %}<br> {% } %} {% if(contact_list[i].email_id) { %} {%= __("Email Address") %}: {%= contact_list[i].email_id %} {% } %} </p> {% endif %} </div> {% } %} {% if(!contact_list.length) { %} <p class="text-muted small">{%= __("No contacts added yet.") %}</p> {% } %} <p><button class="btn btn-xs btn-default btn-contact"> {{ __("New Contact") }}</button> </p>';
frappe.provide("erpnext.stock");
erpnext.stock.StockController = frappe.ui.form.Controller.extend({
onload: function onload() {
if (this.frm.fields_dict.company) {
this.setup_warehouse_query();
}
},
setup_warehouse_query: function setup_warehouse_query() {
var me = this;
erpnext.queries.setup_queries(this.frm, "Warehouse", function () {
return erpnext.queries.warehouse(me.frm.doc);
});
},
setup_posting_date_time_check: function setup_posting_date_time_check() {
frappe.ui.form.on(this.frm.doctype, 'set_posting_date_and_time_read_only', function (frm) {
if (frm.doc.docstatus == 0 && frm.doc.set_posting_time) {
frm.set_df_property('posting_date', 'read_only', 0);
frm.set_df_property('posting_time', 'read_only', 0);
} else {
frm.set_df_property('posting_date', 'read_only', 1);
frm.set_df_property('posting_time', 'read_only', 1);
}
});
frappe.ui.form.on(this.frm.doctype, 'set_posting_time', function (frm) {
frm.trigger('set_posting_date_and_time_read_only');
});
frappe.ui.form.on(this.frm.doctype, 'refresh', function (frm) {
if (frm.doc.docstatus == 0) {
if (!frm.doc.posting_date) {
frm.set_value('posting_date', frappe.datetime.nowdate());
}
if (!frm.doc.posting_time) {
frm.set_value('posting_time', frappe.datetime.now_time());
}
frm.trigger('set_posting_date_and_time_read_only');
}
});
},
show_stock_ledger: function show_stock_ledger() {
var me = this;
if (this.frm.doc.docstatus === 1) {
cur_frm.add_custom_button(__("Stock Ledger"), function () {
frappe.route_options = {
voucher_no: me.frm.doc.name,
from_date: me.frm.doc.posting_date,
to_date: me.frm.doc.posting_date,
company: me.frm.doc.company
};
frappe.set_route("query-report", "Stock Ledger");
}, __("View"));
}
},
show_general_ledger: function show_general_ledger() {
var me = this;
if (this.frm.doc.docstatus === 1) {
cur_frm.add_custom_button(__('Accounting Ledger'), function () {
frappe.route_options = {
voucher_no: me.frm.doc.name,
from_date: me.frm.doc.posting_date,
to_date: me.frm.doc.posting_date,
company: me.frm.doc.company,
group_by_voucher: false
};
frappe.set_route("query-report", "General Ledger");
}, __("View"));
}
}
});
erpnext.payments = erpnext.stock.StockController.extend({
make_payment: function make_payment() {
var me = this;
this.dialog = new frappe.ui.Dialog({
title: 'Payment'
});
this.dialog.show();
this.$body = this.dialog.body;
this.set_payment_primary_action();
this.make_keyboard();
this.select_text();
},
select_text: function select_text() {
var me = this;
$(this.$body).find('.form-control').click(function () {
$(this).select();
});
},
set_payment_primary_action: function set_payment_primary_action() {
var me = this;
this.dialog.set_primary_action(__("Submit"), function () {
me.dialog.hide();
me.submit_invoice();
});
},
make_keyboard: function make_keyboard() {
var me = this;
$(this.$body).empty();
$(this.$body).html(frappe.render_template('pos_payment', this.frm.doc));
this.show_payment_details();
this.bind_keyboard_event();
this.clear_amount();
},
make_multimode_payment: function make_multimode_payment() {
var me = this;
if (this.frm.doc.change_amount > 0) {
me.payment_val = me.doc.outstanding_amount;
}
this.payments = frappe.model.add_child(this.frm.doc, 'Multi Mode Payment', "payments");
this.payments.mode_of_payment = this.dialog.fields_dict.mode_of_payment.get_value();
this.payments.amount = flt(this.payment_val);
},
show_payment_details: function show_payment_details() {
var me = this;
var multimode_payments = $(this.$body).find('.multimode-payments').empty();
if (this.frm.doc.payments.length) {
$.each(this.frm.doc.payments, function (index, data) {
$(frappe.render_template('payment_details', {
mode_of_payment: data.mode_of_payment,
amount: data.amount,
idx: data.idx,
currency: me.frm.doc.currency,
type: data.type
})).appendTo(multimode_payments);
if (data.type == 'Cash' && data.amount == me.frm.doc.paid_amount) {
me.idx = data.idx;
me.selected_mode = $(me.$body).find(repl("input[idx='%(idx)s']", { 'idx': me.idx }));
me.highlight_selected_row();
me.bind_amount_change_event();
}
});
} else {
$("<p>No payment mode selected in pos profile</p>").appendTo(multimode_payments);
}
},
set_outstanding_amount: function set_outstanding_amount() {
this.selected_mode = $(this.$body).find(repl("input[idx='%(idx)s']", { 'idx': this.idx }));
this.highlight_selected_row();
this.payment_val = 0.0;
if (this.frm.doc.outstanding_amount > 0 && flt(this.selected_mode.val()) == 0.0) {
this.payment_val = flt(this.frm.doc.outstanding_amount / this.frm.doc.conversion_rate, precision("outstanding_amount"));
this.selected_mode.val(format_currency(this.payment_val, this.frm.doc.currency));
this.update_payment_amount();
} else if (flt(this.selected_mode.val()) > 0) {
this.payment_val = flt(this.selected_mode.val());
}
this.selected_mode.select();
this.bind_amount_change_event();
},
bind_keyboard_event: function bind_keyboard_event() {
var me = this;
this.payment_val = '';
this.bind_form_control_event();
this.bind_numeric_keys_event();
},
bind_form_control_event: function bind_form_control_event() {
var me = this;
$(this.$body).find('.pos-payment-row').click(function () {
me.idx = $(this).attr("idx");
me.set_outstanding_amount();
});
$(this.$body).find('.form-control').click(function () {
me.idx = $(this).attr("idx");
me.set_outstanding_amount();
me.update_paid_amount(true);
});
$(this.$body).find('.write_off_amount').change(function () {
me.write_off_amount(flt($(this).val()), precision("write_off_amount"));
});
$(this.$body).find('.change_amount').change(function () {
me.change_amount(flt($(this).val()), precision("change_amount"));
});
},
highlight_selected_row: function highlight_selected_row() {
var me = this;
var selected_row = $(this.$body).find(repl(".pos-payment-row[idx='%(idx)s']", { 'idx': this.idx }));
$(this.$body).find('.pos-payment-row').removeClass('selected-payment-mode');
selected_row.addClass('selected-payment-mode');
$(this.$body).find('.amount').attr('disabled', true);
this.selected_mode.attr('disabled', false);
},
bind_numeric_keys_event: function bind_numeric_keys_event() {
var me = this;
$(this.$body).find('.pos-keyboard-key').click(function () {
me.payment_val += $(this).text();
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency));
me.idx = me.selected_mode.attr("idx");
me.update_paid_amount();
});
$(this.$body).find('.delete-btn').click(function () {
me.payment_val = cstr(flt(me.selected_mode.val())).slice(0, -1);
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency));
me.idx = me.selected_mode.attr("idx");
me.update_paid_amount();
});
},
bind_amount_change_event: function bind_amount_change_event() {
var me = this;
this.selected_mode.change(function () {
me.payment_val = flt($(this).val()) || 0.0;
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency));
me.idx = me.selected_mode.attr("idx");
me.update_payment_amount();
});
},
clear_amount: function clear_amount() {
var me = this;
$(this.$body).find('.clr').click(function (e) {
e.stopPropagation();
me.idx = $(this).attr("idx");
me.selected_mode = $(me.$body).find(repl("input[idx='%(idx)s']", { 'idx': me.idx }));
me.payment_val = 0.0;
me.selected_mode.val(0.0);
me.highlight_selected_row();
me.update_payment_amount();
});
},
write_off_amount: function write_off_amount(_write_off_amount) {
var me = this;
this.frm.doc.write_off_amount = flt(_write_off_amount, precision("write_off_amount"));
this.frm.doc.base_write_off_amount = flt(this.frm.doc.write_off_amount * this.frm.doc.conversion_rate, precision("base_write_off_amount"));
this.calculate_outstanding_amount(false);
this.show_amounts();
},
change_amount: function change_amount(_change_amount) {
var me = this;
this.frm.doc.change_amount = flt(_change_amount, precision("change_amount"));
this.calculate_write_off_amount();
this.show_amounts();
},
update_paid_amount: function update_paid_amount(update_write_off) {
var me = this;
if (in_list(['change_amount', 'write_off_amount'], this.idx)) {
var value = me.selected_mode.val();
if (me.idx == 'change_amount') {
me.change_amount(value);
} else {
if (flt(value) == 0 && update_write_off && me.frm.doc.outstanding_amount > 0) {
value = flt(me.frm.doc.outstanding_amount / me.frm.doc.conversion_rate, precision(me.idx));
}
me.write_off_amount(value);
}
} else {
this.update_payment_amount();
}
},
update_payment_amount: function update_payment_amount() {
var me = this;
$.each(this.frm.doc.payments, function (index, data) {
if (cint(me.idx) == cint(data.idx)) {
data.amount = flt(me.selected_mode.val(), 2);
}
});
this.calculate_outstanding_amount(false);
this.show_amounts();
},
show_amounts: function show_amounts() {
var me = this;
$(this.$body).find(".write_off_amount").val(format_currency(this.frm.doc.write_off_amount, this.frm.doc.currency));
$(this.$body).find('.paid_amount').text(format_currency(this.frm.doc.paid_amount, this.frm.doc.currency));
$(this.$body).find('.change_amount').val(format_currency(this.frm.doc.change_amount, this.frm.doc.currency));
$(this.$body).find('.outstanding_amount').text(format_currency(this.frm.doc.outstanding_amount, frappe.get_doc(":Company", this.frm.doc.company).default_currency));
this.update_invoice();
}
});
erpnext.taxes_and_totals = erpnext.payments.extend({
setup: function setup() {},
apply_pricing_rule_on_item: function apply_pricing_rule_on_item(item) {
if (item.margin_type == "Percentage") {
item.rate_with_margin = flt(item.price_list_rate) + flt(item.price_list_rate) * (flt(item.margin_rate_or_amount) / 100);
} else {
item.rate_with_margin = flt(item.price_list_rate) + flt(item.margin_rate_or_amount);
}
item.rate = flt(item.rate_with_margin, precision("rate", item));
if (item.discount_percentage) {
var discount_value = flt(item.rate_with_margin) * flt(item.discount_percentage) / 100;
item.rate = flt(item.rate_with_margin - discount_value, precision('rate', item));
}
},
calculate_taxes_and_totals: function calculate_taxes_and_totals(update_paid_amount) {
this.discount_amount_applied = false;
this._calculate_taxes_and_totals();
this.calculate_discount_amount();
if (in_list(["Sales Invoice", "Purchase Invoice"], this.frm.doc.doctype) && this.frm.doc.docstatus < 2 && !this.frm.doc.is_return) {
this.calculate_total_advance(update_paid_amount);
}
if (in_list(["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"], this.frm.doc.doctype)) {
this.calculate_commission();
this.calculate_contribution();
}
this.frm.refresh_fields();
},
calculate_discount_amount: function calculate_discount_amount() {
if (frappe.meta.get_docfield(this.frm.doc.doctype, "discount_amount")) {
this.set_discount_amount();
this.apply_discount_amount();
}
},
_calculate_taxes_and_totals: function _calculate_taxes_and_totals() {
this.validate_conversion_rate();
this.calculate_item_values();
this.initialize_taxes();
this.determine_exclusive_rate();
this.calculate_net_total();
this.calculate_taxes();
this.manipulate_grand_total_for_inclusive_tax();
this.calculate_totals();
this._cleanup();
},
validate_conversion_rate: function validate_conversion_rate() {
this.frm.doc.conversion_rate = flt(this.frm.doc.conversion_rate, cur_frm ? precision("conversion_rate") : 9);
var conversion_rate_label = frappe.meta.get_label(this.frm.doc.doctype, "conversion_rate", this.frm.doc.name);
var company_currency = this.frm.doc.currency || this.get_company_currency();
if (!this.frm.doc.conversion_rate) {
if (this.frm.doc.currency == company_currency) {
this.frm.set_value("conversion_rate", 1);
} else {
frappe.throw(repl('%(conversion_rate_label)s' + __(' is mandatory. Maybe Currency Exchange record is not created for ') + '%(from_currency)s' + __(" to ") + '%(to_currency)s', {
"conversion_rate_label": conversion_rate_label,
"from_currency": this.frm.doc.currency,
"to_currency": company_currency
}));
}
}
},
calculate_item_values: function calculate_item_values() {
var me = this;
if (!this.discount_amount_applied) {
$.each(this.frm.doc["items"] || [], function (i, item) {
frappe.model.round_floats_in(item);
item.net_rate = item.rate;
item.amount = flt(item.rate * item.qty, precision("amount", item));
item.net_amount = item.amount;
item.item_tax_amount = 0.0;
me.set_in_company_currency(item, ["price_list_rate", "rate", "amount", "net_rate", "net_amount"]);
});
}
},
set_in_company_currency: function set_in_company_currency(doc, fields) {
var me = this;
$.each(fields, function (i, f) {
doc["base_" + f] = flt(flt(doc[f], precision(f, doc)) * me.frm.doc.conversion_rate, precision("base_" + f, doc));
});
},
initialize_taxes: function initialize_taxes() {
var me = this;
$.each(this.frm.doc["taxes"] || [], function (i, tax) {
tax.item_wise_tax_detail = {};
var tax_fields = ["total", "tax_amount_after_discount_amount", "tax_amount_for_current_item", "grand_total_for_current_item", "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"];
if (cstr(tax.charge_type) != "Actual" && !(me.discount_amount_applied && me.frm.doc.apply_discount_on == "Grand Total")) {
tax_fields.push("tax_amount");
}
$.each(tax_fields, function (i, fieldname) {
tax[fieldname] = 0.0;
});
if (!this.discount_amount_applied && cur_frm) {
cur_frm.cscript.validate_taxes_and_charges(tax.doctype, tax.name);
me.validate_inclusive_tax(tax);
}
frappe.model.round_floats_in(tax);
});
},
determine_exclusive_rate: function determine_exclusive_rate() {
var me = this;
var has_inclusive_tax = false;
$.each(me.frm.doc["taxes"] || [], function (i, row) {
if (cint(row.included_in_print_rate)) has_inclusive_tax = true;
});
if (has_inclusive_tax == false) return;
$.each(me.frm.doc["items"] || [], function (n, item) {
var item_tax_map = me._load_item_tax_rate(item.item_tax_rate);
var cumulated_tax_fraction = 0.0;
$.each(me.frm.doc["taxes"] || [], function (i, tax) {
tax.tax_fraction_for_current_item = me.get_current_tax_fraction(tax, item_tax_map);
if (i == 0) {
tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item;
} else {
tax.grand_total_fraction_for_current_item = me.frm.doc["taxes"][i - 1].grand_total_fraction_for_current_item + tax.tax_fraction_for_current_item;
}
cumulated_tax_fraction += tax.tax_fraction_for_current_item;
});
if (cumulated_tax_fraction && !me.discount_amount_applied) {
item.net_amount = flt(item.amount / (1 + cumulated_tax_fraction), precision("net_amount", item));
item.net_rate = flt(item.net_amount / item.qty, precision("net_rate", item));
me.set_in_company_currency(item, ["net_rate", "net_amount"]);
}
});
},
get_current_tax_fraction: function get_current_tax_fraction(tax, item_tax_map) {
var current_tax_fraction = 0.0;
if (cint(tax.included_in_print_rate)) {
var tax_rate = this._get_tax_rate(tax, item_tax_map);
if (tax.charge_type == "On Net Total") {
current_tax_fraction = tax_rate / 100.0;
} else if (tax.charge_type == "On Previous Row Amount") {
current_tax_fraction = tax_rate / 100.0 * this.frm.doc["taxes"][cint(tax.row_id) - 1].tax_fraction_for_current_item;
} else if (tax.charge_type == "On Previous Row Total") {
current_tax_fraction = tax_rate / 100.0 * this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_fraction_for_current_item;
}
}
if (tax.add_deduct_tax) {
current_tax_fraction *= tax.add_deduct_tax == "Deduct" ? -1.0 : 1.0;
}
return current_tax_fraction;
},
_get_tax_rate: function _get_tax_rate(tax, item_tax_map) {
return Object.keys(item_tax_map).indexOf(tax.account_head) != -1 ? flt(item_tax_map[tax.account_head], precision("rate", tax)) : tax.rate;
},
calculate_net_total: function calculate_net_total() {
var me = this;
this.frm.doc.total = this.frm.doc.base_total = this.frm.doc.net_total = this.frm.doc.base_net_total = 0.0;
$.each(this.frm.doc["items"] || [], function (i, item) {
me.frm.doc.total += item.amount;
me.frm.doc.base_total += item.base_amount;
me.frm.doc.net_total += item.net_amount;
me.frm.doc.base_net_total += item.base_net_amount;
});
frappe.model.round_floats_in(this.frm.doc, ["total", "base_total", "net_total", "base_net_total"]);
},
calculate_taxes: function calculate_taxes() {
var me = this;
var actual_tax_dict = {};
$.each(this.frm.doc["taxes"] || [], function (i, tax) {
if (tax.charge_type == "Actual") {
actual_tax_dict[tax.idx] = flt(tax.tax_amount, precision("tax_amount", tax));
}
});
$.each(this.frm.doc["items"] || [], function (n, item) {
var item_tax_map = me._load_item_tax_rate(item.item_tax_rate);
$.each(me.frm.doc["taxes"] || [], function (i, tax) {
var current_tax_amount = me.get_current_tax_amount(item, tax, item_tax_map);
if (tax.charge_type == "Actual") {
actual_tax_dict[tax.idx] -= current_tax_amount;
if (n == me.frm.doc["items"].length - 1) {
current_tax_amount += actual_tax_dict[tax.idx];
}
}
if (tax.charge_type != "Actual" && !(me.discount_amount_applied && me.frm.doc.apply_discount_on == "Grand Total")) {
tax.tax_amount += current_tax_amount;
}
tax.tax_amount_for_current_item = current_tax_amount;
tax.tax_amount_after_discount_amount += current_tax_amount;
if (tax.category) {
current_tax_amount = tax.category == "Valuation" ? 0.0 : current_tax_amount;
current_tax_amount *= tax.add_deduct_tax == "Deduct" ? -1.0 : 1.0;
}
if (i == 0) {
tax.grand_total_for_current_item = flt(item.net_amount + current_tax_amount, precision("total", tax));
} else {
tax.grand_total_for_current_item = flt(me.frm.doc["taxes"][i - 1].grand_total_for_current_item + current_tax_amount, precision("total", tax));
}
tax.total += tax.grand_total_for_current_item;
if (n == me.frm.doc["items"].length - 1) {
me.round_off_totals(tax);
if (i == me.frm.doc["taxes"].length - 1 && me.discount_amount_applied && me.frm.doc.apply_discount_on == "Grand Total" && me.frm.doc.discount_amount) me.adjust_discount_amount_loss(tax);
}
});
});
},
_load_item_tax_rate: function _load_item_tax_rate(item_tax_rate) {
return item_tax_rate ? JSON.parse(item_tax_rate) : {};
},
get_current_tax_amount: function get_current_tax_amount(item, tax, item_tax_map) {
var tax_rate = this._get_tax_rate(tax, item_tax_map);
var current_tax_amount = 0.0;
if (tax.charge_type == "Actual") {
var actual = flt(tax.tax_amount, precision("tax_amount", tax));
current_tax_amount = this.frm.doc.net_total ? item.net_amount / this.frm.doc.net_total * actual : 0.0;
} else if (tax.charge_type == "On Net Total") {
current_tax_amount = tax_rate / 100.0 * item.net_amount;
} else if (tax.charge_type == "On Previous Row Amount") {
current_tax_amount = tax_rate / 100.0 * this.frm.doc["taxes"][cint(tax.row_id) - 1].tax_amount_for_current_item;
} else if (tax.charge_type == "On Previous Row Total") {
current_tax_amount = tax_rate / 100.0 * this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_for_current_item;
}
current_tax_amount = flt(current_tax_amount, precision("tax_amount", tax));
this.set_item_wise_tax(item, tax, tax_rate, current_tax_amount);
return current_tax_amount;
},
set_item_wise_tax: function set_item_wise_tax(item, tax, tax_rate, current_tax_amount) {
var key = item.item_code || item.item_name;
var item_wise_tax_amount = current_tax_amount * this.frm.doc.conversion_rate;
if (tax.item_wise_tax_detail && tax.item_wise_tax_detail[key]) item_wise_tax_amount += tax.item_wise_tax_detail[key][1];
tax.item_wise_tax_detail[key] = [tax_rate, flt(item_wise_tax_amount, precision("base_tax_amount", tax))];
},
round_off_totals: function round_off_totals(tax) {
tax.total = flt(tax.total, precision("total", tax));
tax.tax_amount = flt(tax.tax_amount, precision("tax_amount", tax));
tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount, precision("tax_amount", tax));
this.set_in_company_currency(tax, ["total", "tax_amount", "tax_amount_after_discount_amount"]);
},
adjust_discount_amount_loss: function adjust_discount_amount_loss(tax) {
var discount_amount_loss = this.frm.doc.grand_total - flt(this.frm.doc.discount_amount) - tax.total;
tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount + discount_amount_loss, precision("tax_amount", tax));
tax.total = flt(tax.total + discount_amount_loss, precision("total", tax));
this.set_in_company_currency(tax, ["total", "tax_amount_after_discount_amount"]);
},
manipulate_grand_total_for_inclusive_tax: function manipulate_grand_total_for_inclusive_tax() {
var me = this;
if (this.frm.doc["taxes"] && this.frm.doc["taxes"].length) {
var all_inclusive = frappe.utils.all(this.frm.doc["taxes"].map(function (d) {
return cint(d.included_in_print_rate);
}));
if (all_inclusive) {
var last_tax = me.frm.doc["taxes"].slice(-1)[0];
var diff = me.frm.doc.total - flt(last_tax.total, precision("grand_total"));
if (diff && Math.abs(diff) <= 2.0 / Math.pow(10, precision("tax_amount", last_tax))) {
last_tax.tax_amount += diff;
last_tax.tax_amount_after_discount += diff;
last_tax.total += diff;
this.set_in_company_currency(last_tax, ["total", "tax_amount", "tax_amount_after_discount_amount"]);
}
}
}
},
calculate_totals: function calculate_totals() {
var me = this;
var tax_count = this.frm.doc["taxes"] ? this.frm.doc["taxes"].length : 0;
this.frm.doc.grand_total = flt(tax_count ? this.frm.doc["taxes"][tax_count - 1].total : this.frm.doc.net_total);
if (in_list(["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"], this.frm.doc.doctype)) {
this.frm.doc.base_grand_total = this.frm.doc.total_taxes_and_charges ? flt(this.frm.doc.grand_total * this.frm.doc.conversion_rate) : this.frm.doc.base_net_total;
} else {
this.frm.doc.taxes_and_charges_added = this.frm.doc.taxes_and_charges_deducted = 0.0;
if (tax_count) {
$.each(this.frm.doc["taxes"] || [], function (i, tax) {
if (in_list(["Valuation and Total", "Total"], tax.category)) {
if (tax.add_deduct_tax == "Add") {
me.frm.doc.taxes_and_charges_added += flt(tax.tax_amount_after_discount_amount);
} else {
me.frm.doc.taxes_and_charges_deducted += flt(tax.tax_amount_after_discount_amount);
}
}
});
frappe.model.round_floats_in(this.frm.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"]);
}
this.frm.doc.base_grand_total = flt(this.frm.doc.taxes_and_charges_added || this.frm.doc.taxes_and_charges_deducted ? flt(this.frm.doc.grand_total * this.frm.doc.conversion_rate) : this.frm.doc.base_net_total);
this.set_in_company_currency(this.frm.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"]);
}
this.frm.doc.total_taxes_and_charges = flt(this.frm.doc.grand_total - this.frm.doc.net_total, precision("total_taxes_and_charges"));
this.set_in_company_currency(this.frm.doc, ["total_taxes_and_charges"]);
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "base_grand_total"]);
if (frappe.meta.get_docfield(this.frm.doc.doctype, "rounded_total", this.frm.doc.name)) {
this.frm.doc.rounded_total = round_based_on_smallest_currency_fraction(this.frm.doc.grand_total, this.frm.doc.currency, precision("rounded_total"));
}
if (frappe.meta.get_docfield(this.frm.doc.doctype, "base_rounded_total", this.frm.doc.name)) {
var company_currency = this.frm.doc.currency || this.get_company_currency();
this.frm.doc.base_rounded_total = round_based_on_smallest_currency_fraction(this.frm.doc.base_grand_total, company_currency, precision("base_rounded_total"));
}
},
_cleanup: function _cleanup() {
this.frm.doc.base_in_words = this.frm.doc.in_words = "";
if (this.frm.doc["items"] && this.frm.doc["items"].length) {
if (!frappe.meta.get_docfield(this.frm.doc["items"][0].doctype, "item_tax_amount", this.frm.doctype)) {
$.each(this.frm.doc["items"] || [], function (i, item) {
delete item["item_tax_amount"];
});
}
}
if (this.frm.doc["taxes"] && this.frm.doc["taxes"].length) {
var temporary_fields = ["tax_amount_for_current_item", "grand_total_for_current_item", "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"];
if (!frappe.meta.get_docfield(this.frm.doc["taxes"][0].doctype, "tax_amount_after_discount_amount", this.frm.doctype)) {
temporary_fields.push("tax_amount_after_discount_amount");
}
$.each(this.frm.doc["taxes"] || [], function (i, tax) {
$.each(temporary_fields, function (i, fieldname) {
delete tax[fieldname];
});
tax.item_wise_tax_detail = JSON.stringify(tax.item_wise_tax_detail);
});
}
},
set_discount_amount: function set_discount_amount() {
if (this.frm.doc.additional_discount_percentage) {
this.frm.doc.discount_amount = flt(flt(this.frm.doc[frappe.scrub(this.frm.doc.apply_discount_on)]) * this.frm.doc.additional_discount_percentage / 100, precision("discount_amount"));
}
},
apply_discount_amount: function apply_discount_amount() {
var me = this;
var distributed_amount = 0.0;
this.frm.doc.base_discount_amount = 0.0;
if (this.frm.doc.discount_amount) {
if (!this.frm.doc.apply_discount_on) frappe.throw(__("Please select Apply Discount On"));
this.frm.doc.base_discount_amount = flt(this.frm.doc.discount_amount * this.frm.doc.conversion_rate, precision("base_discount_amount"));
var total_for_discount_amount = this.get_total_for_discount_amount();
if (total_for_discount_amount) {
$.each(this.frm.doc["items"] || [], function (i, item) {
distributed_amount = flt(me.frm.doc.discount_amount) * item.net_amount / total_for_discount_amount;
item.net_amount = flt(item.net_amount - distributed_amount, precision("base_amount", item));
item.net_rate = flt(item.net_amount / item.qty, precision("net_rate", item));
me.set_in_company_currency(item, ["net_rate", "net_amount"]);
});
this.discount_amount_applied = true;
this._calculate_taxes_and_totals();
}
}
},
get_total_for_discount_amount: function get_total_for_discount_amount() {
var me = this;
if (this.frm.doc.apply_discount_on == "Net Total") {
return this.frm.doc.net_total;
} else {
var total_actual_tax = 0.0;
var actual_taxes_dict = {};
$.each(this.frm.doc["taxes"] || [], function (i, tax) {
if (tax.charge_type == "Actual") actual_taxes_dict[tax.idx] = tax.tax_amount;else if (actual_taxes_dict[tax.row_id] !== null) {
var actual_tax_amount = flt(actual_taxes_dict[tax.row_id]) * flt(tax.rate) / 100;
actual_taxes_dict[tax.idx] = actual_tax_amount;
}
});
$.each(actual_taxes_dict, function (key, value) {
if (value) total_actual_tax += value;
});
return flt(this.frm.doc.grand_total - total_actual_tax, precision("grand_total"));
}
},
calculate_total_advance: function calculate_total_advance(update_paid_amount) {
var total_allocated_amount = frappe.utils.sum($.map(this.frm.doc["advances"] || [], function (adv) {
return flt(adv.allocated_amount, precision("allocated_amount", adv));
}));
this.frm.doc.total_advance = flt(total_allocated_amount, precision("total_advance"));
this.calculate_outstanding_amount(update_paid_amount);
},
calculate_outstanding_amount: function calculate_outstanding_amount(update_paid_amount) {
if (this.frm.doc.doctype == "Sales Invoice" && this.frm.doc.is_return) {
this.calculate_paid_amount();
}
if (this.frm.doc.is_return || this.frm.doc.docstatus > 0) return;
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "total_advance", "write_off_amount"]);
if (this.frm.doc.party_account_currency == this.frm.doc.currency) {
var total_amount_to_pay = flt(this.frm.doc.grand_total - this.frm.doc.total_advance - this.frm.doc.write_off_amount, precision("grand_total"));
} else {
var total_amount_to_pay = flt(flt(this.frm.doc.grand_total * this.frm.doc.conversion_rate, precision("grand_total")) - this.frm.doc.total_advance - this.frm.doc.base_write_off_amount, precision("base_grand_total"));
}
if (this.frm.doc.doctype == "Sales Invoice" || this.frm.doc.doctype == "Purchase Invoice") {
frappe.model.round_floats_in(this.frm.doc, ["paid_amount"]);
this.set_in_company_currency(this.frm.doc, ["paid_amount"]);
if (this.frm.refresh_field) {
this.frm.refresh_field("paid_amount");
this.frm.refresh_field("base_paid_amount");
}
if (this.frm.doc.doctype == "Sales Invoice") {
this.set_default_payment(total_amount_to_pay, update_paid_amount);
this.calculate_paid_amount();
}
this.calculate_change_amount();
var outstanding_amount = 0.0;
var paid_amount = this.frm.doc.party_account_currency == this.frm.doc.currency ? this.frm.doc.paid_amount : this.frm.doc.base_paid_amount;
var change_amount = this.frm.doc.party_account_currency == this.frm.doc.currency ? this.frm.doc.change_amount : this.frm.doc.base_change_amount;
this.frm.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) + flt(this.frm.doc.change_amount * this.frm.doc.conversion_rate), precision("outstanding_amount"));
} else if (this.frm.doc.doctype == "Purchase Invoice") {
this.frm.doc.outstanding_amount = flt(total_amount_to_pay, precision("outstanding_amount"));
}
},
set_default_payment: function set_default_payment(total_amount_to_pay, update_paid_amount) {
var me = this;
var payment_status = true;
if (this.frm.doc.is_pos && (update_paid_amount === undefined || update_paid_amount)) {
$.each(this.frm.doc['payments'] || [], function (index, data) {
if (data.default && payment_status && total_amount_to_pay > 0) {
data.base_amount = flt(total_amount_to_pay, precision("base_amount"));
data.amount = flt(total_amount_to_pay / me.frm.doc.conversion_rate, precision("amount"));
payment_status = false;
} else if (me.frm.doc.paid_amount) {
data.amount = 0.0;
}
});
}
},
calculate_paid_amount: function calculate_paid_amount() {
var me = this;
var paid_amount = 0.0;
var base_paid_amount = 0.0;
if (this.frm.doc.is_pos) {
$.each(this.frm.doc['payments'] || [], function (index, data) {
data.base_amount = flt(data.amount * me.frm.doc.conversion_rate, precision("base_amount"));
paid_amount += data.amount;
base_paid_amount += data.base_amount;
});
} else if (!this.frm.doc.is_return) {
this.frm.doc.payments = [];
}
this.frm.doc.paid_amount = flt(paid_amount, precision("paid_amount"));
this.frm.doc.base_paid_amount = flt(base_paid_amount, precision("base_paid_amount"));
},
calculate_change_amount: function calculate_change_amount() {
this.frm.doc.change_amount = 0.0;
this.frm.doc.base_change_amount = 0.0;
if (this.frm.doc.paid_amount > this.frm.doc.grand_total && !this.frm.doc.is_return) {
var payment_types = $.map(this.frm.doc.payments, function (d) {
return d.type;
});
if (in_list(payment_types, 'Cash')) {
this.frm.doc.change_amount = flt(this.frm.doc.paid_amount - this.frm.doc.grand_total + this.frm.doc.write_off_amount, precision("change_amount"));
this.frm.doc.base_change_amount = flt(this.frm.doc.base_paid_amount - this.frm.doc.base_grand_total + this.frm.doc.base_write_off_amount, precision("base_change_amount"));
}
}
},
calculate_write_off_amount: function calculate_write_off_amount() {
if (this.frm.doc.paid_amount > this.frm.doc.grand_total) {
this.frm.doc.write_off_amount = flt(this.frm.doc.grand_total - this.frm.doc.paid_amount + this.frm.doc.change_amount, precision("write_off_amount"));
this.frm.doc.base_write_off_amount = flt(this.frm.doc.write_off_amount * this.frm.doc.conversion_rate, precision("base_write_off_amount"));
} else {
this.frm.doc.paid_amount = 0.0;
}
this.calculate_outstanding_amount(false);
}
});
erpnext.TransactionController = erpnext.taxes_and_totals.extend({
setup: function setup() {
this._super();
frappe.ui.form.on(this.frm.doctype + " Item", "rate", function (frm, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
var has_margin_field = frappe.meta.has_field(cdt, 'margin_type');
frappe.model.round_floats_in(item, ["rate", "price_list_rate"]);
if (item.price_list_rate) {
if (item.rate > item.price_list_rate && has_margin_field) {
item.discount_percentage = 0;
item.margin_type = 'Amount';
item.margin_rate_or_amount = flt(item.rate - item.price_list_rate, precision("margin_rate_or_amount", item));
item.rate_with_margin = item.rate;
} else {
item.discount_percentage = flt((1 - item.rate / item.price_list_rate) * 100.0, precision("discount_percentage", item));
item.margin_type = '';
item.margin_rate_or_amount = 0;
item.rate_with_margin = 0;
}
} else {
item.discount_percentage = 0.0;
item.margin_type = '';
item.margin_rate_or_amount = 0;
item.rate_with_margin = 0;
}
cur_frm.cscript.set_gross_profit(item);
cur_frm.cscript.calculate_taxes_and_totals();
});
frappe.ui.form.on(this.frm.cscript.tax_table, "rate", function (frm, cdt, cdn) {
cur_frm.cscript.calculate_taxes_and_totals();
});
frappe.ui.form.on(this.frm.cscript.tax_table, "tax_amount", function (frm, cdt, cdn) {
cur_frm.cscript.calculate_taxes_and_totals();
});
frappe.ui.form.on(this.frm.cscript.tax_table, "row_id", function (frm, cdt, cdn) {
cur_frm.cscript.calculate_taxes_and_totals();
});
frappe.ui.form.on(this.frm.cscript.tax_table, "included_in_print_rate", function (frm, cdt, cdn) {
cur_frm.cscript.set_dynamic_labels();
cur_frm.cscript.calculate_taxes_and_totals();
});
frappe.ui.form.on(this.frm.doctype, "apply_discount_on", function (frm) {
if (frm.doc.additional_discount_percentage) {
frm.trigger("additional_discount_percentage");
} else {
cur_frm.cscript.calculate_taxes_and_totals();
}
});
frappe.ui.form.on(this.frm.doctype, "additional_discount_percentage", function (frm) {
if (!frm.doc.apply_discount_on) {
frappe.msgprint(__("Please set 'Apply Additional Discount On'"));
return;
}
frm.via_discount_percentage = true;
if (frm.doc.additional_discount_percentage && frm.doc.discount_amount) {
frm.doc.discount_amount = 0;
frm.cscript.calculate_taxes_and_totals();
}
var total = flt(frm.doc[frappe.model.scrub(frm.doc.apply_discount_on)]);
var discount_amount = flt(total * flt(frm.doc.additional_discount_percentage) / 100, precision("discount_amount"));
frm.set_value("discount_amount", discount_amount).then(function () {
return delete frm.via_discount_percentage;
});
});
frappe.ui.form.on(this.frm.doctype, "discount_amount", function (frm) {
frm.cscript.set_dynamic_labels();
if (!frm.via_discount_percentage) {
frm.doc.additional_discount_percentage = 0;
}
frm.cscript.calculate_taxes_and_totals();
});
var me = this;
if (this.frm.fields_dict["items"].grid.get_field('batch_no')) {
this.frm.set_query("batch_no", "items", function (doc, cdt, cdn) {
return me.set_query_for_batch(doc, cdt, cdn);
});
}
},
onload: function onload() {
var me = this;
if (this.frm.doc.__islocal) {
var today = frappe.datetime.get_today(),
currency = frappe.defaults.get_user_default("currency");
$.each({
currency: currency,
price_list_currency: currency,
status: "Draft",
is_subcontracted: "No"
}, function (fieldname, value) {
if (me.frm.fields_dict[fieldname] && !me.frm.doc[fieldname]) me.frm.set_value(fieldname, value);
});
if (this.frm.doc.company && !this.frm.doc.amended_from) {
this.frm.trigger("company");
}
}
if (this.frm.fields_dict["taxes"]) {
this["taxes_remove"] = this.calculate_taxes_and_totals;
}
if (this.frm.fields_dict["items"]) {
this["items_remove"] = this.calculate_taxes_and_totals;
}
if (this.frm.fields_dict["recurring_print_format"]) {
this.frm.set_query("recurring_print_format", function (doc) {
return {
filters: [['Print Format', 'doc_type', '=', cur_frm.doctype]]
};
});
}
if (this.frm.fields_dict["return_against"]) {
this.frm.set_query("return_against", function (doc) {
var filters = {
"docstatus": 1,
"is_return": 0,
"company": doc.company
};
if (me.frm.fields_dict["customer"] && doc.customer) filters["customer"] = doc.customer;
if (me.frm.fields_dict["supplier"] && doc.supplier) filters["supplier"] = doc.supplier;
return {
filters: filters
};
});
}
this.setup_quality_inspection();
},
setup_quality_inspection: function setup_quality_inspection() {
if (!in_list(["Delivery Note", "Sales Invoice", "Purchase Receipt", "Purchase Invoice"], this.frm.doc.doctype)) {
return;
}
var me = this;
var inspection_type = in_list(["Purchase Receipt", "Purchase Invoice"], this.frm.doc.doctype) ? "Incoming" : "Outgoing";
var quality_inspection_field = this.frm.get_docfield("items", "quality_inspection");
quality_inspection_field.get_route_options_for_new_doc = function (row) {
if (me.frm.is_new()) return;
return {
"inspection_type": inspection_type,
"reference_type": me.frm.doc.doctype,
"reference_name": me.frm.doc.name,
"item_code": row.doc.item_code,
"description": row.doc.description,
"item_serial_no": row.doc.serial_no ? row.doc.serial_no.split("\n")[0] : null,
"batch_no": row.doc.batch_no
};
};
this.frm.set_query("quality_inspection", "items", function (doc, cdt, cdn) {
var d = locals[cdt][cdn];
return {
filters: {
docstatus: 1,
inspection_type: inspection_type,
item_code: d.item_code
}
};
});
},
onload_post_render: function onload_post_render() {
var me = this;
if (this.frm.doc.__islocal && !(this.frm.doc.taxes || []).length && !(this.frm.doc.__onload ? this.frm.doc.__onload.load_after_mapping : false)) {
this.apply_default_taxes();
} else if (this.frm.doc.__islocal && this.frm.doc.company && this.frm.doc["items"] && !this.frm.doc.is_pos) {
me.calculate_taxes_and_totals();
}
if (frappe.meta.get_docfield(this.frm.doc.doctype + " Item", "item_code")) {
this.setup_item_selector();
}
},
refresh: function refresh() {
erpnext.toggle_naming_series();
erpnext.hide_company();
this.set_dynamic_labels();
this.setup_sms();
},
apply_default_taxes: function apply_default_taxes() {
var me = this;
var taxes_and_charges_field = frappe.meta.get_docfield(me.frm.doc.doctype, "taxes_and_charges", me.frm.doc.name);
if (taxes_and_charges_field) {
return frappe.call({
method: "erpnext.controllers.accounts_controller.get_default_taxes_and_charges",
args: {
"master_doctype": taxes_and_charges_field.options
},
callback: function callback(r) {
if (!r.exc) {
me.frm.set_value("taxes", r.message);
me.calculate_taxes_and_totals();
}
}
});
}
},
setup_sms: function setup_sms() {
var me = this;
if (this.frm.doc.docstatus === 1 && !in_list(["Lost", "Stopped", "Closed"], this.frm.doc.status) && this.frm.doctype != "Purchase Invoice") {
this.frm.page.add_menu_item(__('Send SMS'), function () {
me.send_sms();
});
}
},
send_sms: function send_sms() {
var sms_man = new erpnext.SMSManager(this.frm.doc);
},
barcode: function barcode(doc, cdt, cdn) {
var d = locals[cdt][cdn];
if (d.barcode == "" || d.barcode == null) {
d.item_code = "";
}
this.item_code(doc, cdt, cdn, true);
},
item_code: function item_code(doc, cdt, cdn, from_barcode) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
var update_stock = 0,
show_batch_dialog = 0;
if (['Sales Invoice', 'Purchase Invoice'].includes(this.frm.doc.doctype)) {
update_stock = cint(me.frm.doc.update_stock);
show_batch_dialog = update_stock;
} else if (this.frm.doc.doctype === 'Purchase Receipt' && me.frm.doc.is_return || this.frm.doc.doctype === 'Delivery Note') {
show_batch_dialog = 1;
}
if (!from_barcode) {
item.barcode = null;
}
if (item.item_code || item.barcode || item.serial_no) {
if (!this.validate_company_and_party()) {
this.frm.fields_dict["items"].grid.grid_rows[item.idx - 1].remove();
} else {
return this.frm.call({
method: "erpnext.stock.get_item_details.get_item_details",
child: item,
args: {
args: {
item_code: item.item_code,
barcode: item.barcode,
serial_no: item.serial_no,
warehouse: item.warehouse,
customer: me.frm.doc.customer,
supplier: me.frm.doc.supplier,
currency: me.frm.doc.currency,
update_stock: update_stock,
conversion_rate: me.frm.doc.conversion_rate,
price_list: me.frm.doc.selling_price_list || me.frm.doc.buying_price_list,
price_list_currency: me.frm.doc.price_list_currency,
plc_conversion_rate: me.frm.doc.plc_conversion_rate,
company: me.frm.doc.company,
order_type: me.frm.doc.order_type,
is_pos: cint(me.frm.doc.is_pos),
is_subcontracted: me.frm.doc.is_subcontracted,
transaction_date: me.frm.doc.transaction_date || me.frm.doc.posting_date,
ignore_pricing_rule: me.frm.doc.ignore_pricing_rule,
doctype: me.frm.doc.doctype,
name: me.frm.doc.name,
project: item.project || me.frm.doc.project,
qty: item.qty || 1,
stock_qty: item.stock_qty,
conversion_factor: item.conversion_factor
}
},
callback: function callback(r) {
if (!r.exc) {
me.frm.script_manager.trigger("price_list_rate", cdt, cdn);
me.toggle_conversion_factor(item);
if (show_batch_dialog) {
var d = locals[cdt][cdn];
$.each(r.message, function (k, v) {
if (!d[k]) d[k] = v;
});
erpnext.show_serial_batch_selector(me.frm, d);
}
}
}
});
}
}
},
serial_no: function serial_no(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
if (item.serial_no) {
if (!item.item_code) {
this.frm.trigger("item_code", cdt, cdn);
} else {
var valid_serial_nos = [];
var serial_nos = item.serial_no.trim().replace(/,/g, '\n');
serial_nos = serial_nos.trim().split('\n');
for (var x = 0; x <= serial_nos.length - 1; x++) {
if (serial_nos[x].trim() != "" && valid_serial_nos.indexOf(serial_nos[x].trim()) == -1) {
valid_serial_nos.push(serial_nos[x].trim());
}
}
item.serial_no = valid_serial_nos.join('\n');
refresh_field("serial_no", item.name, item.parentfield);
if (!doc.is_return) {
frappe.model.set_value(item.doctype, item.name, "qty", valid_serial_nos.length / item.conversion_factor);
frappe.model.set_value(item.doctype, item.name, "stock_qty", valid_serial_nos.length);
}
}
}
},
validate: function validate() {
this.calculate_taxes_and_totals(false);
},
company: function company() {
var me = this;
var set_pricing = function set_pricing() {
if (me.frm.doc.company && me.frm.fields_dict.currency) {
var company_currency = me.get_company_currency();
var company_doc = frappe.get_doc(":Company", me.frm.doc.company);
if (!me.frm.doc.currency) {
me.frm.set_value("currency", company_currency);
}
if (me.frm.doc.currency == company_currency) {
me.frm.set_value("conversion_rate", 1.0);
}
if (me.frm.doc.price_list_currency == company_currency) {
me.frm.set_value('plc_conversion_rate', 1.0);
}
if (company_doc.default_letter_head) {
if (me.frm.fields_dict.letter_head) {
me.frm.set_value("letter_head", company_doc.default_letter_head);
}
}
if (company_doc.default_terms && me.frm.doc.doctype != "Purchase Invoice" && frappe.meta.has_field(me.frm.doc.doctype, "tc_name")) {
me.frm.set_value("tc_name", company_doc.default_terms);
}
me.frm.script_manager.trigger("currency");
me.apply_pricing_rule();
}
};
var set_party_account = function set_party_account(set_pricing) {
if (in_list(["Sales Invoice", "Purchase Invoice"], me.frm.doc.doctype)) {
if (me.frm.doc.doctype == "Sales Invoice") {
var party_type = "Customer";
var party_account_field = 'debit_to';
} else {
var party_type = "Supplier";
var party_account_field = 'credit_to';
}
var party = me.frm.doc[frappe.model.scrub(party_type)];
if (party) {
return frappe.call({
method: "erpnext.accounts.party.get_party_account",
args: {
company: me.frm.doc.company,
party_type: party_type,
party: party
},
callback: function callback(r) {
if (!r.exc && r.message) {
me.frm.set_value(party_account_field, r.message);
set_pricing();
}
}
});
} else {
set_pricing();
}
} else {
set_pricing();
}
};
if (this.frm.doc.posting_date) var date = this.frm.doc.posting_date;else var date = this.frm.doc.transaction_date;
if (frappe.meta.get_docfield(this.frm.doctype, "shipping_address") && in_list(['Purchase Order', 'Purchase Receipt', 'Purchase Invoice'], this.frm.doctype)) {
erpnext.utils.get_shipping_address(this.frm, function () {
set_party_account(set_pricing);
});
} else {
set_party_account(set_pricing);
}
if (this.frm.doc.company) {
erpnext.last_selected_company = this.frm.doc.company;
}
},
transaction_date: function transaction_date() {
if (this.frm.doc.transaction_date) {
this.frm.transaction_date = this.frm.doc.transaction_date;
frappe.ui.form.trigger(this.frm.doc.doctype, "currency");
}
},
posting_date: function posting_date() {
var me = this;
if (this.frm.doc.posting_date) {
this.frm.posting_date = this.frm.doc.posting_date;
if (this.frm.doc.doctype == "Sales Invoice" && this.frm.doc.customer || this.frm.doc.doctype == "Purchase Invoice" && this.frm.doc.supplier) {
return frappe.call({
method: "erpnext.accounts.party.get_due_date",
args: {
"posting_date": me.frm.doc.posting_date,
"party_type": me.frm.doc.doctype == "Sales Invoice" ? "Customer" : "Supplier",
"party": me.frm.doc.doctype == "Sales Invoice" ? me.frm.doc.customer : me.frm.doc.supplier,
"company": me.frm.doc.company
},
callback: function callback(r, rt) {
if (r.message) {
me.frm.set_value("due_date", r.message);
frappe.ui.form.trigger(me.frm.doc.doctype, "currency");
}
}
});
} else {
frappe.ui.form.trigger(me.frm.doc.doctype, "currency");
}
}
},
get_company_currency: function get_company_currency() {
return erpnext.get_currency(this.frm.doc.company);
},
contact_person: function contact_person() {
erpnext.utils.get_contact_details(this.frm);
},
currency: function currency() {
var transaction_date = this.frm.doc.transaction_date || this.frm.doc.posting_date;
var me = this;
this.set_dynamic_labels();
var company_currency = this.get_company_currency();
if (this.frm.doc.currency && this.frm.doc.currency !== company_currency && !this.frm.doc.ignore_pricing_rule) {
this.get_exchange_rate(transaction_date, this.frm.doc.currency, company_currency, function (exchange_rate) {
me.frm.set_value("conversion_rate", exchange_rate);
});
} else {
this.conversion_rate();
}
},
conversion_rate: function conversion_rate() {
if (this.frm.doc.currency === this.get_company_currency()) {
this.frm.set_value("conversion_rate", 1.0);
}
if (this.frm.doc.currency === this.frm.doc.price_list_currency && this.frm.doc.plc_conversion_rate !== this.frm.doc.conversion_rate) {
this.frm.set_value("plc_conversion_rate", this.frm.doc.conversion_rate);
}
if (flt(this.frm.doc.conversion_rate) > 0.0) {
if (this.frm.doc.ignore_pricing_rule) {
this.calculate_taxes_and_totals();
} else if (!this.in_apply_price_list) {
this.apply_price_list();
}
}
},
get_exchange_rate: function get_exchange_rate(transaction_date, from_currency, to_currency, _callback) {
if (!transaction_date || !from_currency || !to_currency) return;
return frappe.call({
method: "erpnext.setup.utils.get_exchange_rate",
args: {
transaction_date: transaction_date,
from_currency: from_currency,
to_currency: to_currency
},
callback: function callback(r) {
_callback(flt(r.message));
}
});
},
price_list_currency: function price_list_currency() {
var me = this;
this.set_dynamic_labels();
var company_currency = this.get_company_currency();
if (this.frm.doc.price_list_currency !== company_currency && !this.frm.doc.ignore_pricing_rule) {
this.get_exchange_rate(this.frm.doc.posting_date, this.frm.doc.price_list_currency, company_currency, function (exchange_rate) {
me.frm.set_value("plc_conversion_rate", exchange_rate);
});
} else {
this.plc_conversion_rate();
}
},
plc_conversion_rate: function plc_conversion_rate() {
if (this.frm.doc.price_list_currency === this.get_company_currency()) {
this.frm.set_value("plc_conversion_rate", 1.0);
} else if (this.frm.doc.price_list_currency === this.frm.doc.currency && this.frm.doc.plc_conversion_rate && cint(this.frm.doc.plc_conversion_rate) != 1 && cint(this.frm.doc.plc_conversion_rate) != cint(this.frm.doc.conversion_rate)) {
this.frm.set_value("conversion_rate", this.frm.doc.plc_conversion_rate);
}
if (!this.in_apply_price_list) {
this.apply_price_list();
}
},
uom: function uom(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
if (item.item_code && item.uom) {
return this.frm.call({
method: "erpnext.stock.get_item_details.get_conversion_factor",
child: item,
args: {
item_code: item.item_code,
uom: item.uom
},
callback: function callback(r) {
if (!r.exc) {
me.conversion_factor(me.frm.doc, cdt, cdn);
}
}
});
}
},
conversion_factor: function conversion_factor(doc, cdt, cdn, dont_fetch_price_list_rate) {
if (frappe.meta.get_docfield(cdt, "stock_qty", cdn)) {
var item = frappe.get_doc(cdt, cdn);
frappe.model.round_floats_in(item, ["qty", "conversion_factor"]);
item.stock_qty = flt(item.qty * item.conversion_factor, precision("stock_qty", item));
refresh_field("stock_qty", item.name, item.parentfield);
this.toggle_conversion_factor(item);
if (!dont_fetch_price_list_rate) this.apply_price_list(item, true);
}
},
toggle_conversion_factor: function toggle_conversion_factor(item) {
if (this.frm.get_field('items').grid.fields_map.conversion_factor) {
this.frm.fields_dict.items.grid.toggle_enable("conversion_factor", item.uom != item.stock_uom ? true : false);
}
},
qty: function qty(doc, cdt, cdn) {
this.conversion_factor(doc, cdt, cdn, true);
this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true);
},
set_dynamic_labels: function set_dynamic_labels() {
this.frm.toggle_reqd("plc_conversion_rate", !!(this.frm.doc.price_list_name && this.frm.doc.price_list_currency));
if (this.frm.doc_currency !== this.frm.doc.currency) {
var company_currency = this.get_company_currency();
this.change_form_labels(company_currency);
this.change_grid_labels(company_currency);
this.frm.refresh_fields();
this.frm.doc_currency = this.frm.doc.currency;
}
},
change_form_labels: function change_form_labels(company_currency) {
var me = this;
this.frm.set_currency_labels(["base_total", "base_net_total", "base_total_taxes_and_charges", "base_discount_amount", "base_grand_total", "base_rounded_total", "base_in_words", "base_taxes_and_charges_added", "base_taxes_and_charges_deducted", "total_amount_to_pay", "base_paid_amount", "base_write_off_amount", "base_change_amount", "base_operating_cost", "base_raw_material_cost", "base_total_cost", "base_scrap_material_cost"], company_currency);
this.frm.set_currency_labels(["total", "net_total", "total_taxes_and_charges", "discount_amount", "grand_total", "taxes_and_charges_added", "taxes_and_charges_deducted", "rounded_total", "in_words", "paid_amount", "write_off_amount", "operating_cost", "scrap_material_cost", "raw_material_cost", "total_cost"], this.frm.doc.currency);
this.frm.set_currency_labels(["outstanding_amount", "total_advance"], this.frm.doc.party_account_currency);
cur_frm.set_df_property("conversion_rate", "description", "1 " + this.frm.doc.currency + " = [?] " + company_currency);
if (this.frm.doc.price_list_currency && this.frm.doc.price_list_currency != company_currency) {
cur_frm.set_df_property("plc_conversion_rate", "description", "1 " + this.frm.doc.price_list_currency + " = [?] " + company_currency);
}
this.frm.toggle_display(["conversion_rate", "base_total", "base_net_total", "base_total_taxes_and_charges", "base_taxes_and_charges_added", "base_taxes_and_charges_deducted", "base_grand_total", "base_rounded_total", "base_in_words", "base_discount_amount", "base_paid_amount", "base_write_off_amount", "base_operating_cost", "base_raw_material_cost", "base_total_cost", "base_scrap_material_cost"], this.frm.doc.currency != company_currency);
this.frm.toggle_display(["plc_conversion_rate", "price_list_currency"], this.frm.doc.price_list_currency != company_currency);
var show = cint(cur_frm.doc.discount_amount) || (cur_frm.doc.taxes || []).filter(function (d) {
return d.included_in_print_rate === 1;
}).length;
if (frappe.meta.get_docfield(cur_frm.doctype, "net_total")) cur_frm.toggle_display("net_total", show);
if (frappe.meta.get_docfield(cur_frm.doctype, "base_net_total")) cur_frm.toggle_display("base_net_total", show && me.frm.doc.currency != company_currency);
},
change_grid_labels: function change_grid_labels(company_currency) {
var me = this;
this.frm.set_currency_labels(["base_rate", "base_net_rate", "base_price_list_rate", "base_amount", "base_net_amount"], company_currency, "items");
this.frm.set_currency_labels(["rate", "net_rate", "price_list_rate", "amount", "net_amount"], this.frm.doc.currency, "items");
if (this.frm.fields_dict["operations"]) {
this.frm.set_currency_labels(["operating_cost", "hour_rate"], this.frm.doc.currency, "operations");
this.frm.set_currency_labels(["base_operating_cost", "base_hour_rate"], company_currency, "operations");
var item_grid = this.frm.fields_dict["operations"].grid;
$.each(["base_operating_cost", "base_hour_rate"], function (i, fname) {
if (frappe.meta.get_docfield(item_grid.doctype, fname)) item_grid.set_column_disp(fname, me.frm.doc.currency != company_currency);
});
}
if (this.frm.fields_dict["scrap_items"]) {
this.frm.set_currency_labels(["rate", "amount"], this.frm.doc.currency, "scrap_items");
this.frm.set_currency_labels(["base_rate", "base_amount"], company_currency, "scrap_items");
var item_grid = this.frm.fields_dict["scrap_items"].grid;
$.each(["base_rate", "base_amount"], function (i, fname) {
if (frappe.meta.get_docfield(item_grid.doctype, fname)) item_grid.set_column_disp(fname, me.frm.doc.currency != company_currency);
});
}
if (this.frm.fields_dict["taxes"]) {
this.frm.set_currency_labels(["tax_amount", "total", "tax_amount_after_discount"], this.frm.doc.currency, "taxes");
this.frm.set_currency_labels(["base_tax_amount", "base_total", "base_tax_amount_after_discount"], company_currency, "taxes");
}
if (this.frm.fields_dict["advances"]) {
this.frm.set_currency_labels(["advance_amount", "allocated_amount"], this.frm.doc.party_account_currency, "advances");
}
var item_grid = this.frm.fields_dict["items"].grid;
$.each(["base_rate", "base_price_list_rate", "base_amount"], function (i, fname) {
if (frappe.meta.get_docfield(item_grid.doctype, fname)) item_grid.set_column_disp(fname, me.frm.doc.currency != company_currency);
});
var show = cint(cur_frm.doc.discount_amount) || (cur_frm.doc.taxes || []).filter(function (d) {
return d.included_in_print_rate === 1;
}).length;
$.each(["net_rate", "net_amount"], function (i, fname) {
if (frappe.meta.get_docfield(item_grid.doctype, fname)) item_grid.set_column_disp(fname, show);
});
$.each(["base_net_rate", "base_net_amount"], function (i, fname) {
if (frappe.meta.get_docfield(item_grid.doctype, fname)) item_grid.set_column_disp(fname, show && me.frm.doc.currency != company_currency);
});
var $wrapper = $(this.frm.wrapper);
},
recalculate: function recalculate() {
this.calculate_taxes_and_totals();
},
recalculate_values: function recalculate_values() {
this.calculate_taxes_and_totals();
},
calculate_charges: function calculate_charges() {
this.calculate_taxes_and_totals();
},
ignore_pricing_rule: function ignore_pricing_rule() {
if (this.frm.doc.ignore_pricing_rule) {
var me = this;
var item_list = [];
$.each(this.frm.doc["items"] || [], function (i, d) {
if (d.item_code) {
item_list.push({
"doctype": d.doctype,
"name": d.name,
"pricing_rule": d.pricing_rule
});
}
});
return this.frm.call({
method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.remove_pricing_rules",
args: { item_list: item_list },
callback: function callback(r) {
if (!r.exc && r.message) {
me._set_values_for_item_list(r.message);
me.calculate_taxes_and_totals();
if (me.frm.doc.apply_discount_on) me.frm.trigger("apply_discount_on");
}
}
});
} else {
this.apply_pricing_rule();
}
},
apply_pricing_rule: function apply_pricing_rule(item, calculate_taxes_and_totals) {
var me = this;
var args = this._get_args(item);
if (!(args.items && args.items.length)) {
if (calculate_taxes_and_totals) me.calculate_taxes_and_totals();
return;
}
return this.frm.call({
method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.apply_pricing_rule",
args: { args: args },
callback: function callback(r) {
if (!r.exc && r.message) {
me._set_values_for_item_list(r.message);
if (item) me.set_gross_profit(item);
if (calculate_taxes_and_totals) me.calculate_taxes_and_totals();
if (me.frm.doc.apply_discount_on) me.frm.trigger("apply_discount_on");
}
}
});
},
_get_args: function _get_args(item) {
var me = this;
return {
"items": this._get_item_list(item),
"customer": me.frm.doc.customer,
"customer_group": me.frm.doc.customer_group,
"territory": me.frm.doc.territory,
"supplier": me.frm.doc.supplier,
"supplier_type": me.frm.doc.supplier_type,
"currency": me.frm.doc.currency,
"conversion_rate": me.frm.doc.conversion_rate,
"price_list": me.frm.doc.selling_price_list || me.frm.doc.buying_price_list,
"price_list_currency": me.frm.doc.price_list_currency,
"plc_conversion_rate": me.frm.doc.plc_conversion_rate,
"company": me.frm.doc.company,
"transaction_date": me.frm.doc.transaction_date || me.frm.doc.posting_date,
"campaign": me.frm.doc.campaign,
"sales_partner": me.frm.doc.sales_partner,
"ignore_pricing_rule": me.frm.doc.ignore_pricing_rule,
"doctype": me.frm.doc.doctype,
"name": me.frm.doc.name,
"is_return": cint(me.frm.doc.is_return),
"update_stock": in_list(['Sales Invoice', 'Purchase Invoice'], me.frm.doc.doctype) ? cint(me.frm.doc.update_stock) : 0,
"conversion_factor": me.frm.doc.conversion_factor
};
},
_get_item_list: function _get_item_list(item) {
var item_list = [];
var append_item = function append_item(d) {
if (d.item_code) {
item_list.push({
"doctype": d.doctype,
"name": d.name,
"item_code": d.item_code,
"item_group": d.item_group,
"brand": d.brand,
"qty": d.qty,
"parenttype": d.parenttype,
"parent": d.parent,
"pricing_rule": d.pricing_rule,
"warehouse": d.warehouse,
"serial_no": d.serial_no,
"discount_percentage": d.discount_percentage || 0.0,
"conversion_factor": d.conversion_factor || 1.0
});
if (in_list(["Quotation Item", "Sales Order Item", "Delivery Note Item", "Sales Invoice Item"]), d.doctype) {
item_list[0]["margin_type"] = d.margin_type;
item_list[0]["margin_rate_or_amount"] = d.margin_rate_or_amount;
}
}
};
if (item) {
append_item(item);
} else {
$.each(this.frm.doc["items"] || [], function (i, d) {
append_item(d);
});
}
return item_list;
},
_set_values_for_item_list: function _set_values_for_item_list(children) {
var me = this;
var price_list_rate_changed = false;
for (var i = 0, l = children.length; i < l; i++) {
var d = children[i];
var existing_pricing_rule = frappe.model.get_value(d.doctype, d.name, "pricing_rule");
for (var k in d) {
var v = d[k];
if (["doctype", "name"].indexOf(k) === -1) {
if (k == "price_list_rate") {
if (flt(v) != flt(d.price_list_rate)) price_list_rate_changed = true;
}
frappe.model.set_value(d.doctype, d.name, k, v);
}
}
if (!me.frm.doc.ignore_pricing_rule && existing_pricing_rule && !d.pricing_rule) {
me.apply_price_list(frappe.get_doc(d.doctype, d.name));
}
}
if (!price_list_rate_changed) me.calculate_taxes_and_totals();
},
apply_price_list: function apply_price_list(item) {
var me = this;
var args = this._get_args(item);
if (!(args.items && args.items.length || args.price_list)) {
return;
}
return this.frm.call({
method: "erpnext.stock.get_item_details.apply_price_list",
args: { args: args },
callback: function callback(r) {
if (!r.exc) {
me.in_apply_price_list = true;
me.frm.set_value("price_list_currency", r.message.parent.price_list_currency);
me.frm.set_value("plc_conversion_rate", r.message.parent.plc_conversion_rate);
me.in_apply_price_list = false;
if (args.items.length) {
me._set_values_for_item_list(r.message.children);
}
}
}
});
},
validate_company_and_party: function validate_company_and_party() {
var me = this;
var valid = true;
$.each(["company", "customer"], function (i, fieldname) {
if (frappe.meta.has_field(me.frm.doc.doctype, fieldname) && me.frm.doc.doctype != "Purchase Order") {
if (!me.frm.doc[fieldname]) {
frappe.msgprint(__("Please specify") + ": " + frappe.meta.get_label(me.frm.doc.doctype, fieldname, me.frm.doc.name) + ". " + __("It is needed to fetch Item Details."));
valid = false;
}
}
});
return valid;
},
get_terms: function get_terms() {
var me = this;
erpnext.utils.get_terms(this.frm.doc.tc_name, this.frm.doc, function (r) {
if (!r.exc) {
me.frm.set_value("terms", r.message);
}
});
},
taxes_and_charges: function taxes_and_charges() {
var me = this;
if (this.frm.doc.taxes_and_charges) {
return this.frm.call({
method: "erpnext.controllers.accounts_controller.get_taxes_and_charges",
args: {
"master_doctype": frappe.meta.get_docfield(this.frm.doc.doctype, "taxes_and_charges", this.frm.doc.name).options,
"master_name": this.frm.doc.taxes_and_charges
},
callback: function callback(r) {
if (!r.exc) {
me.frm.set_value("taxes", r.message);
me.calculate_taxes_and_totals();
}
}
});
}
},
is_recurring: function is_recurring() {
if (this.frm.doc.is_recurring && this.frm.doc.__islocal) {
frappe.msgprint(__("Please set recurring after saving"));
this.frm.set_value('is_recurring', 0);
return;
}
if (this.frm.doc.is_recurring) {
if (!this.frm.doc.recurring_id) {
this.frm.set_value('recurring_id', this.frm.doc.name);
}
var owner_email = this.frm.doc.owner == "Administrator" ? frappe.user_info("Administrator").email : this.frm.doc.owner;
this.frm.doc.notification_email_address = $.map([cstr(owner_email), cstr(this.frm.doc.contact_email)], function (v) {
return v || null;
}).join(", ");
this.frm.doc.repeat_on_day_of_month = frappe.datetime.str_to_obj(this.frm.doc.posting_date).getDate();
}
refresh_many(["notification_email_address", "repeat_on_day_of_month"]);
},
from_date: function from_date() {
if (this.frm.doc.from_date) {
var recurring_type_map = { 'Monthly': 1, 'Quarterly': 3, 'Half-yearly': 6,
'Yearly': 12 };
var months = recurring_type_map[this.frm.doc.recurring_type];
if (months) {
var to_date = frappe.datetime.add_months(this.frm.doc.from_date, months);
this.frm.doc.to_date = frappe.datetime.add_days(to_date, -1);
refresh_field('to_date');
}
}
},
set_gross_profit: function set_gross_profit(item) {
if (this.frm.doc.doctype == "Sales Order" && item.valuation_rate) {
var rate = flt(item.rate) * flt(this.frm.doc.conversion_rate || 1);
item.gross_profit = flt((rate - item.valuation_rate) * item.stock_qty, precision("amount", item));
}
},
setup_item_selector: function setup_item_selector() {
return;
},
get_advances: function get_advances() {
if (!this.frm.is_return) {
return this.frm.call({
method: "set_advances",
doc: this.frm.doc,
callback: function callback(r, rt) {
refresh_field("advances");
}
});
}
},
make_payment_entry: function make_payment_entry() {
return frappe.call({
method: cur_frm.cscript.get_method_for_payment(),
args: {
"dt": cur_frm.doc.doctype,
"dn": cur_frm.doc.name
},
callback: function callback(r) {
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
});
},
get_method_for_payment: function get_method_for_payment() {
var method = "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry";
if (cur_frm.doc.__onload && cur_frm.doc.__onload.make_payment_via_journal_entry) {
if (in_list(['Sales Invoice', 'Purchase Invoice'], cur_frm.doc.doctype)) {
method = "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_against_invoice";
} else {
method = "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_against_order";
}
}
return method;
},
set_query_for_batch: function set_query_for_batch(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
if (!item.item_code) {
frappe.throw(__("Please enter Item Code to get batch no"));
} else if (doc.doctype == "Purchase Receipt" || doc.doctype == "Purchase Invoice" && doc.update_stock) {
return {
filters: { 'item': item.item_code }
};
} else {
filters = {
'item_code': item.item_code,
'posting_date': me.frm.doc.posting_date || frappe.datetime.nowdate()
};
if (item.warehouse) filters["warehouse"] = item.warehouse;
return {
query: "erpnext.controllers.queries.get_batch_no",
filters: filters
};
}
}
});
erpnext.show_serial_batch_selector = function (frm, d) {
frappe.require("assets/erpnext/js/utils/serial_no_batch_selector.js", function () {
new erpnext.SerialNoBatchSelector({
frm: frm,
item: d,
warehouse_details: {
type: "Warehouse",
name: d.warehouse
}
});
});
};frappe.templates['pos'] = '<div class="pos"> <div class="row"> <div class="col-sm-5 pos-bill-wrapper"> <div class="col-sm-12"><h6 class="form-section-heading uppercase">{{ __("Item Cart") }}</h6></div> <div class="pos-bill"> <div class="item-cart"> <div class="pos-list-row pos-bill-header text-muted h6"> <span class="cell subject"> {{ __("Item Name")}} </span> <span class="cell text-right">{{ __("Quantity") }}</span> <span class="cell text-right">{{ __("Discount") }}</span> <span class="cell text-right">{{ __("Rate") }}</span> </div> <div class="item-cart-items"> <div class="no-items-message text-extra-muted"> <span class="text-center"> <i class="fa fa-2x fa-shopping-cart"></i> <p>{{ __("Tap items to add them here") }}</p> </span> </div> <div class="items"> </div> </div> </div> </div> <div class="totals-area"> <div class="pos-list-row net-total-area"> <div class="cell"></div> <div class="cell text-right">{%= __("Net Total") %}</div> <div class="cell price-cell bold net-total text-right"></div> </div> <div class="pos-list-row tax-area"> <div class="cell"></div> <div class="cell text-right">{%= __("Taxes") %}</div> <div class="cell price-cell text-right tax-table"> </div> </div> {% if (apply_discount_on) { %} <div class="pos-list-row discount-amount-area"> <div class="cell"></div> <div class="cell text-right">{%= __("Discount") %}</div> <div class="cell price-cell discount-field-col"> <div class="input-group input-group-sm"> <span class="input-group-addon">%</span> <input type="text" class="form-control discount-percentage text-right"> </div> <div class="input-group input-group-sm"> <span class="input-group-addon">{%= get_currency_symbol(currency) %}</span> <input type="text" class="form-control discount-amount text-right" placeholder="{%= 0.00 %}"> </div> </div> </div> {% } %} <div class="pos-list-row grand-total-area collapse-btn" style="border-bottom:1px solid #d1d8dd;"> <div class="cell"> <a class=""> <i class="octicon octicon-chevron-down"></i> </a> </div> <div class="cell text-right bold">{%= __("Grand Total") %}</div> <div class="cell price-cell grand-total text-right lead"></div> </div> </div> <div class="row" style="margin-top: 30px"> <div class="col-sm-6 selected-item"> </div> <div class="col-xs-6 numeric_keypad hidden-xs" style="display:none"> {% var chartData = ["Qty", "Disc", "Price"] %} {% for(var i=0; i <3; i++) { %} <div class="row text-right"> {% for(var j=i*3; j <(i+1)*3; j++) { %} <button type="button" class="btn btn-default numeric-keypad" val="{{j+1}}">{{j+1}}</button> {% } %} <button type="button" {% if(!allow_user_to_edit_rate && chartData[i] == __("Price")) { %} disabled {% } %} id="pos-item-{{ chartData[i].toLowerCase() }}" class="btn text-center btn-default numeric-keypad pos-operation">{{ __(chartData[i]) }}</button> </div> {% } %} <div class="row text-right"> <button type="button" class="btn btn-default numeric-keypad numeric-del">{{ __("Del") }}</button> <button type="button" class="btn btn-default numeric-keypad" val="0">0</button> <button type="button" class="btn btn-default numeric-keypad" val=".">.</button> <button type="button" class="btn btn-primary numeric-keypad pos-pay">{{ __("Pay") }}</button> </div> </div> </div> </div> <div class="col-sm-5 list-customers"> <div class="col-sm-12"><h6 class="form-section-heading uppercase">{{ __("Customers in Queue") }}</h6></div> <div class="pos-list-row pos-bill-header"> <div class="cell subject"><input class="list-select-all" type="checkbox">{{ __("Customer") }}</div> <div class="cell text-left">{{ __("Status") }}</div> <div class="cell text-right">{{ __("Amount") }}</div> <div class="cell text-right">{{ __("Grand Total") }}</div> </div> <div class="list-customers-table border-left border-right border-bottom"> <div class="no-items-message text-extra-muted"> <span class="text-center"> <i class="fa fa-2x fa-user"></i> <p>{{ __("No Customers yet!") }}</p> </span> </div> </div> </div> <div class="col-sm-7 pos-items-section"> <div class="col-sm-12"><h6 class="form-section-heading uppercase">{{ __("Stock Items") }}</h6></div> <div class="row pos-item-area"> </div> <span id="customer-results" style="color:#68a;"></span> <div class="item-list-area"> <div class="pos-list-row pos-bill-header text-muted h6"> <div class="cell subject search-item-group"> <div class="dropdown"> <a class="text-muted dropdown-toggle" data-toggle="dropdown"><span class="dropdown-text">{{ __("All Item Groups") }}</span><i class="caret"></i></a> <ul class="dropdown-menu"> </ul> </div> </div> <div class="cell search-item"></div> </div> <div class="app-listing item-list image-view-container"> </div> </div> </div> </div> ';
frappe.templates['pos_bill_item'] = '<div class="row pos-bill-row pos-bill-item" data-item-code="{%= item_code %}"> <div class="col-xs-4"><h6>{%= item_code || "" %}{%= __(item_name) || "" %}</h6></div> <div class="col-xs-3"> <div class="row pos-qty-row"> <div class="col-xs-2 text-center pos-qty-btn" data-action="decrease-qty"><i class="fa fa-minus text-muted" style="font-size:12px"></i></div> <div class="col-xs-8"> <div> <input type="tel" value="{%= qty %}" class="form-control pos-item-qty text-right"> </div> {% if(actual_qty != null) { %} <div style="margin-top: 5px;" class="text-muted small text-right"> {%= __("In Stock: ") %} <span>{%= actual_qty || 0.0 %}</span> </div> {% } %} </div> <div class="col-xs-2 text-center pos-qty-btn" data-action="increase-qty"><i class="fa fa-plus text-muted" style="font-size:12px"></i></div> </div> </div> <div class="col-xs-2 text-right"> <div class="row input-sm"> <input type="tel" value="{%= discount_percentage %}" class="form-control text-right pos-item-disc"> </div> </div> <div class="col-xs-3 text-right"> <div class="text-muted" style="margin-top: 5px;"> {% if(enabled) { %} <input type="tel" value="{%= rate %}" class="form-control input-sm pos-item-price text-right"> {% } else { %} <h6>{%= format_currency(rate) %}</h6> {% } %} </div> <p><h6>{%= amount %}</h6></p> </div> </div> ';
frappe.templates['pos_bill_item_new'] = '<div class="pos-list-row pos-bill-item {{ selected_class }}" data-item-code="{{ item_code }}"> <div class="cell subject"> <a class="grey list-id" title="{{ item_name }}">{{ strip_html(__(item_name)) || item_code }}</a> </div> <div class="cell text-right">{%= qty %}</div> <div class="cell text-right">{%= discount_percentage %}</div> <div class="cell text-right">{%= format_currency(rate) %}</div> </div> ';
frappe.templates['pos_selected_item'] = '<div class="pos-selected-item-action" data-item-code="{%= item_code %}" data-idx="{%= idx %}"> <div class="pos-list-row"> <div class="cell">{{ __("Quantity") }}:</div> <input type="tel" class="form-control cell pos-item-qty" value="{%= qty %}"/> </div> <div class="pos-list-row"> <div class="cell">{{ __("Price List Rate") }}:</div> <input type="tel" class="form-control cell" disabled value="{%= price_list_rate %}"/> </div> <div class="pos-list-row"> <div class="cell">{{ __("Discount") }}:</div> <input type="tel" class="form-control cell pos-item-disc" value="{%= discount_percentage %}"> </div> <div class="pos-list-row"> <div class="cell">{{ __("Price") }}:</div> <input type="tel" class="form-control cell pos-item-price" {% if !allow_user_to_edit_rate %} disabled {% endif %} value="{%= rate %}"/> </div> <div class="pos-list-row"> <div class="cell">{{ __("Amount") }}:</div> <input type="tel" class="form-control cell pos-amount" disabled value="{%= amount %}"/> </div> </div>';
frappe.templates['pos_item'] = '<div class="pos-item-wrapper image-view-item" data-item-code="{{item_code}}"> <div class="image-view-header doclist-row"> <div class="list-value"> <a class="grey list-id" data-name="{{item_code}}" title="{{ item_name || item_code}}">{{item_name || item_code}}<br>({{ __(item_stock) }})</a> </div> </div> <div class="image-view-body"> <a data-item-code="{{ item_code }}" title="{{ item_name || item_code }}" > <div class="image-field" style=" {% if (!item_image) { %} background-color: #fafbfc; {% } %} border: 0px;" > {% if (!item_image) { %} <span class="placeholder-text"> {%= frappe.get_abbr(item_name || item_code) %} </span> {% } %} {% if (item_image) { %} <img src="{{ item_image }}" alt="{{item_name || item_code}}"> {% } %} </div> <span class="price-info"> {{item_price}} </span> </a> </div> </div>';
frappe.templates['pos_tax_row'] = '<div class="pos-list-row" style="padding-right: 0;"> <div class="cell">{%= description %}</div> <div class="cell text-right bold">{%= tax_amount %}</div> </div> ';
frappe.templates['customer_toolbar'] = '<div class="pos-bill-toolbar col-xs-9" style="display: flex; width: 70%;"> <div class="party-area" style="flex: 1;"> <span class="edit-customer-btn text-muted" style="display: inline;"> <a class="btn-open no-decoration" title="Edit Customer"> <i class="octicon octicon-pencil"></i> </a> </span> </div> <button class="btn btn-default list-customers-btn" style="margin-left: 12px"> <i class="octicon octicon-organization"></i> </button> </button> {% if (allow_delete) { %} <button class="btn btn-default btn-danger" style="margin: 0 5px 0 5px"> <i class="octicon octicon-trashcan"></i> </button> {% } %} </div>';
frappe.templates['pos_invoice_list'] = '<div class="pos-list-row" invoice-name = "{{name}}"> <div class="list-column cell subject" invoice-name = "{{name}}"> <input class="list-delete text-left" type="checkbox" style = "margin-right:5px"> <a class="grey list-id text-left customer-row" title="{{ customer }}">{%= customer %}</a> </div> <div class="list-column cell text-left customer-row"><span class="indicator {{data.indicator}}">{{ data.status }}</span></div> <div class="list-column cell text-right customer-row">{%= paid_amount %}</div> <div class="list-column cell text-right customer-row">{%= grand_total %}</div> </div> ';
frappe.templates['pos_payment'] = '<div class="pos_payment row"> <div class="row" style="padding: 0px 30px;"> <h3>{{ __("Total Amount") }}: <span class="label label-default" style="font-size:20px;padding:5px">{%= format_currency(grand_total, currency) %}</span></h3> </div> <div class="row amount-row"> <div class="col-xs-6 col-sm-3 text-center"> <p class="amount-label"> {{ __("Paid") }} <h3 class="paid_amount">{%= format_currency(paid_amount, currency) %}</h3></p> </div> <div class="col-xs-6 col-sm-3 text-center"> <p class="amount-label"> {{ __("Outstanding") }} <h3 class="outstanding_amount">{%= format_currency(outstanding_amount, currency) %} </h3></p> </div> <div class="col-xs-6 col-sm-3 text-center"> <p class="amount-label"> {{ __("Change") }} <input class="form-control text-right change_amount bold" type="text" idx="change_amount" value="{{format_number(change_amount, null, 2)}}"> </p> </div> <div class="col-xs-6 col-sm-3 text-center"> <p class="amount-label"> {{ __("Write off") }} <input class="form-control text-right write_off_amount bold" type="text" idx="write_off_amount" value="{{format_number(write_off_amount, null, 2)}}"> </p> </div> </div> <hr> <div class="row"> <div class="col-sm-6 "> <div class ="row multimode-payments"> </div> </div> <div class="col-sm-6 payment-toolbar"> {% for(var i=0; i<3; i++) { %} <div class="row"> {% for(var j=i*3; j<(i+1)*3; j++) { %} <button type="button" class="btn btn-default pos-keyboard-key">{{j+1}}</button> {% } %} </div> {% } %} <div class="row"> <button type="button" class="btn btn-default delete-btn">{{ __("Del") }}</button> <button type="button" class="btn btn-default pos-keyboard-key">0</button> <button type="button" class="btn btn-default pos-keyboard-key">.</button> </div> </div> </div> </div> ';
frappe.templates['payment_details'] = '<div class="row pos-payment-row" type="{{type}}" idx={{idx}}> <div class="col-xs-6" style="padding:20px">{{mode_of_payment}}</div> <div class="col-xs-6"> <div class="input-group"> <input disabled class="form-control text-right amount" idx="{{idx}}" type="text" value="{%= format_currency(amount, currency) %}"> <span class="input-group-btn"> <button type="button" class="btn btn-default clr" idx="{{idx}}" style="border:1px solid #d1d8dd">C</button> </span> </div> </div> </div>';
frappe.templates['item_selector'] = '<div class="row pos-item-area"> {% for (var i=0; i < data.length; i++) { var item = data[i]; %} <div class="col-xs-3 pos-item-wrapper"> <div class="pos-item" data-name="{{ item.name }}"> <div class="pos-item-image" {% if(item.image) { %}style="background-image: url({{ item.image }});"{% } else { %}style="background-color: {{ item.color }};"{% } %}> {% if(!item.image) { %}{{ item.abbr }}{% } %} </div> <div class="pos-item-text"> <h6 class="item-code ellipsis">{{ item.name }}</h6> </div> </div> </div> {% } %} </div>';
erpnext.ItemSelector = Class.extend({
init: function init(opts) {
$.extend(this, opts);
this.grid = this.frm.get_field("items").grid;
this.setup();
},
setup: function setup() {
var me = this;
if (!this.grid.add_items_button) {
this.grid.add_items_button = this.grid.add_custom_button(__('Add Items'), function () {
if (!me.dialog) {
me.make_dialog();
}
me.dialog.show();
me.render_items();
setTimeout(function () {
me.dialog.input.focus();
}, 1000);
});
}
},
make_dialog: function make_dialog() {
this.dialog = new frappe.ui.Dialog({
title: __('Add Items')
});
var body = $(this.dialog.body);
body.html('<div><p><input type="text" class="form-control"></p>\
<br><div class="results"></div></div>');
this.dialog.input = body.find('.form-control');
this.dialog.results = body.find('.results');
var me = this;
this.dialog.results.on('click', '.pos-item', function () {
me.add_item($(this).attr('data-name'));
});
this.dialog.input.on('keyup', function () {
if (me.timeout_id) {
clearTimeout(me.timeout_id);
}
me.timeout_id = setTimeout(function () {
me.render_items();
me.timeout_id = undefined;
}, 500);
});
},
add_item: function add_item(item_code) {
var added = false;
$.each(this.frm.doc.items || [], function (i, d) {
if (d.item_code === item_code) {
frappe.model.set_value(d.doctype, d.name, 'qty', d.qty + 1);
frappe.show_alert(__("Added {0} ({1})", [item_code, d.qty]));
added = true;
return false;
}
});
if (!added) {
var d = this.grid.add_new_row();
frappe.model.set_value(d.doctype, d.name, 'item_code', item_code);
frappe.after_ajax(function () {
setTimeout(function () {
frappe.model.set_value(d.doctype, d.name, 'qty', 1);
frappe.show_alert(__("Added {0} ({1})", [item_code, 1]));
}, 100);
});
}
},
render_items: function render_items() {
var args = erpnext.queries.item();
args.txt = this.dialog.input.val();
args.as_dict = 1;
var me = this;
frappe.link_search("Item", args, function (r) {
$.each(r.values, function (i, d) {
if (!d.image) {
d.abbr = frappe.get_abbr(d.item_name);
d.color = frappe.get_palette(d.item_name);
}
});
me.dialog.results.html(frappe.render_template('item_selector', { 'data': r.values }));
});
}
});
frappe.provide('frappe.help.help_links');
frappe.help.help_links['Form/Rename Tool'] = [{ label: 'Bulk Rename', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/data/bulk-rename' }];
frappe.help.help_links['List/User'] = [{ label: 'New User', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/users-and-permissions/adding-users' }, { label: 'Rename User', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/rename-user' }];
frappe.help.help_links['permission-manager'] = [{ label: 'Role Permissions Manager', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/users-and-permissions/role-based-permissions' }, { label: 'Managing Perm Level in Permissions Manager', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/managing-perm-level' }, { label: 'User Permissions', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/users-and-permissions/user-permissions' }, { label: 'Sharing', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/users-and-permissions/sharing' }, { label: 'Password', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/change-password' }];
frappe.help.help_links['Form/System Settings'] = [{ label: 'Naming Series', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/settings/system-settings' }];
frappe.help.help_links['data-import-tool'] = [{ label: 'Importing and Exporting Data', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/data/data-import-tool' }, { label: 'Overwriting Data from Data Import Tool', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/overwriting-data-from-data-import-tool' }];
frappe.help.help_links['module_setup'] = [{ label: 'Role Permissions Manager', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/users-and-permissions/role-based-permissions' }];
frappe.help.help_links['Form/Naming Series'] = [{ label: 'Naming Series', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/settings/naming-series' }, { label: 'Setting the Current Value for Naming Series', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/naming-series-current-value' }];
frappe.help.help_links['Form/Global Defaults'] = [{ label: 'Global Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/settings/global-defaults' }];
frappe.help.help_links['Form/Email Digest'] = [{ label: 'Email Digest', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/email/email-digest' }];
frappe.help.help_links['List/Print Heading'] = [{ label: 'Print Heading', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/print-headings' }];
frappe.help.help_links['List/Letter Head'] = [{ label: 'Letter Head', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/letter-head' }];
frappe.help.help_links['List/Address Template'] = [{ label: 'Address Template', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/address-template' }];
frappe.help.help_links['List/Terms and Conditions'] = [{ label: 'Terms and Conditions', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/terms-and-conditions' }];
frappe.help.help_links['List/Cheque Print Template'] = [{ label: 'Cheque Print Template', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/cheque-print-template' }];
frappe.help.help_links['List/Email Account'] = [{ label: 'Email Account', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/email/email-account' }];
frappe.help.help_links['List/Email Alert'] = [{ label: 'Email Alert', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/email/email-alerts' }];
frappe.help.help_links['Form/Email Alert'] = [{ label: 'Email Alert', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/email/email-alerts' }];
frappe.help.help_links['List/Email Digest'] = [{ label: 'Email Digest', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/email/email-digest' }];
frappe.help.help_links['List/Auto Email Report'] = [{ label: 'Auto Email Reports', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/email/email-reports' }];
frappe.help.help_links['Form/Print Settings'] = [{ label: 'Print Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/print-settings' }];
frappe.help.help_links['print-format-builder'] = [{ label: 'Print Format Builder', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/print-settings' }];
frappe.help.help_links['List/Print Heading'] = [{ label: 'Print Heading', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/print-headings' }];
frappe.help.help_links['Form/PayPal Settings'] = [{ label: 'PayPal Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/integrations/paypal-integration' }];
frappe.help.help_links['Form/Razorpay Settings'] = [{ label: 'Razorpay Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/integrations/razorpay-integration' }];
frappe.help.help_links['Form/Dropbox Settings'] = [{ label: 'Dropbox Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/integrations/dropbox-backup' }];
frappe.help.help_links['Form/LDAP Settings'] = [{ label: 'LDAP Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/integrations/ldap-integration' }];
frappe.help.help_links['Form/Stripe Settings'] = [{ label: 'Stripe Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/integrations/stripe-integration' }];
frappe.help.help_links['Form/Quotation'] = [{ label: 'Quotation', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/quotation' }, { label: 'Applying Discount', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/applying-discount' }, { label: 'Sales Person', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/sales-persons-in-the-sales-transactions' }, { label: 'Applying Margin', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/adding-margin' }];
frappe.help.help_links['List/Customer'] = [{ label: 'Customer', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/customer' }, { label: 'Credit Limit', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/credit-limit' }];
frappe.help.help_links['Form/Customer'] = [{ label: 'Customer', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/customer' }, { label: 'Credit Limit', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/credit-limit' }];
frappe.help.help_links['List/Sales Taxes and Charges Template'] = [{ label: 'Setting Up Taxes', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/setting-up-taxes' }];
frappe.help.help_links['Form/Sales Taxes and Charges Template'] = [{ label: 'Setting Up Taxes', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/setting-up-taxes' }];
frappe.help.help_links['List/Sales Order'] = [{ label: 'Sales Order', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/sales-order' }, { label: 'Recurring Sales Order', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' }, { label: 'Applying Discount', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/applying-discount' }];
frappe.help.help_links['Form/Sales Order'] = [{ label: 'Sales Order', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/sales-order' }, { label: 'Recurring Sales Order', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' }, { label: 'Applying Discount', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/applying-discount' }, { label: 'Drop Shipping', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/drop-shipping' }, { label: 'Sales Person', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/sales-persons-in-the-sales-transactions' }, { label: 'Close Sales Order', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/close-sales-order' }, { label: 'Applying Margin', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/adding-margin' }];
frappe.help.help_links['Form/Product Bundle'] = [{ label: 'Product Bundle', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/setup/product-bundle' }];
frappe.help.help_links['Form/Selling Settings'] = [{ label: 'Selling Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/setup/selling-settings' }];
frappe.help.help_links['List/Supplier'] = [{ label: 'Supplier', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/supplier' }];
frappe.help.help_links['Form/Supplier'] = [{ label: 'Supplier', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/supplier' }];
frappe.help.help_links['Form/Request for Quotation'] = [{ label: 'Request for Quotation', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/request-for-quotation' }, { label: 'RFQ Video', url: 'https://frappe.github.io/erpnext/user/videos/learn/request-for-quotation.html' }];
frappe.help.help_links['Form/Supplier Quotation'] = [{ label: 'Supplier Quotation', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/supplier-quotation' }];
frappe.help.help_links['Form/Buying Settings'] = [{ label: 'Buying Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/setup/buying-settings' }];
frappe.help.help_links['List/Purchase Order'] = [{ label: 'Purchase Order', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/purchase-order' }, { label: 'Recurring Purchase Order', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' }];
frappe.help.help_links['Form/Purchase Order'] = [{ label: 'Purchase Order', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/purchase-order' }, { label: 'Item UoM', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/articles/purchasing-in-different-unit' }, { label: 'Supplier Item Code', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/articles/maintaining-suppliers-part-no-in-item' }, { label: 'Recurring Purchase Order', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' }, { label: 'Subcontracting', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/subcontracting' }];
frappe.help.help_links['List/Purchase Taxes and Charges Template'] = [{ label: 'Setting Up Taxes', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/setting-up-taxes' }];
frappe.help.help_links['List/POS Profile'] = [{ label: 'POS Profile', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/pos-setting' }];
frappe.help.help_links['List/Price List'] = [{ label: 'Price List', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/price-lists' }];
frappe.help.help_links['List/Authorization Rule'] = [{ label: 'Authorization Rule', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/authorization-rule' }];
frappe.help.help_links['Form/SMS Settings'] = [{ label: 'SMS Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/sms-setting' }];
frappe.help.help_links['List/Stock Reconciliation'] = [{ label: 'Stock Reconciliation', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/stock-reconciliation-for-non-serialized-item' }];
frappe.help.help_links['Tree/Territory'] = [{ label: 'Territory', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/territory' }];
frappe.help.help_links['Form/Dropbox Backup'] = [{ label: 'Dropbox Backup', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/third-party-backups' }, { label: 'Setting Up Dropbox Backup', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/setting-up-dropbox-backups' }];
frappe.help.help_links['List/Workflow'] = [{ label: 'Workflow', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/workflows' }];
frappe.help.help_links['List/Company'] = [{ label: 'Company', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/company-setup' }, { label: 'Managing Multiple Companies', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/managing-multiple-companies' }, { label: 'Delete All Related Transactions for a Company', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/delete-a-company-and-all-related-transactions' }];
frappe.help.help_links['modules/Accounts'] = [{ label: 'Introduction to Accounts', url: 'http://frappe.github.io/erpnext/user/manual/en/accounts/' }, { label: 'Chart of Accounts', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/chart-of-accounts.html' }, { label: 'Multi Currency Accounting', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/multi-currency-accounting' }];
frappe.help.help_links['Tree/Account'] = [{ label: 'Chart of Accounts', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/chart-of-accounts' }, { label: 'Managing Tree Mastes', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/managing-tree-structure-masters' }];
frappe.help.help_links['Form/Sales Invoice'] = [{ label: 'Sales Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/sales-invoice' }, { label: 'Accounts Opening Balance', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/opening-accounts' }, { label: 'Sales Return', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/sales-return' }, { label: 'Recurring Sales Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' }];
frappe.help.help_links['List/Sales Invoice'] = [{ label: 'Sales Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/sales-invoice' }, { label: 'Accounts Opening Balance', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/opening-accounts' }, { label: 'Sales Return', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/sales-return' }, { label: 'Recurring Sales Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' }];
frappe.help.help_links['pos'] = [{ label: 'Point of Sale Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/point-of-sale-pos-invoice' }];
frappe.help.help_links['List/POS Profile'] = [{ label: 'Point of Sale Profile', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/pos-setting' }];
frappe.help.help_links['List/Purchase Invoice'] = [{ label: 'Purchase Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/purchase-invoice' }, { label: 'Accounts Opening Balance', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/opening-accounts' }, { label: 'Recurring Purchase Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' }];
frappe.help.help_links['List/Journal Entry'] = [{ label: 'Journal Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/journal-entry' }, { label: 'Advance Payment Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/advance-payment-entry' }, { label: 'Accounts Opening Balance', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/opening-accounts' }];
frappe.help.help_links['List/Payment Entry'] = [{ label: 'Payment Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/payment-entry' }];
frappe.help.help_links['List/Payment Request'] = [{ label: 'Payment Request', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/payment-request' }];
frappe.help.help_links['List/Asset'] = [{ label: 'Managing Fixed Assets', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/managing-fixed-assets' }];
frappe.help.help_links['List/Asset Category'] = [{ label: 'Asset Category', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/managing-fixed-assets' }];
frappe.help.help_links['Tree/Cost Center'] = [{ label: 'Budgeting', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/budgeting' }];
frappe.help.help_links['List/Item'] = [{ label: 'Item', url: 'http://frappe.github.io/erpnext/user/manual/en/stock/item' }, { label: 'Item Price', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-price' }, { label: 'Barcode', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/track-items-using-barcode' }, { label: 'Item Wise Taxation', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/item-wise-taxation' }, { label: 'Managing Fixed Assets', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/managing-fixed-assets' }, { label: 'Item Codification', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-codification' }, { label: 'Item Variants', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-variants' }, { label: 'Item Valuation', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-valuation-fifo-and-moving-average' }];
frappe.help.help_links['Form/Item'] = [{ label: 'Item', url: 'http://frappe.github.io/erpnext/user/manual/en/stock/item' }, { label: 'Item Price', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-price' }, { label: 'Barcode', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/track-items-using-barcode' }, { label: 'Item Wise Taxation', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/item-wise-taxation' }, { label: 'Managing Fixed Assets', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/managing-fixed-assets' }, { label: 'Item Codification', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-codification' }, { label: 'Item Variants', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-variants' }, { label: 'Item Valuation', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-valuation-fifo-and-moving-average' }];
frappe.help.help_links['List/Purchase Receipt'] = [{ label: 'Purchase Receipt', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/purchase-receipt' }, { label: 'Barcode', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/track-items-using-barcode' }];
frappe.help.help_links['List/Delivery Note'] = [{ label: 'Delivery Note', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/delivery-note' }, { label: 'Barcode', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/track-items-using-barcode' }, { label: 'Sales Return', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/sales-return' }];
frappe.help.help_links['Form/Delivery Note'] = [{ label: 'Delivery Note', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/delivery-note' }, { label: 'Sales Return', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/sales-return' }, { label: 'Barcode', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/track-items-using-barcode' }, { label: 'Subcontracting', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/subcontracting' }];
frappe.help.help_links['List/Installation Note'] = [{ label: 'Installation Note', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/installation-note' }];
frappe.help.help_links['Tree'] = [{ label: 'Managing Tree Structure Masters', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/managing-tree-structure-masters' }];
frappe.help.help_links['List/Budget'] = [{ label: 'Budgeting', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/budgeting' }];
frappe.help.help_links['List/Material Request'] = [{ label: 'Material Request', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/material-request' }, { label: 'Auto-creation of Material Request', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/auto-creation-of-material-request' }];
frappe.help.help_links['Form/Material Request'] = [{ label: 'Material Request', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/material-request' }, { label: 'Auto-creation of Material Request', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/auto-creation-of-material-request' }];
frappe.help.help_links['Form/Stock Entry'] = [{ label: 'Stock Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/stock-entry' }, { label: 'Stock Entry Types', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/stock-entry-purpose' }, { label: 'Repack Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/repack-entry' }, { label: 'Opening Stock', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/opening-stock' }, { label: 'Subcontracting', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/subcontracting' }];
frappe.help.help_links['List/Stock Entry'] = [{ label: 'Stock Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/stock-entry' }];
frappe.help.help_links['Tree/Warehouse'] = [{ label: 'Warehouse', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/warehouse' }];
frappe.help.help_links['List/Serial No'] = [{ label: 'Serial No', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/serial-no' }];
frappe.help.help_links['Form/Serial No'] = [{ label: 'Serial No', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/serial-no' }];
frappe.help.help_links['Form/Batch'] = [{ label: 'Batch', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/batch' }];
frappe.help.help_links['Form/Packing Slip'] = [{ label: 'Packing Slip', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/tools/packing-slip' }];
frappe.help.help_links['Form/Quality Inspection'] = [{ label: 'Quality Inspection', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/tools/quality-inspection' }];
frappe.help.help_links['Form/Landed Cost Voucher'] = [{ label: 'Landed Cost Voucher', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/tools/landed-cost-voucher' }];
frappe.help.help_links['Tree/Item Group'] = [{ label: 'Item Group', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/setup/item-group' }];
frappe.help.help_links['Form/Item Attribute'] = [{ label: 'Item Attribute', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/setup/item-attribute' }];
frappe.help.help_links['Form/UOM'] = [{ label: 'Fractions in UOM', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/managing-fractions-in-uom' }];
frappe.help.help_links['Form/Stock Reconciliation'] = [{ label: 'Opening Stock Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/opening-stock' }];
frappe.help.help_links['Form/Lead'] = [{ label: 'Lead', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/lead' }];
frappe.help.help_links['Form/Opportunity'] = [{ label: 'Opportunity', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/opportunity' }];
frappe.help.help_links['Form/Address'] = [{ label: 'Address', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/contact' }];
frappe.help.help_links['Form/Contact'] = [{ label: 'Contact', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/contact' }];
frappe.help.help_links['Form/Newsletter'] = [{ label: 'Newsletter', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/newsletter' }];
frappe.help.help_links['Form/Campaign'] = [{ label: 'Campaign', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/setup/campaign' }];
frappe.help.help_links['Tree/Sales Person'] = [{ label: 'Sales Person', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/setup/sales-person' }];
frappe.help.help_links['Form/Sales Person'] = [{ label: 'Sales Person Target', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/setup/sales-person-target-allocation' }];
frappe.help.help_links['List/Feedback Trigger'] = [{ label: 'Feedback Trigger', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/feedback/setting-up-feedback' }];
frappe.help.help_links['List/Feedback Request'] = [{ label: 'Feedback Request', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/feedback/submit-feedback' }];
frappe.help.help_links['List/Feedback Request'] = [{ label: 'Feedback Request', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/feedback/submit-feedback' }];
frappe.help.help_links['Form/BOM'] = [{ label: 'Bill of Material', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/bill-of-materials' }, { label: 'Nested BOM Structure', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/articles/nested-bom-structure' }];
frappe.help.help_links['Form/Production Order'] = [{ label: 'Production Order', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/production-order' }];
frappe.help.help_links['Form/Workstation'] = [{ label: 'Workstation', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/workstation' }];
frappe.help.help_links['Form/Operation'] = [{ label: 'Operation', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/operation' }];
frappe.help.help_links['Form/Production Planning Tool'] = [{ label: 'Production Planning Tool', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/tools/production-planning-tool' }];
frappe.help.help_links['Form/BOM Replace Tool'] = [{ label: 'BOM Replace Tool', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/tools/bom-replace-tool' }];
frappe.help.help_links['Form/Customize Form'] = [{ label: 'Custom Field', url: 'https://frappe.github.io/erpnext/user/manual/en/customize-erpnext/custom-field' }, { label: 'Customize Field', url: 'https://frappe.github.io/erpnext/user/manual/en/customize-erpnext/customize-form' }];
frappe.help.help_links['Form/Custom Field'] = [{ label: 'Custom Field', url: 'https://frappe.github.io/erpnext/user/manual/en/customize-erpnext/custom-field' }];
frappe.help.help_links['Form/Custom Field'] = [{ label: 'Custom Field', url: 'https://frappe.github.io/erpnext/user/manual/en/customize-erpnext/custom-field' }];frappe.templates['student_button'] = '<div class="col-sm-3"> <div class="checkbox"> <label> <input type="checkbox" data-group_roll_number="{{group_roll_number}}" data-student="{{student}}" data-student-name="{{student_name}}" class="students-check" {% if status === "Present" %} checked {% endif %} > {{ group_roll_number }} - {{ student_name }} </label> </div> </div>';
frappe.templates['assessment_result_tool'] = '<table class="table table-bordered assessment-result-tool"> <thead> <tr> <th style="width: 100px" rowspan="2">Student</th> <th style="width: 200px" rowspan="2">Student Name</th> {% for c in criteria %} <th class="score" style="width: 100px">{{ c.assessment_criteria }}</th> {% endfor %} <th class="score" style="width: 100px">Total Marks</th> </tr> <tr> {% for c in criteria %} <th class="score" style="width: 100px">{{ c.maximum_score }}</th> {% endfor %} <th class="score" style="width: 100px">{{max_total_score}}</th> </tr> </thead> <tbody> {% for s in students %} <tr {% if(s.assessment_details) { %} class="text-muted" {% } %} data-student="{{s.student}}"> <td>{{ s.student }}</td> <td>{{ s.student_name }}</td> {% for c in criteria %} <td> <input type="text" data-max-score="{{c.maximum_score}}" data-criteria="{{c.assessment_criteria}}" data-student="{{s.student}}" {% if(s.assessment_details) { %} disabled value="{{s.assessment_details[c.assessment_criteria]}}" {% } %}/> </td> {% endfor %} <td data-student="{{s.student}}" class="total-score"> {% if(s.assessment_details) { %} {{s.assessment_details.total_score}} {% } %} </td> </tr> {% endfor %} </tbody> </table>';