Amazon MWS Connector (#15061)

* [fix] #15054

* [fix] #15058

* codacy issues

* Codacy fixes-1

* Travis Fix

* fix codacy

* fix codacy

* review changes 1

* Custom fields and fixes

* remove amazon id

* remove item.json and sales_order.json

* added back sales_order and item files
diff --git a/erpnext/config/integrations.py b/erpnext/config/integrations.py
index e27b7cd..01e077f 100644
--- a/erpnext/config/integrations.py
+++ b/erpnext/config/integrations.py
@@ -30,6 +30,11 @@
 					"type": "doctype",
 					"name": "Shopify Settings",
 					"description": _("Connect Shopify with ERPNext"),
+				},
+				{
+					"type": "doctype",
+					"name": "Amazon MWS Settings",
+					"description": _("Connect Amazon with ERPNext"),
 				}
 			]
 		}
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/__init__.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/__init__.py
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py
new file mode 100644
index 0000000..cb11ece
--- /dev/null
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py
@@ -0,0 +1,505 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe, time, dateutil, math, csv, StringIO
+import amazon_mws_api as mws
+from frappe import _
+
+#Get and Create Products
+def get_products_details():
+	products = get_products_instance()
+	reports = get_reports_instance()
+
+	mws_settings = frappe.get_doc("Amazon MWS Settings")
+	market_place_list = return_as_list(mws_settings.market_place_id)
+
+	for marketplace in market_place_list:
+		report_id = request_and_fetch_report_id("_GET_FLAT_FILE_OPEN_LISTINGS_DATA_", None, None, market_place_list)
+
+		if report_id:
+			listings_response = reports.get_report(report_id=report_id)
+
+			#Get ASIN Codes
+			string_io = StringIO.StringIO(listings_response.original)
+			csv_rows = list(csv.reader(string_io, delimiter=str('\t')))
+			asin_list = list(set([row[1] for row in csv_rows[1:]]))
+			#break into chunks of 10
+			asin_chunked_list = list(chunks(asin_list, 10))
+
+			#Map ASIN Codes to SKUs
+			sku_asin = [{"asin":row[1],"sku":row[0]} for row in csv_rows[1:]]
+
+			#Fetch Products List from ASIN
+			for asin_list in asin_chunked_list:
+				products_response = call_mws_method(products.get_matching_product,marketplaceid=marketplace,
+					asins=asin_list)
+
+				matching_products_list = products_response.parsed 
+				for product in matching_products_list:
+					skus = [row["sku"] for row in sku_asin if row["asin"]==product.ASIN]
+					for sku in skus:
+						create_item_code(product, sku)
+
+def get_products_instance():
+	mws_settings = frappe.get_doc("Amazon MWS Settings")
+	products = mws.Products(
+			account_id = mws_settings.seller_id,
+			access_key = mws_settings.aws_access_key_id,
+			secret_key = mws_settings.secret_key,
+			region = mws_settings.region,
+			domain = mws_settings.domain
+			)
+
+	return products
+
+def get_reports_instance():
+	mws_settings = frappe.get_doc("Amazon MWS Settings")
+	reports = mws.Reports(
+			account_id = mws_settings.seller_id,
+			access_key = mws_settings.aws_access_key_id,
+			secret_key = mws_settings.secret_key,
+			region = mws_settings.region,
+			domain = mws_settings.domain
+	)
+
+	return reports
+
+#returns list as expected by amazon API
+def return_as_list(input_value):
+	if isinstance(input_value, list):
+		return input_value
+	else:
+		return [input_value]
+
+#function to chunk product data
+def chunks(l, n):
+	for i in range(0, len(l), n):
+		yield l[i:i+n]
+
+def request_and_fetch_report_id(report_type, start_date=None, end_date=None, marketplaceids=None):
+	reports = get_reports_instance()
+	report_response = reports.request_report(report_type=report_type,
+			start_date=start_date,
+			end_date=end_date,
+			marketplaceids=marketplaceids)
+
+	#add time delay to wait for amazon to generate report
+	time.sleep(20)
+	report_request_id = report_response.parsed["ReportRequestInfo"]["ReportRequestId"]["value"]
+	generated_report_id = None
+	#poll to get generated report
+	for x in range(1,10):
+		report_request_list_response = reports.get_report_request_list(requestids=[report_request_id])
+		report_status = report_request_list_response.parsed["ReportRequestInfo"]["ReportProcessingStatus"]["value"]
+
+		if report_status == "_SUBMITTED_" or report_status == "_IN_PROGRESS_":
+			#add time delay to wait for amazon to generate report
+			time.sleep(15)
+			continue
+		elif report_status == "_CANCELLED_":
+			break
+		elif report_status == "_DONE_NO_DATA_":
+			break
+		elif report_status == "_DONE_":
+			generated_report_id =  report_request_list_response.parsed["ReportRequestInfo"]["GeneratedReportId"]["value"]
+			break
+	return generated_report_id
+
+def call_mws_method(mws_method, *args, **kwargs):
+
+	mws_settings = frappe.get_doc("Amazon MWS Settings")
+	max_retries = mws_settings.max_retry_limit
+
+	for x in xrange(0, max_retries):
+		try:
+			response = mws_method(*args, **kwargs)
+			return response
+		except Exception as e:
+			delay = math.pow(4, x) * 125
+			frappe.log_error(message=e, title=str(mws_method))
+			time.sleep(delay)
+			continue
+
+	mws_settings.enable_synch = 0
+	mws_settings.save()
+
+	frappe.throw(_("Sync has been temporarily disabled because maximum retries have been exceeded"))
+
+def create_item_code(amazon_item_json, sku):
+	if frappe.db.get_value("Item", sku):
+		return
+
+	item = frappe.new_doc("Item")
+
+	new_manufacturer = create_manufacturer(amazon_item_json)
+	new_brand = create_brand(amazon_item_json)
+
+	mws_settings = frappe.get_doc("Amazon MWS Settings")
+
+	item.item_code = sku
+	item.amazon_item_code = amazon_item_json.ASIN
+	item.item_group = mws_settings.item_group
+	item.description = amazon_item_json.Product.AttributeSets.ItemAttributes.Title
+	item.brand = new_brand
+	item.manufacturer = new_manufacturer
+	item.web_long_description = amazon_item_json.Product.AttributeSets.ItemAttributes.Title
+
+	item.image = amazon_item_json.Product.AttributeSets.ItemAttributes.SmallImage.URL
+
+	temp_item_group = amazon_item_json.Product.AttributeSets.ItemAttributes.ProductGroup
+
+	item_group = frappe.db.get_value("Item Group",filters={"item_group_name": temp_item_group})
+
+	if not item_group:
+		igroup = frappe.new_doc("Item Group")
+		igroup.item_group_name = temp_item_group
+		igroup.parent_item_group =  mws_settings.item_group
+		igroup.insert()
+
+	item.insert(ignore_permissions=True)
+	create_item_price(amazon_item_json, item.item_code)
+
+	return item.name
+
+def create_manufacturer(amazon_item_json):
+	existing_manufacturer = frappe.db.get_value("Manufacturer",
+		filters={"short_name":amazon_item_json.Product.AttributeSets.ItemAttributes.Manufacturer})
+
+	if not existing_manufacturer:
+		manufacturer = frappe.new_doc("Manufacturer")
+		manufacturer.short_name = amazon_item_json.Product.AttributeSets.ItemAttributes.Manufacturer
+		manufacturer.insert()
+		return manufacturer.short_name
+	else:
+		return existing_manufacturer
+
+def create_brand(amazon_item_json):
+	existing_brand = frappe.db.get_value("Brand",
+		filters={"brand":amazon_item_json.Product.AttributeSets.ItemAttributes.Brand})
+	if not existing_brand:
+		brand = frappe.new_doc("Brand")
+		brand.brand = amazon_item_json.Product.AttributeSets.ItemAttributes.Brand
+		brand.insert()
+		return brand.brand
+	else:
+		return existing_brand
+
+def create_item_price(amazon_item_json, item_code):
+	item_price = frappe.new_doc("Item Price")
+	item_price.price_list = frappe.db.get_value("Amazon MWS Settings", "Amazon MWS Settings", "price_list")
+	if not("ListPrice" in amazon_item_json.Product.AttributeSets.ItemAttributes):
+		item_price.price_list_rate = 0
+	else:
+		item_price.price_list_rate = amazon_item_json.Product.AttributeSets.ItemAttributes.ListPrice.Amount
+
+	item_price.item_code = item_code
+	item_price.insert()
+
+#Get and create Orders
+def get_orders(after_date):
+	try:
+		orders = get_orders_instance()
+		statuses = ["PartiallyShipped", "Unshipped", "Shipped", "Canceled"]
+		mws_settings = frappe.get_doc("Amazon MWS Settings")
+		market_place_list = return_as_list(mws_settings.market_place_id)
+
+		orders_response = call_mws_method(orders.list_orders, marketplaceids=market_place_list,
+			fulfillment_channels=["MFN", "AFN"],
+			lastupdatedafter=after_date,
+			orderstatus=statuses,
+			max_results='20')
+
+		while True:
+			orders_list = []
+
+			if "Order" in orders_response.parsed.Orders:
+				orders_list = return_as_list(orders_response.parsed.Orders.Order)
+
+			if len(orders_list) == 0:
+				break
+
+			for order in orders_list:
+				create_sales_order(order, after_date)
+
+			if not "NextToken" in orders_response.parsed:
+				break
+
+			next_token = orders_response.parsed.NextToken
+			orders_response = call_mws_method(orders.list_orders_by_next_token, next_token)
+
+	except Exception as e:
+		frappe.log_error(title="get_orders", message=e)
+
+def get_orders_instance():
+	mws_settings = frappe.get_doc("Amazon MWS Settings")
+	orders = mws.Orders(
+			account_id = mws_settings.seller_id,
+			access_key = mws_settings.aws_access_key_id,
+			secret_key = mws_settings.secret_key,
+			region= mws_settings.region,
+			domain= mws_settings.domain,
+			version="2013-09-01"
+		)
+
+	return orders
+
+def create_sales_order(order_json,after_date):
+	customer_name = create_customer(order_json)
+	create_address(order_json, customer_name)
+
+	market_place_order_id = order_json.AmazonOrderId
+
+	so = frappe.db.get_value("Sales Order",
+			filters={"amazon_order_id": market_place_order_id},
+			fieldname="name")
+
+	taxes_and_charges = frappe.db.get_value("Amazon MWS Settings", "Amazon MWS Settings", "taxes_charges")
+
+	if so:
+		return
+
+	if not so:
+		items = get_order_items(market_place_order_id)
+		delivery_date = dateutil.parser.parse(order_json.LatestShipDate).strftime("%Y-%m-%d")
+		transaction_date = dateutil.parser.parse(order_json.PurchaseDate).strftime("%Y-%m-%d")
+
+		so = frappe.get_doc({
+				"doctype": "Sales Order",
+				"naming_series": "SO-",
+				"amazon_order_id": market_place_order_id,
+				"marketplace_id": order_json.MarketplaceId,
+				"customer": customer_name,
+				"delivery_date": delivery_date,
+				"transaction_date": transaction_date,
+				"items": items,
+				"company": frappe.db.get_value("Amazon MWS Settings", "Amazon MWS Settings", "company")
+			})
+
+		try:
+			if taxes_and_charges:
+				charges_and_fees = get_charges_and_fees(market_place_order_id)
+				for charge in charges_and_fees.get("charges"):
+					so.append('taxes', charge)
+
+				for fee in charges_and_fees.get("fees"):
+					so.append('taxes', fee)
+
+			so.insert(ignore_permissions=True)
+			so.submit()
+
+		except Exception as e:
+			frappe.log_error(message=e, title="Create Sales Order")
+
+def create_customer(order_json):
+	order_customer_name = ""
+
+	if not("BuyerName" in order_json):
+		order_customer_name = "Buyer - " + order_json.AmazonOrderId
+	else:
+		order_customer_name = order_json.BuyerName
+
+	existing_customer_name = frappe.db.get_value("Customer",
+			filters={"name": order_customer_name}, fieldname="name")
+
+	if existing_customer_name:
+		filters = [
+				["Dynamic Link", "link_doctype", "=", "Customer"],
+				["Dynamic Link", "link_name", "=", existing_customer_name],
+				["Dynamic Link", "parenttype", "=", "Contact"]
+			]
+
+		existing_contacts = frappe.get_list("Contact", filters)
+
+		if existing_contacts:
+			pass
+		else:
+			new_contact = frappe.new_doc("Contact")
+			new_contact.first_name = order_customer_name
+			new_contact.append('links', {
+				"link_doctype": "Customer",
+				"link_name": existing_customer_name
+			})
+			new_contact.insert()
+
+		return existing_customer_name
+	else:
+		mws_customer_settings = frappe.get_doc("Amazon MWS Settings")
+		new_customer = frappe.new_doc("Customer")
+		new_customer.customer_name = order_customer_name
+		new_customer.customer_group = mws_customer_settings.customer_group
+		new_customer.territory = mws_customer_settings.territory
+		new_customer.customer_type = mws_customer_settings.customer_type
+		new_customer.save()
+
+		new_contact = frappe.new_doc("Contact")
+		new_contact.first_name = order_customer_name
+		new_contact.append('links', {
+			"link_doctype": "Customer",
+			"link_name": new_customer.name
+		})
+
+		new_contact.insert()
+
+		return new_customer.name
+
+def create_address(amazon_order_item_json, customer_name):
+
+	filters = [
+			["Dynamic Link", "link_doctype", "=", "Customer"],
+			["Dynamic Link", "link_name", "=", customer_name],
+			["Dynamic Link", "parenttype", "=", "Address"]
+		]
+
+	existing_address = frappe.get_list("Address", filters)
+
+	if not("ShippingAddress" in amazon_order_item_json):
+		return None
+	else:
+		make_address = frappe.new_doc("Address")
+
+		if "AddressLine1" in amazon_order_item_json.ShippingAddress:
+			make_address.address_line1 = amazon_order_item_json.ShippingAddress.AddressLine1
+		else:
+			make_address.address_line1 = "Not Provided"
+
+		if "City" in amazon_order_item_json.ShippingAddress:
+			make_address.city = amazon_order_item_json.ShippingAddress.City
+		else:
+			make_address.city = "Not Provided"
+
+		if "StateOrRegion" in amazon_order_item_json.ShippingAddress:
+			make_address.state = amazon_order_item_json.ShippingAddress.StateOrRegion
+
+		if "PostalCode" in amazon_order_item_json.ShippingAddress:
+			make_address.pincode = amazon_order_item_json.ShippingAddress.PostalCode
+
+		for address in existing_address:
+			address_doc = frappe.get_doc("Address", address["name"])
+			if (address_doc.address_line1 == make_address.address_line1 and
+				address_doc.pincode == make_address.pincode):
+				return address
+
+		make_address.append("links", {
+			"link_doctype": "Customer",
+			"link_name": customer_name
+		})
+		make_address.address_type = "Shipping"
+		make_address.insert()
+
+def get_order_items(market_place_order_id):
+	mws_orders = get_orders_instance()
+
+	order_items_response = call_mws_method(mws_orders.list_order_items, amazon_order_id=market_place_order_id)
+	final_order_items = []
+
+	order_items_list = return_as_list(order_items_response.parsed.OrderItems.OrderItem)
+
+	warehouse = frappe.db.get_value("Amazon MWS Settings", "Amazon MWS Settings", "warehouse")
+
+	while True:
+		for order_item in order_items_list:
+
+			if not "ItemPrice" in order_item:
+				price = 0
+			else:
+				price = order_item.ItemPrice.Amount
+
+			final_order_items.append({
+				"item_code": get_item_code(order_item),
+				"item_name": order_item.SellerSKU,
+				"description": order_item.Title,
+				"rate": price,
+				"qty": order_item.QuantityOrdered,
+				"stock_uom": "Nos",
+				"warehouse": warehouse,
+				"conversion_factor": "1.0"
+			})
+
+		if not "NextToken" in order_items_response.parsed:
+			break
+
+		next_token = order_items_response.parsed.NextToken
+
+		order_items_response = call_mws_method(mws_orders.list_order_items_by_next_token, next_token)
+		order_items_list = return_as_list(order_items_response.parsed.OrderItems.OrderItem)
+
+	return final_order_items
+
+def get_item_code(order_item):
+	asin = order_item.ASIN
+	item_code = frappe.db.get_value("Item", {"amazon_item_code": asin}, "item_code")
+	if item_code:
+		return item_code
+
+def get_charges_and_fees(market_place_order_id):
+	finances = get_finances_instance()
+
+	charges_fees = {"charges":[], "fees":[]}
+
+	response = call_mws_method(finances.list_financial_events, amazon_order_id=market_place_order_id)
+
+	shipment_event_list = return_as_list(response.parsed.FinancialEvents.ShipmentEventList)
+
+	for shipment_event in shipment_event_list:
+		if shipment_event:
+			shipment_item_list = return_as_list(shipment_event.ShipmentEvent.ShipmentItemList.ShipmentItem)
+
+			for shipment_item in shipment_item_list:
+				charges = return_as_list(shipment_item.ItemChargeList.ChargeComponent)
+				fees = return_as_list(shipment_item.ItemFeeList.FeeComponent)
+
+				for charge in charges:
+					if(charge.ChargeType != "Principal"):
+						charge_account = get_account(charge.ChargeType)
+						charges_fees.get("charges").append({
+							"charge_type":"Actual",
+							"account_head": charge_account,
+							"tax_amount": charge.ChargeAmount.CurrencyAmount,
+							"description": charge.ChargeType + " for " + shipment_item.SellerSKU
+							})
+
+				for fee in fees:
+					fee_account = get_account(fee.FeeType)
+					charges_fees.get("fees").append({
+						"charge_type":"Actual",
+						"account_head": fee_account,
+						"tax_amount": fee.FeeAmount.CurrencyAmount,
+						"description": fee.FeeType + " for " + shipment_item.SellerSKU
+						})
+
+	return charges_fees
+
+def get_finances_instance():
+
+	mws_settings = frappe.get_doc("Amazon MWS Settings")
+
+	finances = mws.Finances(
+			account_id = mws_settings.seller_id,
+			access_key = mws_settings.aws_access_key_id,
+			secret_key = mws_settings.secret_key,
+			region= mws_settings.region,
+			domain= mws_settings.domain,
+			version="2015-05-01"
+		)
+
+	return finances
+
+def get_account(name):
+	existing_account = frappe.db.get_value("Account", {"account_name": "Amazon {0}".format(name)})
+	account_name = existing_account
+	mws_settings = frappe.get_doc("Amazon MWS Settings")
+
+	if not existing_account:
+		try:
+			new_account = frappe.new_doc("Account")
+			new_account.account_name = "Amazon {0}".format(name)
+			new_account.company = mws_settings.company
+			new_account.parent_account = mws_settings.market_place_account_group
+			new_account.insert(ignore_permissions=True)
+			account_name = new_account.name
+		except Exception as e:
+			frappe.log_error(message=e, title="Create Account")
+
+	return account_name
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py
new file mode 100755
index 0000000..798e637
--- /dev/null
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py
@@ -0,0 +1,642 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Basic interface to Amazon MWS
+# Based on http://code.google.com/p/amazon-mws-python
+# Extended to include finances object
+
+import urllib
+import hashlib
+import hmac
+import base64
+import xml_utils
+import re
+try:
+	from xml.etree.ElementTree import ParseError as XMLError
+except ImportError:
+	from xml.parsers.expat import ExpatError as XMLError
+from time import strftime, gmtime
+
+from requests import request
+from requests.exceptions import HTTPError
+
+
+__all__ = [
+	'Feeds',
+	'Inventory',
+	'MWSError',
+	'Reports',
+	'Orders',
+	'Products',
+	'Recommendations',
+	'Sellers',
+	'Finances'
+]
+
+# See https://images-na.ssl-images-amazon.com/images/G/01/mwsportal/doc/en_US/bde/MWSDeveloperGuide._V357736853_.pdf page 8
+# for a list of the end points and marketplace IDs
+
+MARKETPLACES = {
+	"CA" : "https://mws.amazonservices.ca", #A2EUQ1WTGCTBG2
+	"US" : "https://mws.amazonservices.com", #ATVPDKIKX0DER",
+	"DE" : "https://mws-eu.amazonservices.com", #A1PA6795UKMFR9
+	"ES" : "https://mws-eu.amazonservices.com", #A1RKKUPIHCS9HS
+	"FR" : "https://mws-eu.amazonservices.com", #A13V1IB3VIYZZH
+	"IN" : "https://mws.amazonservices.in", #A21TJRUUN4KGV
+	"IT" : "https://mws-eu.amazonservices.com", #APJ6JRA9NG5V4
+	"UK" : "https://mws-eu.amazonservices.com", #A1F83G8C2ARO7P
+	"JP" : "https://mws.amazonservices.jp", #A1VC38T7YXB528
+	"CN" : "https://mws.amazonservices.com.cn", #AAHKV2X7AFYLW
+}
+
+
+class MWSError(Exception):
+	"""
+		Main MWS Exception class
+	"""
+	# Allows quick access to the response object.
+	# Do not rely on this attribute, always check if its not None.
+	response = None
+
+def calc_md5(string):
+	"""Calculates the MD5 encryption for the given string
+	"""
+	md = hashlib.md5()
+	md.update(string)
+	return base64.encodestring(md.digest()).strip('\n')
+
+def remove_empty(d):
+	"""
+		Helper function that removes all keys from a dictionary (d),
+	that have an empty value.
+	"""
+	for key in d.keys():
+		if not d[key]:
+			del d[key]
+	return d
+
+def remove_namespace(xml):
+	regex = re.compile(' xmlns(:ns2)?="[^"]+"|(ns2:)|(xml:)')
+	return regex.sub('', xml)
+
+class DictWrapper(object):
+	def __init__(self, xml, rootkey=None):
+		self.original = xml
+		self._rootkey = rootkey
+		self._mydict = xml_utils.xml2dict().fromstring(remove_namespace(xml))
+		self._response_dict = self._mydict.get(self._mydict.keys()[0],
+												self._mydict)
+
+	@property
+	def parsed(self):
+		if self._rootkey:
+			return self._response_dict.get(self._rootkey)
+		else:
+			return self._response_dict
+
+class DataWrapper(object):
+	"""
+		Text wrapper in charge of validating the hash sent by Amazon.
+	"""
+	def __init__(self, data, header):
+		self.original = data
+		if 'content-md5' in header:
+			hash_ = calc_md5(self.original)
+			if header['content-md5'] != hash_:
+				raise MWSError("Wrong Contentlength, maybe amazon error...")
+
+	@property
+	def parsed(self):
+		return self.original
+
+class MWS(object):
+	""" Base Amazon API class """
+
+	# This is used to post/get to the different uris used by amazon per api
+	# ie. /Orders/2011-01-01
+	# All subclasses must define their own URI only if needed
+	URI = "/"
+
+	# The API version varies in most amazon APIs
+	VERSION = "2009-01-01"
+
+	# There seem to be some xml namespace issues. therefore every api subclass
+	# is recommended to define its namespace, so that it can be referenced
+	# like so AmazonAPISubclass.NS.
+	# For more information see http://stackoverflow.com/a/8719461/389453
+	NS = ''
+
+	# Some APIs are available only to either a "Merchant" or "Seller"
+	# the type of account needs to be sent in every call to the amazon MWS.
+	# This constant defines the exact name of the parameter Amazon expects
+	# for the specific API being used.
+	# All subclasses need to define this if they require another account type
+	# like "Merchant" in which case you define it like so.
+	# ACCOUNT_TYPE = "Merchant"
+	# Which is the name of the parameter for that specific account type.
+	ACCOUNT_TYPE = "SellerId"
+
+	def __init__(self, access_key, secret_key, account_id, region='US', domain='', uri="", version=""):
+		self.access_key = access_key
+		self.secret_key = secret_key
+		self.account_id = account_id
+		self.version = version or self.VERSION
+		self.uri = uri or self.URI
+
+		if domain:
+			self.domain = domain
+		elif region in MARKETPLACES:
+			self.domain = MARKETPLACES[region]
+		else:
+			error_msg = "Incorrect region supplied ('%(region)s'). Must be one of the following: %(marketplaces)s" % {
+				"marketplaces" : ', '.join(MARKETPLACES.keys()),
+				"region" : region,
+			}
+			raise MWSError(error_msg)
+
+	def make_request(self, extra_data, method="GET", **kwargs):
+		"""Make request to Amazon MWS API with these parameters
+		"""
+
+		# Remove all keys with an empty value because
+		# Amazon's MWS does not allow such a thing.
+		extra_data = remove_empty(extra_data)
+
+		params = {
+			'AWSAccessKeyId': self.access_key,
+			self.ACCOUNT_TYPE: self.account_id,
+			'SignatureVersion': '2',
+			'Timestamp': self.get_timestamp(),
+			'Version': self.version,
+			'SignatureMethod': 'HmacSHA256',
+		}
+		params.update(extra_data)
+		request_description = '&'.join(['%s=%s' % (k, urllib.quote(params[k], safe='-_.~').encode('utf-8')) for k in sorted(params)])
+		signature = self.calc_signature(method, request_description)
+		url = '%s%s?%s&Signature=%s' % (self.domain, self.uri, request_description, urllib.quote(signature))
+		headers = {'User-Agent': 'python-amazon-mws/0.0.1 (Language=Python)'}
+		headers.update(kwargs.get('extra_headers', {}))
+
+		try:
+			# Some might wonder as to why i don't pass the params dict as the params argument to request.
+			# My answer is, here i have to get the url parsed string of params in order to sign it, so
+			# if i pass the params dict as params to request, request will repeat that step because it will need
+			# to convert the dict to a url parsed string, so why do it twice if i can just pass the full url :).
+			response = request(method, url, data=kwargs.get('body', ''), headers=headers)
+			response.raise_for_status()
+			# When retrieving data from the response object,
+			# be aware that response.content returns the content in bytes while response.text calls
+			# response.content and converts it to unicode.
+			data = response.content
+
+			# I do not check the headers to decide which content structure to server simply because sometimes
+			# Amazon's MWS API returns XML error responses with "text/plain" as the Content-Type.
+			try:
+				parsed_response = DictWrapper(data, extra_data.get("Action") + "Result")
+			except XMLError:
+				parsed_response = DataWrapper(data, response.headers)
+
+		except HTTPError, e:
+			error = MWSError(str(e))
+			error.response = e.response
+			raise error
+
+		# Store the response object in the parsed_response for quick access
+		parsed_response.response = response
+		return parsed_response
+
+	def get_service_status(self):
+		"""
+			Returns a GREEN, GREEN_I, YELLOW or RED status.
+			Depending on the status/availability of the API its being called from.
+		"""
+
+		return self.make_request(extra_data=dict(Action='GetServiceStatus'))
+
+	def calc_signature(self, method, request_description):
+		"""Calculate MWS signature to interface with Amazon
+		"""
+		sig_data = method + '\n' + self.domain.replace('https://', '').lower() + '\n' + self.uri + '\n' + request_description
+		return base64.b64encode(hmac.new(str(self.secret_key), sig_data, hashlib.sha256).digest())
+
+	def get_timestamp(self):
+		"""
+			Returns the current timestamp in proper format.
+		"""
+		return strftime("%Y-%m-%dT%H:%M:%SZ", gmtime())
+
+	def enumerate_param(self, param, values):
+		"""
+			Builds a dictionary of an enumerated parameter.
+			Takes any iterable and returns a dictionary.
+			ie.
+			enumerate_param('MarketplaceIdList.Id', (123, 345, 4343))
+			returns
+			{
+				MarketplaceIdList.Id.1: 123,
+				MarketplaceIdList.Id.2: 345,
+				MarketplaceIdList.Id.3: 4343
+			}
+		"""
+		params = {}
+		if values is not None:
+			if not param.endswith('.'):
+				param = "%s." % param
+			for num, value in enumerate(values):
+				params['%s%d' % (param, (num + 1))] = value
+		return params
+
+
+class Feeds(MWS):
+	""" Amazon MWS Feeds API """
+
+	ACCOUNT_TYPE = "Merchant"
+
+	def submit_feed(self, feed, feed_type, marketplaceids=None,
+					content_type="text/xml", purge='false'):
+		"""
+		Uploads a feed ( xml or .tsv ) to the seller's inventory.
+		Can be used for creating/updating products on Amazon.
+		"""
+		data = dict(Action='SubmitFeed',
+					FeedType=feed_type,
+					PurgeAndReplace=purge)
+		data.update(self.enumerate_param('MarketplaceIdList.Id.', marketplaceids))
+		md = calc_md5(feed)
+		return self.make_request(data, method="POST", body=feed,
+								extra_headers={'Content-MD5': md, 'Content-Type': content_type})
+
+	def get_feed_submission_list(self, feedids=None, max_count=None, feedtypes=None,
+								processingstatuses=None, fromdate=None, todate=None):
+		"""
+		Returns a list of all feed submissions submitted in the previous 90 days.
+		That match the query parameters.
+		"""
+
+		data = dict(Action='GetFeedSubmissionList',
+					MaxCount=max_count,
+					SubmittedFromDate=fromdate,
+					SubmittedToDate=todate,)
+		data.update(self.enumerate_param('FeedSubmissionIdList.Id', feedids))
+		data.update(self.enumerate_param('FeedTypeList.Type.', feedtypes))
+		data.update(self.enumerate_param('FeedProcessingStatusList.Status.', processingstatuses))
+		return self.make_request(data)
+
+	def get_submission_list_by_next_token(self, token):
+		data = dict(Action='GetFeedSubmissionListByNextToken', NextToken=token)
+		return self.make_request(data)
+
+	def get_feed_submission_count(self, feedtypes=None, processingstatuses=None, fromdate=None, todate=None):
+		data = dict(Action='GetFeedSubmissionCount',
+					SubmittedFromDate=fromdate,
+					SubmittedToDate=todate)
+		data.update(self.enumerate_param('FeedTypeList.Type.', feedtypes))
+		data.update(self.enumerate_param('FeedProcessingStatusList.Status.', processingstatuses))
+		return self.make_request(data)
+
+	def cancel_feed_submissions(self, feedids=None, feedtypes=None, fromdate=None, todate=None):
+		data = dict(Action='CancelFeedSubmissions',
+					SubmittedFromDate=fromdate,
+					SubmittedToDate=todate)
+		data.update(self.enumerate_param('FeedSubmissionIdList.Id.', feedids))
+		data.update(self.enumerate_param('FeedTypeList.Type.', feedtypes))
+		return self.make_request(data)
+
+	def get_feed_submission_result(self, feedid):
+		data = dict(Action='GetFeedSubmissionResult', FeedSubmissionId=feedid)
+		return self.make_request(data)
+
+class Reports(MWS):
+	""" Amazon MWS Reports API """
+
+	ACCOUNT_TYPE = "Merchant"
+
+	## REPORTS ###
+
+	def get_report(self, report_id):
+		data = dict(Action='GetReport', ReportId=report_id)
+		return self.make_request(data)
+
+	def get_report_count(self, report_types=(), acknowledged=None, fromdate=None, todate=None):
+		data = dict(Action='GetReportCount',
+					Acknowledged=acknowledged,
+					AvailableFromDate=fromdate,
+					AvailableToDate=todate)
+		data.update(self.enumerate_param('ReportTypeList.Type.', report_types))
+		return self.make_request(data)
+
+	def get_report_list(self, requestids=(), max_count=None, types=(), acknowledged=None,
+						fromdate=None, todate=None):
+		data = dict(Action='GetReportList',
+					Acknowledged=acknowledged,
+					AvailableFromDate=fromdate,
+					AvailableToDate=todate,
+					MaxCount=max_count)
+		data.update(self.enumerate_param('ReportRequestIdList.Id.', requestids))
+		data.update(self.enumerate_param('ReportTypeList.Type.', types))
+		return self.make_request(data)
+
+	def get_report_list_by_next_token(self, token):
+		data = dict(Action='GetReportListByNextToken', NextToken=token)
+		return self.make_request(data)
+
+	def get_report_request_count(self, report_types=(), processingstatuses=(), fromdate=None, todate=None):
+		data = dict(Action='GetReportRequestCount',
+					RequestedFromDate=fromdate,
+					RequestedToDate=todate)
+		data.update(self.enumerate_param('ReportTypeList.Type.', report_types))
+		data.update(self.enumerate_param('ReportProcessingStatusList.Status.', processingstatuses))
+		return self.make_request(data)
+
+	def get_report_request_list(self, requestids=(), types=(), processingstatuses=(),
+								max_count=None, fromdate=None, todate=None):
+		data = dict(Action='GetReportRequestList',
+					MaxCount=max_count,
+					RequestedFromDate=fromdate,
+					RequestedToDate=todate)
+		data.update(self.enumerate_param('ReportRequestIdList.Id.', requestids))
+		data.update(self.enumerate_param('ReportTypeList.Type.', types))
+		data.update(self.enumerate_param('ReportProcessingStatusList.Status.', processingstatuses))
+		return self.make_request(data)
+
+	def get_report_request_list_by_next_token(self, token):
+		data = dict(Action='GetReportRequestListByNextToken', NextToken=token)
+		return self.make_request(data)
+
+	def request_report(self, report_type, start_date=None, end_date=None, marketplaceids=()):
+		data = dict(Action='RequestReport',
+					ReportType=report_type,
+					StartDate=start_date,
+					EndDate=end_date)
+		data.update(self.enumerate_param('MarketplaceIdList.Id.', marketplaceids))
+		return self.make_request(data)
+
+	### ReportSchedule ###
+
+	def get_report_schedule_list(self, types=()):
+		data = dict(Action='GetReportScheduleList')
+		data.update(self.enumerate_param('ReportTypeList.Type.', types))
+		return self.make_request(data)
+
+	def get_report_schedule_count(self, types=()):
+		data = dict(Action='GetReportScheduleCount')
+		data.update(self.enumerate_param('ReportTypeList.Type.', types))
+		return self.make_request(data)
+
+
+class Orders(MWS):
+	""" Amazon Orders API """
+
+	URI = "/Orders/2013-09-01"
+	VERSION = "2013-09-01"
+	NS = '{https://mws.amazonservices.com/Orders/2011-01-01}'
+
+	def list_orders(self, marketplaceids, created_after=None, created_before=None, lastupdatedafter=None,
+					lastupdatedbefore=None, orderstatus=(), fulfillment_channels=(),
+					payment_methods=(), buyer_email=None, seller_orderid=None, max_results='100'):
+
+		data = dict(Action='ListOrders',
+					CreatedAfter=created_after,
+					CreatedBefore=created_before,
+					LastUpdatedAfter=lastupdatedafter,
+					LastUpdatedBefore=lastupdatedbefore,
+					BuyerEmail=buyer_email,
+					SellerOrderId=seller_orderid,
+					MaxResultsPerPage=max_results,
+					)
+		data.update(self.enumerate_param('OrderStatus.Status.', orderstatus))
+		data.update(self.enumerate_param('MarketplaceId.Id.', marketplaceids))
+		data.update(self.enumerate_param('FulfillmentChannel.Channel.', fulfillment_channels))
+		data.update(self.enumerate_param('PaymentMethod.Method.', payment_methods))
+		return self.make_request(data)
+
+	def list_orders_by_next_token(self, token):
+		data = dict(Action='ListOrdersByNextToken', NextToken=token)
+		return self.make_request(data)
+
+	def get_order(self, amazon_order_ids):
+		data = dict(Action='GetOrder')
+		data.update(self.enumerate_param('AmazonOrderId.Id.', amazon_order_ids))
+		return self.make_request(data)
+
+	def list_order_items(self, amazon_order_id):
+		data = dict(Action='ListOrderItems', AmazonOrderId=amazon_order_id)
+		return self.make_request(data)
+
+	def list_order_items_by_next_token(self, token):
+		data = dict(Action='ListOrderItemsByNextToken', NextToken=token)
+		return self.make_request(data)
+
+
+class Products(MWS):
+	""" Amazon MWS Products API """
+
+	URI = '/Products/2011-10-01'
+	VERSION = '2011-10-01'
+	NS = '{http://mws.amazonservices.com/schema/Products/2011-10-01}'
+
+	def list_matching_products(self, marketplaceid, query, contextid=None):
+		""" Returns a list of products and their attributes, ordered by
+			relevancy, based on a search query that you specify.
+			Your search query can be a phrase that describes the product
+			or it can be a product identifier such as a UPC, EAN, ISBN, or JAN.
+		"""
+		data = dict(Action='ListMatchingProducts',
+					MarketplaceId=marketplaceid,
+					Query=query,
+					QueryContextId=contextid)
+		return self.make_request(data)
+
+	def get_matching_product(self, marketplaceid, asins):
+		""" Returns a list of products and their attributes, based on a list of
+			ASIN values that you specify.
+		"""
+		data = dict(Action='GetMatchingProduct', MarketplaceId=marketplaceid)
+		data.update(self.enumerate_param('ASINList.ASIN.', asins))
+		return self.make_request(data)
+
+	def get_matching_product_for_id(self, marketplaceid, type, id):
+		""" Returns a list of products and their attributes, based on a list of
+			product identifier values (asin, sellersku, upc, ean, isbn and JAN)
+			Added in Fourth Release, API version 2011-10-01
+		"""
+		data = dict(Action='GetMatchingProductForId',
+					MarketplaceId=marketplaceid,
+					IdType=type)
+		data.update(self.enumerate_param('IdList.Id', id))
+		return self.make_request(data)
+
+	def get_competitive_pricing_for_sku(self, marketplaceid, skus):
+		""" Returns the current competitive pricing of a product,
+			based on the SellerSKU and MarketplaceId that you specify.
+		"""
+		data = dict(Action='GetCompetitivePricingForSKU', MarketplaceId=marketplaceid)
+		data.update(self.enumerate_param('SellerSKUList.SellerSKU.', skus))
+		return self.make_request(data)
+
+	def get_competitive_pricing_for_asin(self, marketplaceid, asins):
+		""" Returns the current competitive pricing of a product,
+			based on the ASIN and MarketplaceId that you specify.
+		"""
+		data = dict(Action='GetCompetitivePricingForASIN', MarketplaceId=marketplaceid)
+		data.update(self.enumerate_param('ASINList.ASIN.', asins))
+		return self.make_request(data)
+
+	def get_lowest_offer_listings_for_sku(self, marketplaceid, skus, condition="Any", excludeme="False"):
+		data = dict(Action='GetLowestOfferListingsForSKU',
+					MarketplaceId=marketplaceid,
+					ItemCondition=condition,
+					ExcludeMe=excludeme)
+		data.update(self.enumerate_param('SellerSKUList.SellerSKU.', skus))
+		return self.make_request(data)
+
+	def get_lowest_offer_listings_for_asin(self, marketplaceid, asins, condition="Any", excludeme="False"):
+		data = dict(Action='GetLowestOfferListingsForASIN',
+					MarketplaceId=marketplaceid,
+					ItemCondition=condition,
+					ExcludeMe=excludeme)
+		data.update(self.enumerate_param('ASINList.ASIN.', asins))
+		return self.make_request(data)
+
+	def get_product_categories_for_sku(self, marketplaceid, sku):
+		data = dict(Action='GetProductCategoriesForSKU',
+					MarketplaceId=marketplaceid,
+					SellerSKU=sku)
+		return self.make_request(data)
+
+	def get_product_categories_for_asin(self, marketplaceid, asin):
+		data = dict(Action='GetProductCategoriesForASIN',
+					MarketplaceId=marketplaceid,
+					ASIN=asin)
+		return self.make_request(data)
+
+	def get_my_price_for_sku(self, marketplaceid, skus, condition=None):
+		data = dict(Action='GetMyPriceForSKU',
+					MarketplaceId=marketplaceid,
+					ItemCondition=condition)
+		data.update(self.enumerate_param('SellerSKUList.SellerSKU.', skus))
+		return self.make_request(data)
+
+	def get_my_price_for_asin(self, marketplaceid, asins, condition=None):
+		data = dict(Action='GetMyPriceForASIN',
+					MarketplaceId=marketplaceid,
+					ItemCondition=condition)
+		data.update(self.enumerate_param('ASINList.ASIN.', asins))
+		return self.make_request(data)
+
+
+class Sellers(MWS):
+	""" Amazon MWS Sellers API """
+
+	URI = '/Sellers/2011-07-01'
+	VERSION = '2011-07-01'
+	NS = '{http://mws.amazonservices.com/schema/Sellers/2011-07-01}'
+
+	def list_marketplace_participations(self):
+		"""
+			Returns a list of marketplaces a seller can participate in and
+			a list of participations that include seller-specific information in that marketplace.
+			The operation returns only those marketplaces where the seller's account is in an active state.
+		"""
+
+		data = dict(Action='ListMarketplaceParticipations')
+		return self.make_request(data)
+
+	def list_marketplace_participations_by_next_token(self, token):
+		"""
+			Takes a "NextToken" and returns the same information as "list_marketplace_participations".
+			Based on the "NextToken".
+		"""
+		data = dict(Action='ListMarketplaceParticipations', NextToken=token)
+		return self.make_request(data)
+
+#### Fulfillment APIs ####
+
+class InboundShipments(MWS):
+	URI = "/FulfillmentInboundShipment/2010-10-01"
+	VERSION = '2010-10-01'
+
+	# To be completed
+
+
+class Inventory(MWS):
+	""" Amazon MWS Inventory Fulfillment API """
+
+	URI = '/FulfillmentInventory/2010-10-01'
+	VERSION = '2010-10-01'
+	NS = "{http://mws.amazonaws.com/FulfillmentInventory/2010-10-01}"
+
+	def list_inventory_supply(self, skus=(), datetime=None, response_group='Basic'):
+		""" Returns information on available inventory """
+
+		data = dict(Action='ListInventorySupply',
+					QueryStartDateTime=datetime,
+					ResponseGroup=response_group,
+					)
+		data.update(self.enumerate_param('SellerSkus.member.', skus))
+		return self.make_request(data, "POST")
+
+	def list_inventory_supply_by_next_token(self, token):
+		data = dict(Action='ListInventorySupplyByNextToken', NextToken=token)
+		return self.make_request(data, "POST")
+
+
+class OutboundShipments(MWS):
+	URI = "/FulfillmentOutboundShipment/2010-10-01"
+	VERSION = "2010-10-01"
+	# To be completed
+
+
+class Recommendations(MWS):
+
+	""" Amazon MWS Recommendations API """
+
+	URI = '/Recommendations/2013-04-01'
+	VERSION = '2013-04-01'
+	NS = "{https://mws.amazonservices.com/Recommendations/2013-04-01}"
+
+	def get_last_updated_time_for_recommendations(self, marketplaceid):
+		"""
+		Checks whether there are active recommendations for each category for the given marketplace, and if there are,
+		returns the time when recommendations were last updated for each category.
+		"""
+
+		data = dict(Action='GetLastUpdatedTimeForRecommendations',
+					MarketplaceId=marketplaceid)
+		return self.make_request(data, "POST")
+
+	def list_recommendations(self, marketplaceid, recommendationcategory=None):
+		"""
+		Returns your active recommendations for a specific category or for all categories for a specific marketplace.
+		"""
+
+		data = dict(Action="ListRecommendations",
+					MarketplaceId=marketplaceid,
+					RecommendationCategory=recommendationcategory)
+		return self.make_request(data, "POST")
+
+	def list_recommendations_by_next_token(self, token):
+		"""
+		Returns the next page of recommendations using the NextToken parameter.
+		"""
+
+		data = dict(Action="ListRecommendationsByNextToken",
+					NextToken=token)
+		return self.make_request(data, "POST")
+
+class Finances(MWS):
+	""" Amazon Finances API"""
+	URI = '/Finances/2015-05-01'
+	VERSION = '2015-05-01'
+	NS = "{https://mws.amazonservices.com/Finances/2015-05-01}"
+
+	def list_financial_events(self , posted_after=None, posted_before=None,
+		 					amazon_order_id=None, max_results='100'):
+
+		data = dict(Action='ListFinancialEvents',
+					PostedAfter=posted_after,
+					PostedBefore=posted_before,
+					AmazonOrderId=amazon_order_id,
+					MaxResultsPerPage=max_results,
+					)
+		return self.make_request(data)
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.js b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.js
new file mode 100644
index 0000000..a9925ad
--- /dev/null
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.js
@@ -0,0 +1,3 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.json b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.json
new file mode 100644
index 0000000..771d1f2
--- /dev/null
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.json
@@ -0,0 +1,974 @@
+{
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "autoname": "", 
+ "beta": 0, 
+ "creation": "2018-07-31 05:51:41.357047", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "enable_amazon", 
+   "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": "Enable Amazon", 
+   "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, 
+   "collapsible_depends_on": "", 
+   "columns": 0, 
+   "fieldname": "mws_credentials", 
+   "fieldtype": "Section 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, 
+   "label": "MWS Credentials", 
+   "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, 
+   "fieldname": "seller_id", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Seller ID", 
+   "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": 1, 
+   "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, 
+   "fieldname": "aws_access_key_id", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "AWS Access Key ID", 
+   "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": 1, 
+   "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, 
+   "fieldname": "mws_auth_token", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "MWS Auth Token", 
+   "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": 1, 
+   "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, 
+   "fieldname": "secret_key", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Secret Key", 
+   "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": 1, 
+   "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, 
+   "fieldname": "column_break_4", 
+   "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_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "market_place_id", 
+   "fieldtype": "Data", 
+   "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": "Market Place ID", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "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, 
+   "fieldname": "region", 
+   "fieldtype": "Select", 
+   "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": "Region", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "\nIN\nCN\nJP\nBR\nAU\nES\nUK\nFR\nDE\nIT\nCA\nUS\nMX", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "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, 
+   "fieldname": "domain", 
+   "fieldtype": "Data", 
+   "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": "Domain", 
+   "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": 1, 
+   "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, 
+   "fieldname": "section_break_13", 
+   "fieldtype": "Section 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_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "company", 
+   "fieldtype": "Link", 
+   "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": "Company", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Company", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "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, 
+   "fieldname": "warehouse", 
+   "fieldtype": "Link", 
+   "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": "Warehouse", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Warehouse", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "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, 
+   "fieldname": "item_group", 
+   "fieldtype": "Link", 
+   "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": "Item Group", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Item Group", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "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, 
+   "fieldname": "price_list", 
+   "fieldtype": "Link", 
+   "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": "Price List", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Price List", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "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, 
+   "fieldname": "column_break_17", 
+   "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_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "customer_group", 
+   "fieldtype": "Link", 
+   "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": "Customer Group", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Customer Group", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "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, 
+   "fieldname": "territory", 
+   "fieldtype": "Link", 
+   "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": "Territory", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Territory", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "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, 
+   "fieldname": "customer_type", 
+   "fieldtype": "Select", 
+   "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": "Customer Type", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Individual\nCompany", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "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, 
+   "fieldname": "market_place_account_group", 
+   "fieldtype": "Link", 
+   "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": "Market Place Account Group", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Account", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "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, 
+   "fieldname": "section_break_12", 
+   "fieldtype": "Section 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_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "description": "Amazon will synch data updated after this date", 
+   "fieldname": "after_date", 
+   "fieldtype": "Datetime", 
+   "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": "After Date", 
+   "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": 1, 
+   "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, 
+   "description": "Get financial breakup of Taxes and charges data by Amazon ", 
+   "fieldname": "taxes_charges", 
+   "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": "Synch Taxes and Charges", 
+   "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, 
+   "description": "Always synch your products from Amazon MWS before synching the Orders details", 
+   "fieldname": "synch_products", 
+   "fieldtype": "Button", 
+   "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": "Synch Products", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "get_products_details", 
+   "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, 
+   "description": "Click this button to pull your Sales Order data from Amazon MWS.", 
+   "fieldname": "synch_orders", 
+   "fieldtype": "Button", 
+   "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": "Synch Orders", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "get_order_details", 
+   "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, 
+   "fieldname": "column_break_10", 
+   "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_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "default": "1", 
+   "description": "Check this to enable a scheduled Daily synchronization routine via scheduler", 
+   "fieldname": "enable_synch", 
+   "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": "Enable Scheduled Synch", 
+   "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, 
+   "default": "3", 
+   "fieldname": "max_retry_limit", 
+   "fieldtype": "Int", 
+   "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": "Max Retry Limit", 
+   "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
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 1, 
+ "istable": 0, 
+ "max_attachments": 0, 
+ "modified": "2018-08-23 20:52:58.471424", 
+ "modified_by": "Administrator", 
+ "module": "ERPNext Integrations", 
+ "name": "Amazon MWS Settings", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [
+  {
+   "amend": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 0, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 0, 
+   "role": "System Manager", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }
+ ], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0, 
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py
new file mode 100644
index 0000000..7e64915
--- /dev/null
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+import dateutil
+from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
+from amazon_methods import get_products_details, get_orders
+
+class AmazonMWSSettings(Document):
+	def validate(self):
+		if self.enable_amazon == 1:
+			setup_custom_fields()
+
+	def get_products_details(self):
+		if self.enable_amazon == 1:
+			get_products_details()
+
+	def get_order_details(self):
+		if self.enable_amazon == 1:
+			after_date = dateutil.parser.parse(self.after_date).strftime("%Y-%m-%d")
+			get_orders(after_date = after_date)
+
+def schedule_get_order_details():
+	mws_settings = frappe.get_doc("Amazon MWS Settings")
+	if mws_settings.enable_synch:
+		after_date = dateutil.parser.parse(mws_settings.after_date).strftime("%Y-%m-%d")
+		get_orders(after_date = after_date)
+
+def setup_custom_fields():
+	custom_fields = {
+		"Item": [dict(fieldname='amazon_item_code', label='Amazon Item Code',
+			fieldtype='Data', insert_after='series', read_only=1, print_hide=1)],
+		"Sales Order": [dict(fieldname='amazon_order_id', label='Amazon Order ID',
+			fieldtype='Data', insert_after='title', read_only=1, print_hide=1)]
+	}
+
+	create_custom_fields(custom_fields)
\ No newline at end of file
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.js b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.js
new file mode 100644
index 0000000..9c89909
--- /dev/null
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Amazon MWS Settings", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Amazon MWS Settings
+		() => frappe.tests.make('Amazon MWS Settings', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.py
new file mode 100644
index 0000000..7b40014
--- /dev/null
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import unittest
+
+class TestAmazonMWSSettings(unittest.TestCase):
+	pass
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py
new file mode 100644
index 0000000..985ac08
--- /dev/null
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py
@@ -0,0 +1,102 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Tue Jun 26 15:42:07 2012
+
+Borrowed from https://github.com/timotheus/ebaysdk-python
+
+@author: pierre
+"""
+
+import xml.etree.ElementTree as ET
+import re
+
+
+class object_dict(dict):
+	"""object view of dict, you can
+	>>> a = object_dict()
+	>>> a.fish = 'fish'
+	>>> a['fish']
+	'fish'
+	>>> a['water'] = 'water'
+	>>> a.water
+	'water'
+ 	>>> a.test = {'value': 1}
+	>>> a.test2 = object_dict({'name': 'test2', 'value': 2})
+	>>> a.test, a.test2.name, a.test2.value
+	(1, 'test2', 2)
+	"""
+	def __init__(self, initd=None):
+		if initd is None:
+			initd = {}
+		dict.__init__(self, initd)
+
+	def __getattr__(self, item):
+
+		d = self.__getitem__(item)
+
+		if isinstance(d, dict) and 'value' in d and len(d) == 1:
+			return d['value']
+		else:
+			return d
+
+	# if value is the only key in object, you can omit it
+	def __setstate__(self, item):
+		return False
+
+	def __setattr__(self, item, value):
+		self.__setitem__(item, value)
+
+	def getvalue(self, item, value=None):
+		return self.get(item, {}).get('value', value)
+
+
+class xml2dict(object):
+
+	def __init__(self):
+		pass
+
+	def _parse_node(self, node):
+		node_tree = object_dict()
+		# Save attrs and text, hope there will not be a child with same name
+		if node.text:
+			node_tree.value = node.text
+		for (k, v) in node.attrib.items():
+			k, v = self._namespace_split(k, object_dict({'value':v}))
+			node_tree[k] = v
+		#Save childrens
+		for child in node.getchildren():
+			tag, tree = self._namespace_split(child.tag,
+											self._parse_node(child))
+			if tag not in node_tree:  # the first time, so store it in dict
+				node_tree[tag] = tree
+				continue
+			old = node_tree[tag]
+			if not isinstance(old, list):
+				node_tree.pop(tag)
+				node_tree[tag] = [old]  # multi times, so change old dict to a list
+			node_tree[tag].append(tree)  # add the new one
+
+		return node_tree
+
+	def _namespace_split(self, tag, value):
+		"""
+		Split the tag '{http://cs.sfsu.edu/csc867/myscheduler}patients'
+		ns = http://cs.sfsu.edu/csc867/myscheduler
+		name = patients
+		"""
+		result = re.compile("\{(.*)\}(.*)").search(tag)
+		if result:
+			value.namespace, tag = result.groups()
+
+		return (tag, value)
+
+	def parse(self, file):
+		"""parse a xml file to a dict"""
+		f = open(file, 'r')
+		return self.fromstring(f.read())
+
+	def fromstring(self, s):
+		"""parse a string"""
+		t = ET.fromstring(s)
+		root_tag, root_tree = self._namespace_split(t.tag, self._parse_node(t))
+		return object_dict({root_tag: root_tree})
\ No newline at end of file
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 300808a..20552be 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -224,7 +224,8 @@
 scheduler_events = {
 	"hourly": [
 		'erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group.trigger_emails',
-		"erpnext.accounts.doctype.subscription.subscription.process_all"
+		"erpnext.accounts.doctype.subscription.subscription.process_all",
+		"erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_settings.schedule_get_order_details"
 	],
 	"daily": [
 		"erpnext.stock.reorder_item.reorder_item",