Merge pull request #16724 from rohitwaghchaure/user_progress_issue

fix: user progress issue
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 465c283..049a8a0 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
 from erpnext.hooks import regional_overrides
 from frappe.utils import getdate
 
-__version__ = '11.1.6'
+__version__ = '11.1.9'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index f303301..8161cc6 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -6,7 +6,7 @@
 import frappe, erpnext, json
 from frappe import _, scrub, ValidationError
 from frappe.utils import flt, comma_or, nowdate, getdate
-from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on
+from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on, get_allow_cost_center_in_entry_of_bs_account
 from erpnext.accounts.party import get_party_account
 from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
 from erpnext.setup.utils import get_exchange_rate
@@ -564,8 +564,8 @@
 			.format(frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"]))
 
 	# Add cost center condition
-	if args.get("cost_center"):
-		condition += " and cost_center='%s'" % args.get("cost_center")
+	if args.get("cost_center") and get_allow_cost_center_in_entry_of_bs_account():
+			condition += " and cost_center='%s'" % args.get("cost_center")
 
 	outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"),
 		args.get("party_account"), condition=condition)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 8911ddf..b1a851a 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -201,7 +201,8 @@
 					get_query: function() {
 						var filters = {
 							docstatus: 1,
-							company: me.frm.doc.company
+							company: me.frm.doc.company,
+							is_return: 0
 						};
 						if(me.frm.doc.customer) filters["customer"] = me.frm.doc.customer;
 						return {
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index abd201f..4cf3a1a 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -24,7 +24,6 @@
 from erpnext.accounts.doctype.loyalty_program.loyalty_program import \
 	get_loyalty_program_details_with_points, get_loyalty_details, validate_loyalty_points
 from erpnext.accounts.deferred_revenue import validate_service_stop_date
-from erpnext.controllers.accounts_controller import on_submit_regional, on_cancel_regional
 
 from erpnext.healthcare.utils import manage_invoice_submit_cancel
 
@@ -199,8 +198,6 @@
 		if "Healthcare" in active_domains:
 			manage_invoice_submit_cancel(self, "on_submit")
 
-		on_submit_regional(self)
-
 	def validate_pos_paid_amount(self):
 		if len(self.payments) == 0 and self.is_pos:
 			frappe.throw(_("At least one mode of payment is required for POS invoice."))
@@ -256,8 +253,6 @@
 		if "Healthcare" in active_domains:
 			manage_invoice_submit_cancel(self, "on_cancel")
 
-		on_cancel_regional(self)
-
 	def update_status_updater_args(self):
 		if cint(self.update_stock):
 			self.status_updater.extend([{
@@ -1017,9 +1012,10 @@
 			for serial_no in item.serial_no.split("\n"):
 				sales_invoice = frappe.db.get_value("Serial No", serial_no, "sales_invoice")
 				if sales_invoice and self.name != sales_invoice:
-					frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}".format(
-						serial_no, sales_invoice
-					)))
+					sales_invoice_company = frappe.db.get_value("Sales Invoice", sales_invoice, "company")
+					if sales_invoice_company == self.company:
+						frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}"
+							.format(serial_no, sales_invoice)))
 
 	def update_project(self):
 		if self.project:
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 95cb351..b8c9854 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -495,6 +495,7 @@
 			values.append(self.filters.get(party_type_field))
 
 		if party_type_field=="customer":
+			account_type = "Receivable"
 			if self.filters.get("customer_group"):
 				lft, rgt = frappe.db.get_value("Customer Group",
 					self.filters.get("customer_group"), ["lft", "rgt"])
@@ -529,12 +530,18 @@
 						or (steam.parent = against_voucher and steam.parenttype = against_voucher_type)
 						or (steam.parent = party and steam.parenttype = 'Customer')))""".format(lft, rgt))
 
-		if party_type_field=="supplier":
+		elif party_type_field=="supplier":
+			account_type = "Payable"
 			if self.filters.get("supplier_group"):
 				conditions.append("""party in (select name from tabSupplier
 					where supplier_group=%s)""")
 				values.append(self.filters.get("supplier_group"))
 
+		accounts = [d.name for d in frappe.get_all("Account",
+			filters={"account_type": account_type, "company": self.filters.company})]
+		conditions.append("account in (%s)" % ','.join(['%s'] *len(accounts)))
+		values += accounts
+
 		return " and ".join(conditions), values
 
 	def get_gl_entries_for(self, party, party_type, against_voucher_type, against_voucher):
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index 09cf5b1..2c7bd72 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -270,7 +270,7 @@
 			for period in period_list:
 				total_row.setdefault(period.key, 0.0)
 				total_row[period.key] += row.get(period.key, 0.0)
-				row[period.key] = 0.0
+				row[period.key] = row.get(period.key, 0.0)
 
 			total_row.setdefault("total", 0.0)
 			total_row["total"] += flt(row["total"])
diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py
index 01211a9..67105e5 100644
--- a/erpnext/accounts/report/gross_profit/gross_profit.py
+++ b/erpnext/accounts/report/gross_profit/gross_profit.py
@@ -135,9 +135,9 @@
 				row.buying_rate, row.base_rate = 0.0, 0.0
 
 			# calculate gross profit
-			row.gross_profit = row.base_amount - row.buying_amount
+			row.gross_profit = flt(row.base_amount - row.buying_amount, 3)
 			if row.base_amount:
-				row.gross_profit_percent = (row.gross_profit / row.base_amount) * 100.0
+				row.gross_profit_percent = flt((row.gross_profit / row.base_amount) * 100.0, 3)
 			else:
 				row.gross_profit_percent = 0.0
 
@@ -174,8 +174,8 @@
 						self.grouped_data.append(row)
 
 	def set_average_rate(self, new_row):
-		new_row.gross_profit = new_row.base_amount - new_row.buying_amount
-		new_row.gross_profit_percent = ((new_row.gross_profit / new_row.base_amount) * 100.0) \
+		new_row.gross_profit = flt(new_row.base_amount - new_row.buying_amount,3)
+		new_row.gross_profit_percent = flt(((new_row.gross_profit / new_row.base_amount) * 100.0),3) \
 			if new_row.base_amount else 0
 		new_row.buying_rate = (new_row.buying_amount / new_row.qty) if new_row.qty else 0
 		new_row.base_rate = (new_row.base_amount / new_row.qty) if new_row.qty else 0
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 5a765aa..34bbe7b 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1138,11 +1138,3 @@
 @erpnext.allow_regional
 def validate_regional(doc):
 	pass
-
-@erpnext.allow_regional
-def on_submit_regional(doc):
-	pass
-
-@erpnext.allow_regional
-def on_cancel_regional(doc):
-	pass
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 2a871f0..ccdd412 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -202,7 +202,8 @@
 		"validate": "erpnext.portal.doctype.products_settings.products_settings.home_page_is_products"
 	},
 	"Sales Invoice": {
-		"on_submit": "erpnext.regional.france.utils.create_transaction_log",
+		"on_submit": ["erpnext.regional.france.utils.create_transaction_log", "erpnext.regional.italy.utils.sales_invoice_on_submit"],
+		"on_cancel": "erpnext.regional.italy.utils.sales_invoice_on_cancel",
 		"on_trash": "erpnext.regional.check_deletion_permission"
 	},
 	"Payment Entry": {
@@ -210,7 +211,7 @@
 		"on_trash": "erpnext.regional.check_deletion_permission"
 	},
 	'Address': {
-		'validate': 'erpnext.regional.india.utils.validate_gstin_for_india'
+		'validate': ['erpnext.regional.india.utils.validate_gstin_for_india', 'erpnext.regional.italy.utils.set_state_code']
 	},
 	('Sales Invoice', 'Purchase Invoice', 'Delivery Note'): {
 		'validate': 'erpnext.regional.india.utils.set_place_of_supply'
@@ -305,7 +306,5 @@
 	'Italy': {
 		'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.italy.utils.update_itemised_tax_data',
 		'erpnext.controllers.accounts_controller.validate_regional': 'erpnext.regional.italy.utils.sales_invoice_validate',
-		'erpnext.controllers.accounts_controller.on_submit_regional': 'erpnext.regional.italy.utils.sales_invoice_on_submit',
-		'erpnext.controllers.accounts_controller.on_cancel_regional': 'erpnext.regional.italy.utils.sales_invoice_on_cancel'
 	}
 }
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 6b7c0f7..b85f38b 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -487,7 +487,6 @@
 
 	add_block_dates(events, start, end, employee, company)
 	add_holidays(events, start, end, employee, company)
-
 	return events
 
 def add_department_leaves(events, start, end, employee, company):
@@ -500,10 +499,22 @@
 	department_employees = frappe.db.sql_list("""select name from tabEmployee where department=%s
 		and company=%s""", (department, company))
 
-	match_conditions = "and employee in (\"%s\")" % '", "'.join(department_employees)
-	add_leaves(events, start, end, match_conditions=match_conditions)
+	filter_conditions = "employee in (\"%s\")" % '", "'.join(department_employees)
+	add_leaves(events, start, end, filter_conditions=filter_conditions)
 
-def add_leaves(events, start, end, match_conditions=None):
+def add_leaves(events, start, end, filter_conditions=None):
+	conditions = []
+
+	if filter_conditions:
+		conditions.append(filter_conditions)
+
+	if not cint(frappe.db.get_value("HR Settings", None, "show_leaves_of_all_department_members_in_calendar")):
+		from frappe.desk.reportview import build_match_conditions
+		match_conditions = build_match_conditions("Leave Application")
+
+		if match_conditions:
+			conditions.append(match_conditions)
+
 	query = """select name, from_date, to_date, employee_name, half_day,
 		status, employee, docstatus
 		from `tabLeave Application` where
@@ -511,8 +522,8 @@
 		and docstatus < 2
 		and status!="Rejected" """
 
-	if match_conditions:
-		query += match_conditions
+	if conditions:
+		query += ' and ' + ' and '.join(conditions)
 
 	for d in frappe.db.sql(query, {"start":start, "end": end}, as_dict=True):
 		e = {
diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py
index 6d082bd..2f2ad00 100644
--- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py
+++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py
@@ -41,12 +41,19 @@
 						work_done = nm and nm[0][3] or ''
 					else:
 						status = 'Open'
-						mntc_date = ''
-						service_person = ''
-						work_done = ''
+						mntc_date = None
+						service_person = None
+						work_done = None
 
-				frappe.db.sql("update `tabWarranty Claim` set resolution_date=%s, resolved_by=%s, resolution_details=%s, status=%s where name =%s",(mntc_date,service_person,work_done,status,d.prevdoc_docname))
+				wc_doc = frappe.get_doc('Warranty Claim', d.prevdoc_docname)
+				wc_doc.update({
+					'resolution_date': mntc_date,
+					'resolved_by': service_person,
+					'resolution_details': work_done,
+					'status': status
+				})
 
+				wc_doc.db_update()
 
 	def check_if_last_visit(self):
 		"""check if last maintenance visit against same sales order/ Warranty Claim"""
diff --git a/erpnext/patches/v11_0/make_italian_localization_fields.py b/erpnext/patches/v11_0/make_italian_localization_fields.py
index b0b5ef1..fa77149 100644
--- a/erpnext/patches/v11_0/make_italian_localization_fields.py
+++ b/erpnext/patches/v11_0/make_italian_localization_fields.py
@@ -3,12 +3,26 @@
 
 from __future__ import unicode_literals
 from erpnext.regional.italy.setup import make_custom_fields, setup_report
+from erpnext.regional.italy import state_codes
 import frappe
 
-def execute():
-    company = frappe.get_all('Company', filters = {'country': 'Italy'})
-    if not company:
-      return
 
-    make_custom_fields()
-    setup_report()
+def execute():
+	company = frappe.get_all('Company', filters = {'country': 'Italy'})
+	if not company:
+		return
+
+	frappe.reload_doc('regional', 'report', 'electronic_invoice_register')
+	make_custom_fields()
+	setup_report()
+
+	# Set state codes
+	condition = ""
+	for state, code in state_codes.items():
+		condition += " when '{0}' then '{1}'".format(frappe.db.escape(state), frappe.db.escape(code))
+
+	if condition:
+		frappe.db.sql("""
+			UPDATE tabAddress set state_code = (case state {condition} end)
+			WHERE country in ('Italy', 'Italia', 'Italian Republic', 'Repubblica Italiana')
+		""".format(condition=condition))
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 64085a8..389e25e 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -255,11 +255,16 @@
 		// get valid options for tree based on user permission & locals dict
 		let unscrub_option = frappe.model.unscrub(option);
 		let user_permission = frappe.defaults.get_user_permissions();
+		let options;
+
 		if(user_permission && user_permission[unscrub_option]) {
-			return user_permission[unscrub_option].map(perm => perm.doc);
+			options = user_permission[unscrub_option].map(perm => perm.doc);
 		} else {
-			return $.map(locals[`:${unscrub_option}`], function(c) { return c.name; }).sort();
+			options = $.map(locals[`:${unscrub_option}`], function(c) { return c.name; }).sort();
 		}
+
+		// filter unique values, as there may be multiple user permissions for any value
+		return options.filter((value, index, self) => self.indexOf(value) === index);
 	},
 	get_tree_default: function(option) {
 		// set default for a field based on user permission
diff --git a/erpnext/regional/italy/__init__.py b/erpnext/regional/italy/__init__.py
index 22bf84e..ef1d582 100644
--- a/erpnext/regional/italy/__init__.py
+++ b/erpnext/regional/italy/__init__.py
@@ -61,3 +61,19 @@
     "D-Differita",
     "S-Scissione dei Pagamenti"
 ]
+
+state_codes = {'Siracusa': 'SR', 'Bologna': 'BO', 'Grosseto': 'GR', 'Caserta': 'CE', 'Alessandria': 'AL', 'Ancona': 'AN', 'Pavia': 'PV',
+ 'Benevento or Beneventum': 'BN', 'Modena': 'MO', 'Lodi': 'LO', 'Novara': 'NO', 'Avellino': 'AV', 'Verona': 'VR', 'Forli-Cesena': 'FC',
+ 'Caltanissetta': 'CL', 'Brescia': 'BS', 'Rieti': 'RI', 'Treviso': 'TV', 'Ogliastra': 'OG', 'Olbia-Tempio': 'OT', 'Bergamo': 'BG',
+ 'Napoli': 'NA', 'Campobasso': 'CB', 'Fermo': 'FM', 'Roma': 'RM', 'Lucca': 'LU', 'Rovigo': 'RO', 'Piacenza': 'PC', 'Monza and Brianza': 'MB',
+ 'La Spezia': 'SP', 'Pescara': 'PE', 'Vercelli': 'VC', 'Enna': 'EN', 'Nuoro': 'NU', 'Medio Campidano': 'MD', 'Trieste': 'TS', 'Aosta': 'AO',
+ 'Firenze': 'FI', 'Trapani': 'TP', 'Messina': 'ME', 'Teramo': 'TE', 'Udine': 'UD', 'Verbano-Cusio-Ossola': 'VB', 'Padua': 'PD',
+ 'Reggio Emilia': 'RE', 'Frosinone': 'FR', 'Taranto': 'TA', 'Catanzaro': 'CZ', 'Belluno': 'BL', 'Pordenone': 'PN', 'Viterbo': 'VT',
+ 'Gorizia': 'GO', 'Vatican City': 'SCV', 'Ferrara': 'FE', 'Chieti': 'CH', 'Crotone': 'KR', 'Foggia': 'FG', 'Perugia': 'PG', 'Bari': 'BA',
+ 'Massa-Carrara': 'MS', 'Pisa': 'PI', 'Latina': 'LT', 'Salerno': 'SA', 'Turin': 'TO', 'Lecco': 'LC', 'Lecce': 'LE', 'Pistoia': 'PT', 'Como': 'CO',
+ 'Barletta-Andria-Trani': 'BT', 'Mantua': 'MN', 'Ragusa': 'RG', 'Macerata': 'MC', 'Imperia': 'IM', 'Palermo': 'PA', 'Matera': 'MT', "L'Aquila": 'AQ',
+ 'Milano': 'MI', 'Catania': 'CT', 'Pesaro e Urbino': 'PU', 'Potenza': 'PZ', 'Republic of San Marino': 'RSM', 'Genoa': 'GE', 'Brindisi': 'BR',
+ 'Cagliari': 'CA', 'Siena': 'SI', 'Vibo Valentia': 'VV', 'Reggio Calabria': 'RC', 'Ascoli Piceno': 'AP', 'Carbonia-Iglesias': 'CI', 'Oristano': 'OR',
+ 'Asti': 'AT', 'Ravenna': 'RA', 'Vicenza': 'VI', 'Savona': 'SV', 'Biella': 'BI', 'Rimini': 'RN', 'Agrigento': 'AG', 'Prato': 'PO', 'Cuneo': 'CN',
+ 'Cosenza': 'CS', 'Livorno or Leghorn': 'LI', 'Sondrio': 'SO', 'Cremona': 'CR', 'Isernia': 'IS', 'Trento': 'TN', 'Terni': 'TR', 'Bolzano/Bozen': 'BZ',
+ 'Parma': 'PR', 'Varese': 'VA', 'Venezia': 'VE', 'Sassari': 'SS', 'Arezzo': 'AR'}
\ No newline at end of file
diff --git a/erpnext/regional/italy/e-invoice.xml b/erpnext/regional/italy/e-invoice.xml
index 1c416ee..34053bd 100644
--- a/erpnext/regional/italy/e-invoice.xml
+++ b/erpnext/regional/italy/e-invoice.xml
@@ -6,8 +6,8 @@
 <Indirizzo>{{ address.address_line1 }}</Indirizzo>
 <CAP>{{ address.pincode }}</CAP>
 <Comune>{{ address.city }}</Comune>
-{%- if address.state %}
-<Provincia>{{ address.state }}</Provincia>
+{%- if address.state_code %}
+<Provincia>{{ address.state_code }}</Provincia>
 {%- endif %}
 <Nazione>{{ address.country_code|upper }}</Nazione>
 {%- endmacro %}
diff --git a/erpnext/regional/italy/setup.py b/erpnext/regional/italy/setup.py
index b4ab26f..a9de2d1 100644
--- a/erpnext/regional/italy/setup.py
+++ b/erpnext/regional/italy/setup.py
@@ -10,12 +10,12 @@
 from erpnext.regional.italy import fiscal_regimes, tax_exemption_reasons, mode_of_payment_codes, vat_collectability_options
 
 def setup(company=None, patch=True):
-    make_custom_fields()
-    setup_report()
+	make_custom_fields()
+	setup_report()
 
 def make_custom_fields(update=True):
-    invoice_item_fields = [
-        dict(fieldname='tax_rate', label='Tax Rate',
+	invoice_item_fields = [
+		dict(fieldname='tax_rate', label='Tax Rate',
 			fieldtype='Float', insert_after='description',
 			print_hide=1, hidden=1, read_only=1),
 		dict(fieldname='tax_amount', label='Tax Amount',
@@ -24,133 +24,135 @@
 		dict(fieldname='total_amount', label='Total Amount',
 			fieldtype='Currency', insert_after='tax_amount',
 			print_hide=1, hidden=1, read_only=1, options="currency")
-    ]
+	]
 
-    custom_fields = {
-        'Company': [
-            dict(fieldname='sb_e_invoicing', label='E-Invoicing',
-			    fieldtype='Section Break', insert_after='date_of_establishment', print_hide=1),
-            dict(fieldname='fiscal_regime', label='Fiscal Regime',
-			    fieldtype='Select', insert_after='sb_e_invoicing', print_hide=1,
-                options="\n".join(map(lambda x: x.decode('utf-8'), fiscal_regimes))),
-            dict(fieldname='fiscal_code', label='Fiscal Code', fieldtype='Data', insert_after='fiscal_regime', print_hide=1,
-                description=_("Applicable if the company is an Individual or a Proprietorship")),
-            dict(fieldname='vat_collectability', label='VAT Collectability',
-			    fieldtype='Select', insert_after='fiscal_code', print_hide=1,
-                options="\n".join(map(lambda x: x.decode('utf-8'), vat_collectability_options))),
-            dict(fieldname='cb_e_invoicing1', fieldtype='Column Break', insert_after='vat_collectability', print_hide=1),
-            dict(fieldname='registrar_office_province', label='Province of the Registrar Office',
-			    fieldtype='Data', insert_after='cb_e_invoicing1', print_hide=1, length=2),
-            dict(fieldname='registration_number', label='Registration Number',
-			    fieldtype='Data', insert_after='registrar_office_province', print_hide=1, length=20),
-            dict(fieldname='share_capital_amount', label='Share Capital',
-			    fieldtype='Currency', insert_after='registration_number', print_hide=1,
-                description=_('Applicable if the company is SpA, SApA or SRL')),
-            dict(fieldname='no_of_members', label='No of Members',
-			    fieldtype='Select', insert_after='share_capital_amount', print_hide=1,
-                options="\nSU-Socio Unico\nSM-Piu Soci", description=_("Applicable if the company is a limited liability company")),
-            dict(fieldname='liquidation_state', label='Liquidation State',
-			    fieldtype='Select', insert_after='no_of_members', print_hide=1,
-                options="\nLS-In Liquidazione\nLN-Non in Liquidazione")
-        ],
-        'Sales Taxes and Charges': [
-            dict(fieldname='tax_exemption_reason', label='Tax Exemption Reason',
-                fieldtype='Select', insert_after='included_in_print_rate', print_hide=1,
-                depends_on='eval:doc.charge_type!="Actual" && doc.rate==0.0',
-                options="\n" + "\n".join(map(lambda x: x.decode('utf-8'), tax_exemption_reasons))),
-            dict(fieldname='tax_exemption_law', label='Tax Exempt Under',
-                fieldtype='Text', insert_after='tax_exemption_reason', print_hide=1,
-                depends_on='eval:doc.charge_type!="Actual" && doc.rate==0.0')
-        ],
-        'Customer': [
-            dict(fieldname='fiscal_code', label='Fiscal Code', fieldtype='Data', insert_after='tax_id', print_hide=1),
-            dict(fieldname='recipient_code', label='Recipient Code',
-                fieldtype='Data', insert_after='fiscal_code', print_hide=1, default="0000000"),
-            dict(fieldname='pec', label='Recipient PEC',
-                fieldtype='Data', insert_after='fiscal_code', print_hide=1),
-            dict(fieldname='is_public_administration', label='Is Public Administration',
-			    fieldtype='Check', insert_after='is_internal_customer', print_hide=1,
-                description=_("Set this if the customer is a Public Administration company."),
-                depends_on='eval:doc.customer_type=="Company"'),
-            dict(fieldname='first_name', label='First Name', fieldtype='Data',
-                insert_after='salutation', print_hide=1, depends_on='eval:doc.customer_type!="Company"'),
-            dict(fieldname='last_name', label='Last Name', fieldtype='Data',
-                insert_after='first_name', print_hide=1, depends_on='eval:doc.customer_type!="Company"')
-        ],
-        'Mode of Payment': [
-            dict(fieldname='mode_of_payment_code', label='Code',
-		    fieldtype='Select', insert_after='included_in_print_rate', print_hide=1,
-            options="\n".join(map(lambda x: x.decode('utf-8'), mode_of_payment_codes)))
-        ],
-        'Payment Schedule': [
-            dict(fieldname='mode_of_payment_code', label='Code',
-                fieldtype='Select', insert_after='mode_of_payment', print_hide=1,
-                options="\n".join(map(lambda x: x.decode('utf-8'), mode_of_payment_codes)),
-                fetch_from="mode_of_payment.mode_of_payment_code", read_only=1),
-            dict(fieldname='bank_account', label='Bank Account',
-                fieldtype='Link', insert_after='mode_of_payment_code', print_hide=1,
-                options="Bank Account"),
-            dict(fieldname='bank_account_name', label='Bank Account Name',
-                fieldtype='Data', insert_after='bank_account', print_hide=1,
-                fetch_from="bank_account.account_name", read_only=1),
-            dict(fieldname='bank_account_no', label='Bank Account No',
-                fieldtype='Data', insert_after='bank_account_name', print_hide=1,
-                fetch_from="bank_account.bank_account_no", read_only=1),
-            dict(fieldname='bank_account_iban', label='IBAN',
-                fieldtype='Data', insert_after='bank_account_name', print_hide=1,
-                fetch_from="bank_account.iban", read_only=1),
-        ],
-        "Sales Invoice": [
-            dict(fieldname='vat_collectability', label='VAT Collectability',
-			    fieldtype='Select', insert_after='taxes_and_charges', print_hide=1,
-                options="\n".join(map(lambda x: x.decode('utf-8'), vat_collectability_options)),
-                fetch_from="company.vat_collectability"),
-            dict(fieldname='sb_e_invoicing_reference', label='E-Invoicing',
-			    fieldtype='Section Break', insert_after='pos_total_qty', print_hide=1),
-            dict(fieldname='company_tax_id', label='Company Tax ID',
-			    fieldtype='Data', insert_after='sb_e_invoicing_reference', print_hide=1, read_only=1,
-                fetch_from="company.tax_id"),
-            dict(fieldname='company_fiscal_code', label='Company Fiscal Code',
-			    fieldtype='Data', insert_after='company_tax_id', print_hide=1, read_only=1,
-                fetch_from="company.fiscal_code"),
-            dict(fieldname='company_fiscal_regime', label='Company Fiscal Regime',
-			    fieldtype='Data', insert_after='company_fiscal_code', print_hide=1, read_only=1,
-                fetch_from="company.fiscal_regime"),
-            dict(fieldname='cb_e_invoicing_reference', fieldtype='Column Break',
-                insert_after='company_fiscal_regime', print_hide=1),
-            dict(fieldname='customer_fiscal_code', label='Customer Fiscal Code',
-                fieldtype='Data', insert_after='cb_e_invoicing_reference', read_only=1,
-                fetch_from="customer.fiscal_code"),
-        ],
-        'Purchase Invoice Item': invoice_item_fields,
+	custom_fields = {
+		'Company': [
+			dict(fieldname='sb_e_invoicing', label='E-Invoicing',
+				fieldtype='Section Break', insert_after='date_of_establishment', print_hide=1),
+			dict(fieldname='fiscal_regime', label='Fiscal Regime',
+				fieldtype='Select', insert_after='sb_e_invoicing', print_hide=1,
+				options="\n".join(map(lambda x: x.decode('utf-8'), fiscal_regimes))),
+			dict(fieldname='fiscal_code', label='Fiscal Code', fieldtype='Data', insert_after='fiscal_regime', print_hide=1,
+				description=_("Applicable if the company is an Individual or a Proprietorship")),
+			dict(fieldname='vat_collectability', label='VAT Collectability',
+				fieldtype='Select', insert_after='fiscal_code', print_hide=1,
+				options="\n".join(map(lambda x: x.decode('utf-8'), vat_collectability_options))),
+			dict(fieldname='cb_e_invoicing1', fieldtype='Column Break', insert_after='vat_collectability', print_hide=1),
+			dict(fieldname='registrar_office_province', label='Province of the Registrar Office',
+				fieldtype='Data', insert_after='cb_e_invoicing1', print_hide=1, length=2),
+			dict(fieldname='registration_number', label='Registration Number',
+				fieldtype='Data', insert_after='registrar_office_province', print_hide=1, length=20),
+			dict(fieldname='share_capital_amount', label='Share Capital',
+				fieldtype='Currency', insert_after='registration_number', print_hide=1,
+				description=_('Applicable if the company is SpA, SApA or SRL')),
+			dict(fieldname='no_of_members', label='No of Members',
+				fieldtype='Select', insert_after='share_capital_amount', print_hide=1,
+				options="\nSU-Socio Unico\nSM-Piu Soci", description=_("Applicable if the company is a limited liability company")),
+			dict(fieldname='liquidation_state', label='Liquidation State',
+				fieldtype='Select', insert_after='no_of_members', print_hide=1,
+				options="\nLS-In Liquidazione\nLN-Non in Liquidazione")
+		],
+		'Sales Taxes and Charges': [
+			dict(fieldname='tax_exemption_reason', label='Tax Exemption Reason',
+				fieldtype='Select', insert_after='included_in_print_rate', print_hide=1,
+				depends_on='eval:doc.charge_type!="Actual" && doc.rate==0.0',
+				options="\n" + "\n".join(map(lambda x: x.decode('utf-8'), tax_exemption_reasons))),
+			dict(fieldname='tax_exemption_law', label='Tax Exempt Under',
+				fieldtype='Text', insert_after='tax_exemption_reason', print_hide=1,
+				depends_on='eval:doc.charge_type!="Actual" && doc.rate==0.0')
+		],
+		'Customer': [
+			dict(fieldname='fiscal_code', label='Fiscal Code', fieldtype='Data', insert_after='tax_id', print_hide=1),
+			dict(fieldname='recipient_code', label='Recipient Code',
+				fieldtype='Data', insert_after='fiscal_code', print_hide=1, default="0000000"),
+			dict(fieldname='pec', label='Recipient PEC',
+				fieldtype='Data', insert_after='fiscal_code', print_hide=1),
+			dict(fieldname='is_public_administration', label='Is Public Administration',
+				fieldtype='Check', insert_after='is_internal_customer', print_hide=1,
+				description=_("Set this if the customer is a Public Administration company."),
+				depends_on='eval:doc.customer_type=="Company"'),
+			dict(fieldname='first_name', label='First Name', fieldtype='Data',
+				insert_after='salutation', print_hide=1, depends_on='eval:doc.customer_type!="Company"'),
+			dict(fieldname='last_name', label='Last Name', fieldtype='Data',
+				insert_after='first_name', print_hide=1, depends_on='eval:doc.customer_type!="Company"')
+		],
+		'Mode of Payment': [
+			dict(fieldname='mode_of_payment_code', label='Code',
+			fieldtype='Select', insert_after='included_in_print_rate', print_hide=1,
+			options="\n".join(map(lambda x: x.decode('utf-8'), mode_of_payment_codes)))
+		],
+		'Payment Schedule': [
+			dict(fieldname='mode_of_payment_code', label='Code',
+				fieldtype='Select', insert_after='mode_of_payment', print_hide=1,
+				options="\n".join(map(lambda x: x.decode('utf-8'), mode_of_payment_codes)),
+				fetch_from="mode_of_payment.mode_of_payment_code", read_only=1),
+			dict(fieldname='bank_account', label='Bank Account',
+				fieldtype='Link', insert_after='mode_of_payment_code', print_hide=1,
+				options="Bank Account"),
+			dict(fieldname='bank_account_name', label='Bank Account Name',
+				fieldtype='Data', insert_after='bank_account', print_hide=1,
+				fetch_from="bank_account.account_name", read_only=1),
+			dict(fieldname='bank_account_no', label='Bank Account No',
+				fieldtype='Data', insert_after='bank_account_name', print_hide=1,
+				fetch_from="bank_account.bank_account_no", read_only=1),
+			dict(fieldname='bank_account_iban', label='IBAN',
+				fieldtype='Data', insert_after='bank_account_name', print_hide=1,
+				fetch_from="bank_account.iban", read_only=1),
+		],
+		"Sales Invoice": [
+			dict(fieldname='vat_collectability', label='VAT Collectability',
+				fieldtype='Select', insert_after='taxes_and_charges', print_hide=1,
+				options="\n".join(map(lambda x: x.decode('utf-8'), vat_collectability_options)),
+				fetch_from="company.vat_collectability"),
+			dict(fieldname='sb_e_invoicing_reference', label='E-Invoicing',
+				fieldtype='Section Break', insert_after='pos_total_qty', print_hide=1),
+			dict(fieldname='company_tax_id', label='Company Tax ID',
+				fieldtype='Data', insert_after='sb_e_invoicing_reference', print_hide=1, read_only=1,
+				fetch_from="company.tax_id"),
+			dict(fieldname='company_fiscal_code', label='Company Fiscal Code',
+				fieldtype='Data', insert_after='company_tax_id', print_hide=1, read_only=1,
+				fetch_from="company.fiscal_code"),
+			dict(fieldname='company_fiscal_regime', label='Company Fiscal Regime',
+				fieldtype='Data', insert_after='company_fiscal_code', print_hide=1, read_only=1,
+				fetch_from="company.fiscal_regime"),
+			dict(fieldname='cb_e_invoicing_reference', fieldtype='Column Break',
+				insert_after='company_fiscal_regime', print_hide=1),
+			dict(fieldname='customer_fiscal_code', label='Customer Fiscal Code',
+				fieldtype='Data', insert_after='cb_e_invoicing_reference', read_only=1,
+				fetch_from="customer.fiscal_code"),
+		],
+		'Purchase Invoice Item': invoice_item_fields,
 		'Sales Order Item': invoice_item_fields,
 		'Delivery Note Item': invoice_item_fields,
-        'Sales Invoice Item': invoice_item_fields,
+		'Sales Invoice Item': invoice_item_fields,
 		'Quotation Item': invoice_item_fields,
 		'Purchase Order Item': invoice_item_fields,
 		'Purchase Receipt Item': invoice_item_fields,
 		'Supplier Quotation Item': invoice_item_fields,
-        'Address': [
-            dict(fieldname='country_code', label='Country Code',
-			    fieldtype='Data', insert_after='country', print_hide=1, read_only=1,
-                fetch_from="country.code")
-        ]
-    }
+		'Address': [
+			dict(fieldname='country_code', label='Country Code',
+				fieldtype='Data', insert_after='country', print_hide=1, read_only=1,
+				fetch_from="country.code"),
+			dict(fieldname='state_code', label='State Code',
+				fieldtype='Data', insert_after='state', print_hide=1)
+		]
+	}
 
-    create_custom_fields(custom_fields, ignore_validate = frappe.flags.in_patch, update=update)
+	create_custom_fields(custom_fields, ignore_validate = frappe.flags.in_patch, update=update)
 
 def setup_report():
-    report_name = 'Electronic Invoice Register'
+	report_name = 'Electronic Invoice Register'
 
-    frappe.db.sql(""" update `tabReport` set disabled = 0 where
-        name = %s """, report_name)
+	frappe.db.sql(""" update `tabReport` set disabled = 0 where
+		name = %s """, report_name)
 
-    if not frappe.db.get_value('Custom Role', dict(report=report_name)):
-        frappe.get_doc(dict(
-            doctype='Custom Role',
-            report=report_name,
-            roles= [
-                dict(role='Accounts User'),
-                dict(role='Accounts Manager')
-            ]
-        )).insert()
+	if not frappe.db.get_value('Custom Role', dict(report=report_name)):
+		frappe.get_doc(dict(
+			doctype='Custom Role',
+			report=report_name,
+			roles= [
+				dict(role='Accounts User'),
+				dict(role='Accounts Manager')
+			]
+		)).insert()
diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py
index 85f7447..c86ad78 100644
--- a/erpnext/regional/italy/utils.py
+++ b/erpnext/regional/italy/utils.py
@@ -6,6 +6,7 @@
 from frappe import _
 from frappe.utils.file_manager import save_file, remove_file
 from frappe.desk.form.load import get_attachments
+from erpnext.regional.italy import state_codes
 
 
 def update_itemised_tax_data(doc):
@@ -182,6 +183,9 @@
 #Preflight for successful e-invoice export.
 def sales_invoice_validate(doc):
 	#Validate company
+	if doc.doctype != 'Sales Invoice':
+		return
+
 	if not doc.company_address:
 		frappe.throw(_("Please set an Address on the Company '%s'" % doc.company), title=_("E-Invoicing Information Missing"))
 	else:
@@ -218,8 +222,12 @@
 
 
 #Ensure payment details are valid for e-invoice.
-def sales_invoice_on_submit(doc):
+def sales_invoice_on_submit(doc, method):
 	#Validate payment details
+	if get_company_country(doc.company) not in ['Italy',
+		'Italia', 'Italian Republic', 'Repubblica Italiana']:
+		return
+
 	if not len(doc.payment_schedule):
 		frappe.throw(_("Please set the Payment Schedule"), title=_("E-Invoicing Information Missing"))
 	else:
@@ -243,10 +251,17 @@
 	save_file(xml_filename, invoice_xml, dt=doc.doctype, dn=doc.name, is_private=True)
 
 #Delete e-invoice attachment on cancel.
-def sales_invoice_on_cancel(doc):
+def sales_invoice_on_cancel(doc, method):
+	if get_company_country(doc.company) not in ['Italy',
+		'Italia', 'Italian Republic', 'Repubblica Italiana']:
+		return
+
 	for attachment in get_e_invoice_attachments(doc):
 		remove_file(attachment.name, attached_to_doctype=doc.doctype, attached_to_name=doc.name)
 
+def get_company_country(company):
+	return frappe.get_cached_value('Company', company, 'country')
+
 def get_e_invoice_attachments(invoice):
 	out = []
 	attachments = get_attachments(invoice.doctype, invoice.name)
@@ -282,4 +297,11 @@
 	progressive_name = frappe.model.naming.make_autoname(company_tax_id + "_.#####")
 	progressive_number = progressive_name.split("_")[1]
 
-	return progressive_name, progressive_number
\ No newline at end of file
+	return progressive_name, progressive_number
+
+def set_state_code(doc, method):
+	if not (hasattr(doc, "state_code") and doc.country in ["Italy", "Italia", "Italian Republic", "Repubblica Italiana"]):
+		return
+
+	state_codes_lower = {key.lower():value for key,value in state_codes.items()}
+	doc.state_code = state_codes_lower.get(doc.get('state','').lower())
diff --git a/erpnext/stock/dashboard/item_dashboard.py b/erpnext/stock/dashboard/item_dashboard.py
index 6242fa7..487c765 100644
--- a/erpnext/stock/dashboard/item_dashboard.py
+++ b/erpnext/stock/dashboard/item_dashboard.py
@@ -28,7 +28,7 @@
 		# user does not have access on warehouse
 		return []
 
-	return frappe.db.get_all('Bin', fields=['item_code', 'warehouse', 'projected_qty',
+	items = frappe.db.get_all('Bin', fields=['item_code', 'warehouse', 'projected_qty',
 			'reserved_qty', 'reserved_qty_for_production', 'reserved_qty_for_sub_contract', 'actual_qty', 'valuation_rate'],
 		or_filters={
 			'projected_qty': ['!=', 0],
@@ -41,3 +41,10 @@
 		order_by=sort_by + ' ' + sort_order,
 		limit_start=start,
 		limit_page_length='21')
+
+	for item in items:
+		item.update({
+			'item_name': frappe.get_cached_value("Item", item.item_code, 'item_name')
+		})
+
+	return items
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 50996ed..1eb2b09 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -391,7 +391,7 @@
 
 	return invoiced_qty_map
 
-def get_returned_qty_map(sales_orders):
+def get_returned_qty_map_against_so(sales_orders):
 	"""returns a map: {so_detail: returned_qty}"""
 	returned_qty_map = {}
 
@@ -403,12 +403,25 @@
 
 	return returned_qty_map
 
+def get_returned_qty_map_against_dn(delivery_note):
+	"""returns a map: {so_detail: returned_qty}"""
+	returned_qty_map = frappe._dict(frappe.db.sql("""select dn_item.item_code, sum(abs(dn_item.qty)) as qty
+		from `tabDelivery Note Item` dn_item, `tabDelivery Note` dn
+		where dn.name = dn_item.parent
+			and dn.docstatus = 1
+			and dn.is_return = 1
+			and dn.return_against = %s
+		group by dn_item.item_code
+	""", delivery_note))
+
+	return returned_qty_map
+
 @frappe.whitelist()
 def make_sales_invoice(source_name, target_doc=None):
 	doc = frappe.get_doc('Delivery Note', source_name)
 	sales_orders = [d.against_sales_order for d in doc.items]
-	returned_qty_map = get_returned_qty_map(sales_orders)
-
+	returned_qty_map_against_so = get_returned_qty_map_against_so(sales_orders)
+	returned_qty_map_against_dn = get_returned_qty_map_against_dn(source_name)
 	invoiced_qty_map = get_invoiced_qty_map(source_name)
 
 	def set_missing_values(source, target):
@@ -428,13 +441,26 @@
 			target.update(get_fetch_values("Sales Invoice", 'company_address', target.company_address))
 
 	def update_item(source_doc, target_doc, source_parent):
-		target_doc.qty = (source_doc.qty -
-			invoiced_qty_map.get(source_doc.name, 0) - returned_qty_map.get(source_doc.so_detail, 0))
+		target_doc.qty, returned_qty = get_pending_qty(source_doc)
+		if not source_doc.so_detail:
+			returned_qty_map_against_dn[source_doc.item_code] = returned_qty
 
 		if source_doc.serial_no and source_parent.per_billed > 0:
 			target_doc.serial_no = get_delivery_note_serial_no(source_doc.item_code,
 				target_doc.qty, source_parent.name)
 
+	def get_pending_qty(item_row):
+		pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0) - returned_qty_map_against_so.get(item_row.so_detail, 0)
+		returned_qty = flt(returned_qty_map_against_dn.get(item_row.item_code, 0))
+		if not item_row.so_detail:
+			if returned_qty >= pending_qty:
+				pending_qty = 0
+				returned_qty -= pending_qty
+			else:
+				pending_qty -= returned_qty
+				returned_qty = 0
+		return pending_qty, returned_qty
+
 	doc = get_mapped_doc("Delivery Note", source_name, 	{
 		"Delivery Note": {
 			"doctype": "Sales Invoice",
@@ -453,7 +479,7 @@
 				"cost_center": "cost_center"
 			},
 			"postprocess": update_item,
-			"filter": lambda d: abs(d.qty) - abs(invoiced_qty_map.get(d.name, 0))<=0
+			"filter": lambda d: get_pending_qty(d)[0]<=0
 		},
 		"Sales Taxes and Charges": {
 			"doctype": "Sales Taxes and Charges",
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index 0c5a71c..5c03121 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -636,7 +636,7 @@
 			self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
 
 		set_perpetual_inventory(0, company)
-	
+
 	def test_make_sales_invoice_from_dn_for_returned_qty(self):
 		from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note
 		from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
@@ -655,6 +655,33 @@
 		si = make_sales_invoice(dn.name)
 		self.assertEquals(si.items[0].qty, 1)
 
+	def test_make_sales_invoice_from_dn_with_returned_qty_against_dn(self):
+		from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
+
+		dn = create_delivery_note(qty=8, do_not_submit=True)
+		dn.append("items", {
+			"item_code": "_Test Item",
+			"warehouse": "_Test Warehouse - _TC",
+			"qty": 1,
+			"rate": 100,
+			"conversion_factor": 1.0,
+			"expense_account": "Cost of Goods Sold - _TC",
+			"cost_center": "_Test Cost Center - _TC"
+		})
+		dn.submit()
+
+		si1 = make_sales_invoice(dn.name)
+		si1.items[0].qty = 4
+		si1.items.pop(1)
+		si1.save()
+		si1.submit()
+
+		create_delivery_note(is_return=1, return_against=dn.name, qty=-2)
+
+		si2 = make_sales_invoice(dn.name)
+		self.assertEquals(si2.items[0].qty, 2)
+		self.assertEquals(si2.items[1].qty, 1)
+
 def create_delivery_note(**args):
 	dn = frappe.new_doc("Delivery Note")
 	args = frappe._dict(args)
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index 2b0ed38..cb4afef 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -85,7 +85,7 @@
 
 				// stop
 				frm.add_custom_button(__('Stop'),
-					() => frm.events.update_status(frm, 'Stop'));
+					() => frm.events.update_status(frm, 'Stopped'));
 
 			}
 		}
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index f006d00..cb51e22 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -125,7 +125,7 @@
 		else:
 			self.status = "Completed"
 
-		
+
 		# Updating stock ledger should always be called after updating prevdoc status,
 		# because updating ordered qty, reserved_qty_for_subcontract in bin
 		# depends upon updated ordered qty in PO
@@ -311,7 +311,7 @@
 				"\n".join(warehouse_with_no_account))
 
 		return process_gl_map(gl_entries)
-		
+
 	def get_asset_gl_entry(self, gl_entries):
 		for d in self.get("items"):
 			if d.is_fixed_asset:
@@ -405,6 +405,11 @@
 @frappe.whitelist()
 def make_purchase_invoice(source_name, target_doc=None):
 	from frappe.model.mapper import get_mapped_doc
+	doc = frappe.get_doc('Purchase Receipt', source_name)
+	purchase_orders = [d.purchase_order for d in doc.items]
+	returned_qty_map_against_po = get_returned_qty_map_against_po(purchase_orders)
+	returned_qty_map_against_pr = get_returned_qty_map_against_pr(source_name)
+
 	invoiced_qty_map = get_invoiced_qty_map(source_name)
 
 	def set_missing_values(source, target):
@@ -417,7 +422,23 @@
 		doc.run_method("calculate_taxes_and_totals")
 
 	def update_item(source_doc, target_doc, source_parent):
-		target_doc.qty = source_doc.qty - invoiced_qty_map.get(source_doc.name, 0)
+		target_doc.qty, returned_qty = get_pending_qty(source_doc)
+		if not source_doc.purchase_order_item:
+			returned_qty_map_against_pr[source_doc.item_code] = returned_qty
+
+	def get_pending_qty(item_row):
+		pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0) \
+			- returned_qty_map_against_po.get(item_row.purchase_order_item, 0)
+		returned_qty = flt(returned_qty_map_against_pr.get(item_row.item_code, 0))
+		if not item_row.purchase_order_item:
+			if returned_qty >= pending_qty:
+				pending_qty = 0
+				returned_qty -= pending_qty
+			else:
+				pending_qty -= returned_qty
+				returned_qty = 0
+		return pending_qty, returned_qty
+
 
 	doclist = get_mapped_doc("Purchase Receipt", source_name,	{
 		"Purchase Receipt": {
@@ -440,7 +461,7 @@
 				"asset": "asset",
 			},
 			"postprocess": update_item,
-			"filter": lambda d: abs(d.qty) - abs(invoiced_qty_map.get(d.name, 0))<=0
+			"filter": lambda d: get_pending_qty(d)[0]<=0
 		},
 		"Purchase Taxes and Charges": {
 			"doctype": "Purchase Taxes and Charges",
@@ -462,6 +483,31 @@
 
 	return invoiced_qty_map
 
+def get_returned_qty_map_against_po(purchase_orders):
+	"""returns a map: {so_detail: returned_qty}"""
+	returned_qty_map = {}
+
+	for name, returned_qty in frappe.get_all('Purchase Order Item', fields = ["name", "returned_qty"],
+		filters = {'parent': ('in', purchase_orders), 'docstatus': 1}, as_list=1):
+		if not returned_qty_map.get(name):
+				returned_qty_map[name] = 0
+		returned_qty_map[name] += returned_qty
+
+	return returned_qty_map
+
+def get_returned_qty_map_against_pr(purchase_receipt):
+	"""returns a map: {so_detail: returned_qty}"""
+	returned_qty_map = frappe._dict(frappe.db.sql("""select pr_item.item_code, sum(abs(pr_item.qty)) as qty
+		from `tabPurchase Receipt Item` pr_item, `tabPurchase Receipt` pr
+		where pr.name = pr_item.parent
+			and pr.docstatus = 1
+			and pr.is_return = 1
+			and pr.return_against = %s
+		group by pr_item.item_code
+	""", purchase_receipt))
+
+	return returned_qty_map
+
 @frappe.whitelist()
 def make_purchase_return(source_name, target_doc=None):
 	from erpnext.controllers.sales_and_purchase_return import make_return_doc
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index 472083b..c5ae838 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -404,6 +404,44 @@
 
 		set_perpetual_inventory(0, pr.company)
 
+	def test_make_purchase_invoice_from_pr_for_returned_qty(self):
+		from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order, create_pr_against_po
+
+		po = create_purchase_order()
+		pr = create_pr_against_po(po.name)
+
+		pr1 = make_purchase_receipt(is_return=1, return_against=pr.name, qty=-1, do_not_submit=True)
+		pr1.items[0].purchase_order = po.name
+		pr1.items[0].purchase_order_item = po.items[0].name
+		pr1.submit()
+
+		pi = make_purchase_invoice(pr.name)
+		self.assertEquals(pi.items[0].qty, 3)
+
+	def test_make_purchase_invoice_from_dn_with_returned_qty_against_dn(self):
+		pr1 = make_purchase_receipt(qty=8, do_not_submit=True)
+		pr1.append("items", {
+			"item_code": "_Test Item",
+			"warehouse": "_Test Warehouse - _TC",
+			"qty": 1,
+			"received_qty": 1,
+			"rate": 100,
+			"conversion_factor": 1.0,
+		})
+		pr1.submit()
+
+		pi1 = make_purchase_invoice(pr1.name)
+		pi1.items[0].qty = 4
+		pi1.items.pop(1)
+		pi1.save()
+		pi1.submit()
+
+		make_purchase_receipt(is_return=1, return_against=pr1.name, qty=-2)
+
+		pi2 = make_purchase_invoice(pr1.name)
+		self.assertEquals(pi2.items[0].qty, 2)
+		self.assertEquals(pi2.items[1].qty, 1)
+
 def get_gl_entries(voucher_type, voucher_no):
 	return frappe.db.sql("""select account, debit, credit, cost_center
 		from `tabGL Entry` where voucher_type=%s and voucher_no=%s