Get Advances and auto allocate (#14970)

diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 60ccf1c..a6a97a7 100755
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -3401,6 +3401,39 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "allocate_advances_automatically", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Set Advances and Allocate (FIFO)", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "depends_on": "eval:!doc.allocate_advances_automatically", 
    "fieldname": "get_advances", 
    "fieldtype": "Button", 
    "hidden": 0, 
@@ -4526,7 +4559,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2018-07-30 08:35:17.736855",
+ "modified": "2018-07-31 18:35:17.736855",
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Purchase Invoice", 
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index ca6b47b..194c364 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -402,7 +402,7 @@
 // ------------
 cur_frm.cscript.hide_fields = function(doc) {
 	var parent_fields = ['project', 'due_date', 'is_opening', 'source', 'total_advance', 'get_advances',
-		'advances', 'advances', 'from_date', 'to_date'];
+		'advances', 'from_date', 'to_date'];
 
 	if(cint(doc.is_pos) == 1) {
 		hide_field(parent_fields);
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index bd0a4d7..94d46ec 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -681,65 +681,69 @@
    "unique": 0
   }, 
   {
-   "allow_bulk_edit": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
-   "fieldname": "column_break_21",
-   "fieldtype": "Column Break",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "column_break_21", 
+   "fieldtype": "Column Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
-  },
+  }, 
   {
-   "allow_bulk_edit": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
-   "depends_on": "eval: doc.is_return && doc.return_against",
-   "fieldname": "update_billed_amount_in_sales_order",
-   "fieldtype": "Check",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
-   "label": "Update Billed Amount in Sales Order",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "depends_on": "eval: doc.is_return && doc.return_against", 
+   "fieldname": "update_billed_amount_in_sales_order", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Update Billed Amount in Sales Order", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
-  },
+  }, 
   {
    "allow_bulk_edit": 0, 
    "allow_in_quick_entry": 0, 
@@ -2488,10 +2492,10 @@
    "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
-   "collapsible": 1,
+   "collapsible": 1, 
    "collapsible_depends_on": "", 
    "columns": 0, 
-   "depends_on": "",
+   "depends_on": "", 
    "fieldname": "loyalty_points_redemption", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -2524,7 +2528,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "depends_on": "redeem_loyalty_points",
+   "depends_on": "redeem_loyalty_points", 
    "fieldname": "loyalty_points", 
    "fieldtype": "Int", 
    "hidden": 0, 
@@ -2536,7 +2540,7 @@
    "in_standard_filter": 0, 
    "label": "Loyalty Points", 
    "length": 0, 
-   "no_copy": 1,
+   "no_copy": 1, 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 1, 
@@ -2557,7 +2561,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "depends_on": "redeem_loyalty_points",
+   "depends_on": "redeem_loyalty_points", 
    "fieldname": "loyalty_amount", 
    "fieldtype": "Currency", 
    "hidden": 0, 
@@ -2569,7 +2573,7 @@
    "in_standard_filter": 0, 
    "label": "Loyalty Amount", 
    "length": 0, 
-   "no_copy": 1,
+   "no_copy": 1, 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 1, 
@@ -2590,38 +2594,38 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "redeem_loyalty_points",
-   "fieldtype": "Check",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
-   "label": "Redeem Loyalty Points",
-   "length": 0,
-   "no_copy": 1,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 1,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
+   "fieldname": "redeem_loyalty_points", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Redeem Loyalty Points", 
+   "length": 0, 
+   "no_copy": 1, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
-  },
+  }, 
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "column_break_77", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -2653,8 +2657,8 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "depends_on": "",
-   "fetch_from": "customer.loyalty_program",
+   "depends_on": "", 
+   "fetch_from": "customer.loyalty_program", 
    "fieldname": "loyalty_program", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -2666,7 +2670,7 @@
    "in_standard_filter": 0, 
    "label": "Loyalty Program", 
    "length": 0, 
-   "no_copy": 1,
+   "no_copy": 1, 
    "options": "Loyalty Program", 
    "permlevel": 0, 
    "precision": "", 
@@ -2688,7 +2692,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "depends_on": "redeem_loyalty_points",
+   "depends_on": "redeem_loyalty_points", 
    "fieldname": "loyalty_redemption_account", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -2700,7 +2704,7 @@
    "in_standard_filter": 0, 
    "label": "Redemption Account", 
    "length": 0, 
-   "no_copy": 1,
+   "no_copy": 1, 
    "options": "Account", 
    "permlevel": 0, 
    "precision": "", 
@@ -2722,7 +2726,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "depends_on": "redeem_loyalty_points",
+   "depends_on": "redeem_loyalty_points", 
    "fieldname": "loyalty_redemption_cost_center", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -2734,7 +2738,7 @@
    "in_standard_filter": 0, 
    "label": "Redemption Cost Center", 
    "length": 0, 
-   "no_copy": 1,
+   "no_copy": 1, 
    "options": "Cost Center", 
    "permlevel": 0, 
    "precision": "", 
@@ -2795,8 +2799,8 @@
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
-   "in_filter": 0,
-   "in_global_search": 0,
+   "in_filter": 0, 
+   "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
    "label": "Apply Additional Discount On", 
@@ -3386,6 +3390,39 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "allocate_advances_automatically", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Allocate Advances Automatically (FIFO)", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "depends_on": "eval:!doc.allocate_advances_automatically", 
    "fieldname": "get_advances", 
    "fieldtype": "Button", 
    "hidden": 0, 
@@ -3398,10 +3435,10 @@
    "label": "Get Advances Received", 
    "length": 0, 
    "no_copy": 0, 
-   "oldfieldtype": "Button", 
-   "options": "", 
+   "options": "set_advances", 
    "permlevel": 0, 
-   "print_hide": 1, 
+   "precision": "", 
+   "print_hide": 0, 
    "print_hide_if_no_value": 0, 
    "read_only": 0, 
    "remember_last_selected_value": 0, 
@@ -5442,7 +5479,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2018-07-30 08:34:55.545490",
+ "modified": "2018-07-31 19:22:13.027242", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Sales Invoice", 
@@ -5536,6 +5573,5 @@
  "timeline_field": "customer", 
  "title_field": "title", 
  "track_changes": 1, 
- "track_seen": 1, 
- "track_views": 0
+ "track_seen": 1
 }
\ No newline at end of file
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index b8fa0ec..5175395 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -85,8 +85,12 @@
 		if self.doctype == 'Purchase Invoice':
 			self.validate_paid_amount()
 
-		if self.doctype in ['Purchase Invoice', 'Sales Invoice'] and self.is_return:
-			self.validate_qty()
+		if self.doctype in ['Purchase Invoice', 'Sales Invoice']:
+			if cint(self.allocate_advances_automatically):
+				self.set_advances()
+
+			if self.is_return:
+				self.validate_qty()
 
 	def validate_invoice_documents_schedule(self):
 		self.validate_payment_schedule_dates()
@@ -363,23 +367,6 @@
 		frappe.db.sql("""delete from `tab%s` where parentfield=%s and parent = %s
 			and allocated_amount = 0""" % (childtype, '%s', '%s'), (parentfield, self.name))
 
-	def set_advances(self):
-		"""Returns list of advances against Account, Party, Reference"""
-
-		res = self.get_advance_entries()
-
-		self.set("advances", [])
-		for d in res:
-			self.append("advances", {
-				"doctype": self.doctype + " Advance",
-				"reference_type": d.reference_type,
-				"reference_name": d.reference_name,
-				"reference_row": d.reference_row,
-				"remarks": d.remarks,
-				"advance_amount": flt(d.amount),
-				"allocated_amount": flt(d.amount) if d.against_order else 0
-			})
-
 	def apply_shipping_rule(self):
 		if self.shipping_rule:
 			shipping_rule = frappe.get_doc("Shipping Rule", self.shipping_rule)
@@ -400,6 +387,30 @@
 
 		return {}
 
+	def set_advances(self):
+		"""Returns list of advances against Account, Party, Reference"""
+
+		res = self.get_advance_entries()
+
+		self.set("advances", [])
+		advance_allocated = 0
+		for d in res:
+			if d.against_order:
+				allocated_amount = flt(d.amount)
+			else:
+				allocated_amount = min(self.grand_total - advance_allocated, d.amount)
+			advance_allocated += flt(allocated_amount)
+			
+			self.append("advances", {
+				"doctype": self.doctype + " Advance",
+				"reference_type": d.reference_type,
+				"reference_name": d.reference_name,
+				"reference_row": d.reference_row,
+				"remarks": d.remarks,
+				"advance_amount": flt(d.amount),
+				"allocated_amount": allocated_amount
+			})
+
 	def get_advance_entries(self, include_unallocated=True):
 		if self.doctype == "Sales Invoice":
 			party_account = self.debit_to
diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js
index 3f664ae..3dfc891 100644
--- a/erpnext/public/js/controllers/accounts.js
+++ b/erpnext/public/js/controllers/accounts.js
@@ -52,7 +52,19 @@
 	},
 	taxes_on_form_rendered: function(frm) {
 		erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm.open_grid_row());
-	}
+	},
+
+	allocate_advances_automatically: function(frm) {
+		if(frm.doc.allocate_advances_automatically) {
+			frappe.call({
+				doc: frm.doc,
+				method: "set_advances",
+				callback: function(r, rt) {
+					refresh_field("advances");
+				}
+			})
+		}
+	}	
 });
 
 frappe.ui.form.on('Sales Invoice Payment', {
@@ -129,7 +141,6 @@
 	});
 }
 
-
 cur_frm.cscript.account_head = function(doc, cdt, cdn) {
 	var d = locals[cdt][cdn];
 	if(!d.charge_type && d.account_head){