diff --git a/attributions.md b/attributions.md
new file mode 100644
index 0000000000..9cd6eb8f8f
--- /dev/null
+++ b/attributions.md
@@ -0,0 +1,7 @@
+## ERPNext includes these public works
+
+For Frappe Framework, please see attributions.md at https://github.com/frappe/frappe/
+
+#### Images
+
+POS Icon: https://thenounproject.com/icon/41958 by hunotika
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index 6b0d933e28..7227f742b4 100644
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -41,7 +41,3 @@ def get_items(price_list, sales_or_purchase, item=None):
item_det.item_code=i.name
where
%s""" % ('%(price_list)s', condition), args, as_dict=1)
-
-@frappe.whitelist()
-def get_mode_of_payment():
- return sorted([d.name for d in frappe.get_list("Mode of Payment")])
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 482f5df421..a289d0e876 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -9,6 +9,7 @@ cur_frm.pformat.print_heading = 'Invoice';
frappe.provide("erpnext.accounts");
erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.extend({
onload: function() {
+ var me = this;
this._super();
if(!this.frm.doc.__islocal && !this.frm.doc.customer && this.frm.doc.debit_to) {
@@ -22,7 +23,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
this.frm.set_value("is_pos", 1);
this.is_pos(function() {
if (cint(frappe.defaults.get_user_defaults("fs_pos_view"))===1)
- cur_frm.cscript.toggle_pos(true);
+ erpnext.pos.toggle(me.frm);
});
}
}
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 45afb0b324..9029c48a89 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -103,16 +103,6 @@
"permlevel": 0,
"read_only": 0
},
- {
- "fieldname": "is_pos",
- "fieldtype": "Check",
- "label": "Is POS",
- "oldfieldname": "is_pos",
- "oldfieldtype": "Check",
- "permlevel": 0,
- "print_hide": 1,
- "read_only": 0
- },
{
"fieldname": "company",
"fieldtype": "Link",
@@ -168,6 +158,16 @@
"reqd": 1,
"search_index": 0
},
+ {
+ "fieldname": "is_pos",
+ "fieldtype": "Check",
+ "label": "Is POS",
+ "oldfieldname": "is_pos",
+ "oldfieldtype": "Check",
+ "permlevel": 0,
+ "print_hide": 1,
+ "read_only": 0
+ },
{
"fieldname": "shipping_address_name",
"fieldtype": "Link",
@@ -1244,7 +1244,7 @@
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
- "modified": "2015-03-04 16:08:58.641155",
+ "modified": "2015-03-05 01:42:46.778216",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index c3b3c03c22..1bc5681231 100644
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -1,18 +1,11 @@
frappe.pages['pos'].on_page_load = function(wrapper) {
var page = frappe.ui.make_app_page({
parent: wrapper,
- title: __('Start POS'),
+ title: __('Start Point-of-Sale (POS)'),
single_column: true
});
- page.main.html('
\
-
' + __("Select type of transaction") + '
\
-
\
-
'
- + '
'
- + __("Make new POS Setting") + '
\
-
\
-
');
+ page.main.html(frappe.render_template("pos_page", {}));
var pos_type = frappe.ui.form.make_control({
parent: page.main.find(".select-type"),
@@ -34,6 +27,8 @@ frappe.pages['pos'].on_page_load = function(wrapper) {
pos_type.refresh();
+ pos_type.set_input("Sales Invoice");
+
page.main.find(".btn-primary").on("click", function() {
erpnext.open_as_pos = true;
new_doc(pos_type.get_value());
diff --git a/erpnext/accounts/page/pos/pos_page.html b/erpnext/accounts/page/pos/pos_page.html
new file mode 100644
index 0000000000..98cce009ad
--- /dev/null
+++ b/erpnext/accounts/page/pos/pos_page.html
@@ -0,0 +1,15 @@
+
+
+
{%= __("Select type of transaction") %}
+
+
+
+
+
+
+
+
+ {%= __("Make new POS Setting") %}
+
+
diff --git a/erpnext/public/images/pos.svg b/erpnext/public/images/pos.svg
new file mode 100644
index 0000000000..3d12d9cb86
--- /dev/null
+++ b/erpnext/public/images/pos.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/erpnext/public/js/pos/pos.js b/erpnext/public/js/pos/pos.js
index 91193a28e5..282d9b9d7e 100644
--- a/erpnext/public/js/pos/pos.js
+++ b/erpnext/public/js/pos/pos.js
@@ -335,19 +335,15 @@ erpnext.pos.PointOfSale = Class.extend({
if (!this.frm.doc.is_pos) {
this.frm.set_value("is_pos", 1);
}
- this.frm.page.clear_actions();
this.frm.page.set_primary_action(__("Pay"), function() {
me.make_payment();
});
- this.frm.toolbar.current_status = null;
} else if (this.frm.doc.docstatus===1) {
- this.frm.page.clear_actions();
this.frm.page.set_primary_action(__("New"), function() {
me.frm.pos_active = false;
erpnext.open_as_pos = true;
new_doc(me.frm.doctype);
});
- this.frm.toolbar.current_status = null;
}
},
refresh_delete_btn: function() {
@@ -382,6 +378,18 @@ erpnext.pos.PointOfSale = Class.extend({
this.frm.script_manager.trigger("calculate_taxes_and_totals");
this.refresh();
},
+ with_modes_of_payment: function(callback) {
+ var me = this;
+ if(me.modes_of_payment) {
+ callback();
+ } else {
+ me.modes_of_payment = [];
+ $.ajax("/api/resource/Mode of Payment").success(function(data) {
+ $.each(data.data, function(i, d) { me.modes_of_payment.push(d.name); });
+ callback();
+ });
+ }
+ },
make_payment: function() {
var me = this;
var no_of_items = this.frm.doc.items.length;
@@ -389,95 +397,92 @@ erpnext.pos.PointOfSale = Class.extend({
if (no_of_items == 0)
msgprint(__("Payment cannot be made for empty cart"));
else {
- frappe.call({
- method: 'erpnext.accounts.doctype.sales_invoice.pos.get_mode_of_payment',
- callback: function(r) {
- if(!r.message) {
- msgprint(__("Please add to Modes of Payment from Setup."))
- return;
+
+ this.with_modes_of_payment(function() {
+ // prefer cash payment!
+ var default_mode = me.modes_of_payment.indexOf(__("Cash"))!==-1 ? __("Cash") : undefined;
+
+ // show payment wizard
+ var dialog = new frappe.ui.Dialog({
+ width: 400,
+ title: 'Payment',
+ fields: [
+ {fieldtype:'Currency',
+ fieldname:'total_amount', label: __('Total Amount'), read_only:1,
+ "default": me.frm.doc.grand_total, read_only: 1},
+ {fieldtype:'Select', fieldname:'mode_of_payment',
+ label: __('Mode of Payment'),
+ options: me.modes_of_payment.join('\n'), reqd: 1,
+ "default": default_mode},
+ {fieldtype:'Currency', fieldname:'paid_amount', label:__('Amount Paid'),
+ reqd:1, "default": me.frm.doc.grand_total, hidden: 1, change: function() {
+ var values = dialog.get_values();
+ dialog.set_value("change", Math.round(values.paid_amount - values.total_amount));
+ dialog.get_input("change").trigger("change");
+
+ }},
+ {fieldtype:'Currency', fieldname:'change', label: __('Change'),
+ "default": 0.0, hidden: 1, change: function() {
+ var values = dialog.get_values();
+ var write_off_amount = (flt(values.paid_amount) - flt(values.change)) - values.total_amount;
+ dialog.get_field("write_off_amount").toggle(write_off_amount);
+ dialog.set_value("write_off_amount", write_off_amount);
+ }
+ },
+ {fieldtype:'Currency', fieldname:'write_off_amount',
+ label: __('Write Off'), default: 0.0, hidden: 1},
+ ]
+ });
+ me.dialog = dialog;
+ dialog.show();
+
+ // make read only
+ dialog.get_input("total_amount").prop("disabled", true);
+ dialog.get_input("write_off_amount").prop("disabled", true);
+
+ // toggle amount paid and change
+ dialog.get_input("mode_of_payment").on("change", function() {
+ var is_cash = dialog.get_value("mode_of_payment") === __("Cash");
+ dialog.get_field("paid_amount").toggle(is_cash);
+ dialog.get_field("change").toggle(is_cash);
+
+ if (is_cash && !dialog.get_value("change")) {
+ // set to nearest 5
+ var paid_amount = 5 * Math.ceil(dialog.get_value("total_amount") / 5);
+ dialog.set_value("paid_amount", paid_amount);
+ dialog.get_input("paid_amount").trigger("change");
}
+ }).trigger("change");
- var modes_of_payment = r.message;
-
- // prefer cash payment!
- var default_mode = modes_of_payment.indexOf(__("Cash"))!==-1 ? __("Cash") : undefined;
-
- // show payment wizard
- var dialog = new frappe.ui.Dialog({
- width: 400,
- title: 'Payment',
- fields: [
- {fieldtype:'Currency', fieldname:'total_amount', label: __('Total Amount'), read_only:1,
- options:"currency", default:me.frm.doc.grand_total, read_only: 1},
- {fieldtype:'Select', fieldname:'mode_of_payment', label: __('Mode of Payment'),
- options:modes_of_payment.join('\n'), reqd: 1, default: default_mode},
- {fieldtype:'Currency', fieldname:'paid_amount', label:__('Amount Paid'), reqd:1,
- options: "currency",
- default:me.frm.doc.grand_total, hidden: 1},
- {fieldtype:'Currency', fieldname:'change', label: __('Change'), options: "currency",
- default: 0.0, hidden: 1},
- {fieldtype:'Currency', fieldname:'write_off_amount', label: __('Write Off'), options: "currency",
- default: 0.0, hidden: 1},
- {fieldtype:'Button', fieldname:'pay', label:'Pay'}
- ]
- });
- dialog.show();
-
- // make read only
- dialog.get_input("total_amount").prop("disabled", true);
- dialog.get_input("write_off_amount").prop("disabled", true);
-
- dialog.get_input("paid_amount").on("change", function() {
- var values = dialog.get_values();
- dialog.set_value("change", Math.round(values.paid_amount - values.total_amount));
- dialog.get_input("change").trigger("change");
- });
-
- dialog.get_input("change").on("change", function() {
- var values = dialog.get_values();
- var write_off_amount = (flt(values.paid_amount) - flt(values.change)) - values.total_amount;
- dialog.set_value("write_off_amount", write_off_amount);
- dialog.fields_dict.write_off_amount.$wrapper.toggleClass("hide", !!!write_off_amount);
- });
-
- // toggle amount paid and change
- dialog.get_input("mode_of_payment").on("change", function() {
- var is_cash = dialog.get_value("mode_of_payment") === __("Cash");
- dialog.fields_dict.paid_amount.$wrapper.toggleClass("hide", !is_cash);
- dialog.fields_dict.change.$wrapper.toggleClass("hide", !is_cash);
-
- if (is_cash && !dialog.get_value("change")) {
- // set to nearest 5
- var paid_amount = 5 * Math.ceil(dialog.get_value("total_amount") / 5);
- dialog.set_value("paid_amount", paid_amount);
- dialog.get_input("paid_amount").trigger("change");
- }
- }).trigger("change");
-
- dialog.fields_dict.pay.input.onclick = function() {
- var values = dialog.get_values();
- var is_cash = values.mode_of_payment === __("Cash");
- if (!is_cash) {
- values.write_off_amount = values.change = 0.0;
- values.paid_amount = values.total_amount;
- }
- me.frm.set_value("mode_of_payment", values.mode_of_payment);
-
- var paid_amount = flt((flt(values.paid_amount) - flt(values.change)) / me.frm.doc.conversion_rate, precision("paid_amount"));
- me.frm.set_value("paid_amount", paid_amount);
-
- // specifying writeoff amount here itself, so as to avoid recursion issue
- me.frm.set_value("write_off_amount", me.frm.doc.base_grand_total - paid_amount);
- me.frm.set_value("outstanding_amount", 0);
-
- me.frm.savesubmit(this);
- dialog.hide();
- me.refresh();
- };
- }
+ me.set_pay_button(dialog);
});
}
},
+ set_pay_button: function(dialog) {
+ var me = this;
+ dialog.set_primary_action(__("Pay"), function() {
+ var values = dialog.get_values();
+ console.log(values);
+ var is_cash = values.mode_of_payment === __("Cash");
+ if (!is_cash) {
+ values.write_off_amount = values.change = 0.0;
+ values.paid_amount = values.total_amount;
+ }
+ me.frm.set_value("mode_of_payment", values.mode_of_payment);
+
+ var paid_amount = flt((flt(values.paid_amount) - flt(values.change)) / me.frm.doc.conversion_rate, precision("paid_amount"));
+ me.frm.set_value("paid_amount", paid_amount);
+
+ // specifying writeoff amount here itself, so as to avoid recursion issue
+ me.frm.set_value("write_off_amount", me.frm.doc.base_grand_total - paid_amount);
+ me.frm.set_value("outstanding_amount", 0);
+
+ me.frm.savesubmit(this);
+ dialog.hide();
+ me.refresh();
+ })
+
+ }
});
erpnext.pos.make_pos_btn = function(frm) {
@@ -486,28 +491,13 @@ erpnext.pos.make_pos_btn = function(frm) {
return;
}
- if(frm.doc.docstatus <= 1) {
- if(!frm.pos_active) {
- var btn_label = __("POS View"),
- icon = "icon-th";
- } else {
- var btn_label = __("Form View"),
- icon = "icon-file-text";
- }
+ if(!frm.pos_btn) {
+ frm.pos_btn = frm.page.add_action_icon("icon-th", function() {
+ erpnext.pos.toggle(frm) });
+ }
- if(erpnext.open_as_pos) {
- erpnext.pos.toggle(frm, true);
- erpnext.open_as_pos = false;
- }
-
- frm.$pos_btn && frm.$pos_btn.remove();
-
- frm.$pos_btn = frm.page.add_menu_item(btn_label, function() {
- erpnext.pos.toggle(frm);
- });
- } else {
- // hack: will avoid calling refresh from refresh
- setTimeout(function() { erpnext.pos.toggle(frm, false); }, 100);
+ if(erpnext.open_as_pos && !frm.pos_active) {
+ erpnext.pos.toggle(frm);
}
}
@@ -534,6 +524,7 @@ erpnext.pos.toggle = function(frm, show) {
frm.page.set_view(frm.pos_active ? "main" : "pos");
frm.pos_active = !frm.pos_active;
+ frm.toolbar.current_status = null;
frm.refresh();
// refresh