[design] Point of Sale
diff --git a/erpnext/public/js/pos/pos.html b/erpnext/public/js/pos/pos.html
index d26e0b6..1c337f4 100644
--- a/erpnext/public/js/pos/pos.html
+++ b/erpnext/public/js/pos/pos.html
@@ -2,10 +2,7 @@
     <div class="row">
     	<div class="col-sm-5 pos-bill-wrapper">
             <div class="pos-bill-toolbar row">
-                <div class="party-area col-xs-9"></div>
-                <div class="col-xs-3 text-right">
-        			<button class="btn btn-success make-payment hide">{%= __("Pay") %}</button>
-                </div>
+                <div class="party-area col-xs-12"></div>
             </div>
     		<div class="pos-bill">
     			<div class="item-cart">
@@ -35,10 +32,10 @@
                         <div class="col-xs-6"><h6>{%= __("Grand Total") %}</h6></div>
                         <div class="col-xs-6"><h6 class="grand-total text-right"></h6></div>
                     </div>
-                    <div class="row pos-bill-row paid-amount-area">
+                    <!-- <div class="row pos-bill-row paid-amount-area">
                         <div class="col-xs-6"><h6 class="text-muted">{%= __("Amount Paid") %}</h6></div>
                         <div class="col-xs-6"><input type="text" class="form-control paid-amount text-right"></div>
-                    </div>
+                    </div> -->
     			</div>
     		</div>
     	</div>
diff --git a/erpnext/public/js/pos/pos.js b/erpnext/public/js/pos/pos.js
index ae4c6a5..6950182 100644
--- a/erpnext/public/js/pos/pos.js
+++ b/erpnext/public/js/pos/pos.js
@@ -1,7 +1,9 @@
 // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
 // License: GNU General Public License v3. See license.txt
 
-erpnext.POS = Class.extend({
+frappe.provide("erpnext.pos");
+
+erpnext.pos.PointOfSale = Class.extend({
 	init: function(wrapper, frm) {
 		this.wrapper = wrapper;
 		this.frm = frm;
@@ -18,10 +20,6 @@
 		this.wrapper.find('input.discount-amount').on("change", function() {
 			frappe.model.set_value(me.frm.doctype, me.frm.docname, "discount_amount", this.value);
 		});
-
-		this.wrapper.find(".make-payment").on("click", function() {
-			me.make_payment();
-		})
 	},
 	check_transaction_type: function() {
 		var me = this;
@@ -130,7 +128,7 @@
 							item_price: format_currency(obj.price_list_rate, obj.currency),
 							item_name: obj.name===obj.item_name ? "" : obj.item_name,
 							item_image: obj.image
-						})).appendTo($wrap);
+						})).tooltip().appendTo($wrap);
 					});
 				}
 
@@ -216,12 +214,7 @@
 		var me = this;
 
 		this.refresh_item_list();
-		this.party_field.set_input(this.frm.doc[this.party.toLowerCase()]);
-		this.wrapper.find('input.discount-amount').val(this.frm.doc.discount_amount);
-
-		this.show_items_in_item_cart();
-		this.show_taxes();
-		this.set_totals();
+		this.refresh_fields();
 
 		// if form is local then only run all these functions
 		if (this.frm.doc.docstatus===0) {
@@ -229,13 +222,21 @@
 		}
 
 		this.disable_text_box_and_button();
-		this.hide_payment_button();
+		this.set_primary_action();
 
 		// If quotation to is not Customer then remove party
 		if (this.frm.doctype == "Quotation" && this.frm.doc.quotation_to!="Customer") {
 			this.party_field.$input.prop("disabled", true);
 		}
 	},
+	refresh_fields: function() {
+		this.party_field.set_input(this.frm.doc[this.party.toLowerCase()]);
+		this.wrapper.find('input.discount-amount').val(this.frm.doc.discount_amount);
+
+		this.show_items_in_item_cart();
+		this.show_taxes();
+		this.set_totals();
+	},
 	refresh_item_list: function() {
 		var me = this;
 		// refresh item list on change of price list
@@ -285,12 +286,6 @@
 			me.frm.doc.currency));
 		this.wrapper.find(".grand-total").text(format_currency(this.frm.doc[this.grand_total],
 			me.frm.doc.currency));
-
-		$(".paid-amount-area").toggle(!!this.frm.doc.paid_amount);
-		if(this.frm.doc.paid_amount) {
-			this.wrapper.find(".paid-amount").text(format_currency(this.frm.doc.paid_amount,
-				me.frm.doc.currency));
-		}
 	},
 	call_when_local: function() {
 		var me = this;
@@ -307,25 +302,10 @@
 			me.increase_decrease_qty($item, $(this).attr("data-action"));
 		});
 
-		// on td click toggle the highlighting of row
-		$(this.wrapper).find("#cart tbody tr td").on("click", function() {
-			var row = $(this).closest("tr");
-			if (row.attr("data-selected") == "false") {
-				row.attr("class", "warning");
-				row.attr("data-selected", "true");
-			}
-			else {
-				row.prop("class", null);
-				row.attr("data-selected", "false");
-			}
-			me.refresh_delete_btn();
-		});
-
-		me.refresh_delete_btn();
-		//me.focus();
+		this.focus();
 	},
 	focus: function() {
-		if(me.frm.doc[this.party].toLowerCase()) {
+		if(this.frm.doc[this.party.toLowerCase()]) {
 			this.search.$input.focus();
 		} else {
 			if(!(this.frm.doctype == "Quotation" && this.frm.doc.quotation_to!="Customer"))
@@ -353,12 +333,28 @@
 		this.wrapper.find(".pos-item-area").toggleClass("hide", me.frm.doc.docstatus!==0);
 
 	},
-	hide_payment_button: function() {
-		var toggle = !(this.frm.doctype == "Sales Invoice" && this.frm.doc.is_pos && this.frm.doc.docstatus===1);
-		$(this.wrapper)
-			.find(".make-payment")
-			.toggleClass("hide", toggle)
-			.prop("disabled", toggle);
+	set_primary_action: function() {
+		var me = this;
+		if (!this.frm.pos_active) return;
+
+		if (this.frm.doctype == "Sales Invoice" && this.frm.doc.docstatus===0) {
+			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() {
 		$(this.wrapper).find(".remove-items").toggle($(".item-cart .warning").length ? true : false);
@@ -395,7 +391,6 @@
 	make_payment: function() {
 		var me = this;
 		var no_of_items = this.frm.doc.items.length;
-		var mode_of_payment = [];
 
 		if (no_of_items == 0)
 			msgprint(__("Payment cannot be made for empty cart"));
@@ -407,32 +402,81 @@
 						msgprint(__("Please add to Modes of Payment from Setup."))
 						return;
 					}
-					for (x=0; x<=r.message.length - 1; x++) {
-						mode_of_payment.push(r.message[x].name);
-					}
+
+					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:'Data', fieldname:'total_amount', label:'Total Amount', read_only:1},
-							{fieldtype:'Select', fieldname:'mode_of_payment', label:'Mode of Payment',
-								options:mode_of_payment.join('\n'), reqd: 1},
+							{fieldtype:'Currency', fieldname:'total_amount', label: __('Total Amount'), read_only:1,
+								options:"currency", default:me.frm.doc.grand_total_export, 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_export, 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.set_values({
-						"total_amount": $(".grand-total").text()
-					});
 					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() {
-						me.frm.set_value("mode_of_payment", dialog.get_values().mode_of_payment);
-						me.frm.set_value("paid_amount", dialog.get_values().total_amount);
-						me.frm.cscript.mode_of_payment(me.frm.doc);
-						me.frm.save();
+						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.grand_total - paid_amount);
+						me.frm.set_value("outstanding_amount", 0);
+
+						me.frm.savesubmit(this);
 						dialog.hide();
 						me.refresh();
 					};
@@ -441,3 +485,65 @@
 		}
 	},
 });
+
+erpnext.pos.make_pos_btn = function(frm) {
+	// Show POS button only if it is enabled from features setup
+	if (cint(sys_defaults.fs_pos_view)!==1 || frm.doctype==="Material Request") {
+		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(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);
+	}
+}
+
+erpnext.pos.toggle = function(frm, show) {
+	// Check whether it is Selling or Buying cycle
+	var price_list = frappe.meta.has_field(cur_frm.doc.doctype, "selling_price_list") ?
+		frm.doc.selling_price_list : frm.doc.buying_price_list;
+
+	if((show===true && frm.pos_active) || (show===false && !frm.pos_active)) {
+		return;
+	}
+
+	if(show && !price_list) {
+		frappe.throw(__("Please select Price List"));
+	}
+
+	// make pos
+	if(!frm.pos) {
+		var wrapper = frm.page.add_view("pos", "<div>");
+		frm.pos = new erpnext.pos.PointOfSale(wrapper, frm);
+	}
+
+	// toggle view
+	frm.page.set_view(frm.pos_active ? "main" : "pos");
+	frm.pos_active = !frm.pos_active;
+
+	frm.refresh();
+
+	// refresh
+	if(frm.pos_active) {
+		frm.pos.refresh();
+	}
+}
diff --git a/erpnext/public/js/pos/pos_item.html b/erpnext/public/js/pos/pos_item.html
index 246eb4e..481f041 100644
--- a/erpnext/public/js/pos/pos_item.html
+++ b/erpnext/public/js/pos/pos_item.html
@@ -1,10 +1,9 @@
-<div class="pos-item" data-item-code="{%= item_code %}">
+<div class="pos-item" data-item-code="{%= item_code %}" title="{%= item_name || item_code %}">
 	<div class="pos-item-image {% if (!item_image) { %} no-image {% } %}"
 		 style="{% if (item_image) { %} background-image: url({%= item_image %}) {% } %}">
 	</div>
-	<h6 class="item-code text-ellipsis">{%= item_code %}</h6>
-	<div class="small text-ellipsis">
-		{% if (item_name) { %}{%= item_name %}<br>{% } %}
-		{%= item_price %}
+	<div class="pos-item-text">
+		<h6 class="item-code text-ellipsis">{%= item_code %}</h6>
+		<div class="small text-ellipsis">{%= item_price %}</div>
 	</div>
 </div>
diff --git a/erpnext/public/js/transaction.js b/erpnext/public/js/transaction.js
index 3b6beed..107114e 100644
--- a/erpnext/public/js/transaction.js
+++ b/erpnext/public/js/transaction.js
@@ -58,68 +58,10 @@
 		this.show_item_wise_taxes();
 		this.set_dynamic_labels();
 
-		// Show POS button only if it is enabled from features setup
-		if(cint(sys_defaults.fs_pos_view)===1 && this.frm.doctype!="Material Request") {
-			this.make_pos_btn();
-		}
+		erpnext.pos.make_pos_btn(this.frm);
+
 	},
 
-	make_pos_btn: function() {
-		var me = this;
-		if(this.frm.doc.docstatus <= 1) {
-			if(!this.pos_active) {
-				var btn_label = __("POS View"),
-					icon = "icon-th";
-			} else {
-				var btn_label = __("Form View"),
-					icon = "icon-file-text";
-			}
-
-			if(erpnext.open_as_pos) {
-				me.toggle_pos(true);
-				erpnext.open_as_pos = false;
-			}
-
-			this.$pos_btn && this.$pos_btn.remove();
-
-			this.$pos_btn = this.frm.page.add_menu_item(btn_label, function() {
-				me.toggle_pos();
-			});
-		} else {
-			// hack: will avoid calling refresh from refresh
-			setTimeout(function() { me.toggle_pos(false); }, 100);
-		}
-	},
-
-	toggle_pos: function(show) {
-		// Check whether it is Selling or Buying cycle
-		var price_list = frappe.meta.has_field(cur_frm.doc.doctype, "selling_price_list") ?
-			this.frm.doc.selling_price_list : this.frm.doc.buying_price_list;
-
-		if((show===true && this.pos_active) || (show===false && !this.pos_active))
-			return;
-
-		if(show && !price_list) {
-			frappe.throw(__("Please select Price List"));
-		}
-
-		// make pos
-		if(!this.frm.pos) {
-			var wrapper = this.frm.page.add_view("pos", "<div>");
-			this.frm.pos = new erpnext.POS(wrapper, this.frm);
-		}
-
-		// toggle view
-		this.frm.page.set_view(this.pos_active ? "main" : "pos");
-		this.pos_active = !this.pos_active;
-
-		// refresh
-		if(this.pos_active)
-			this.frm.pos.refresh();
-		this.frm.refresh();
-	},
-
-
 	item_code: function(doc, cdt, cdn) {
 		var me = this;
 		var item = frappe.get_doc(cdt, cdn);