# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from __future__ import unicode_literals
import webnotes
from webnotes import _, msgprint
from webnotes.utils import flt

from buying.utils import get_item_details
from setup.utils import get_company_currency

from controllers.stock_controller import StockController

class WrongWarehouseCompany(Exception): pass

class BuyingController(StockController):
	def onload_post_render(self):
		self.set_price_list_currency("buying")

		# contact, address, item details
		self.set_missing_values()
		
		self.set_taxes("Purchase Taxes and Charges", "purchase_tax_details", "purchase_other_charges")
	
	def validate(self):
		super(BuyingController, self).validate()
		self.validate_stock_or_nonstock_items()
		self.validate_warehouse_belongs_to_company()
		
	def set_missing_values(self, for_validate=False):
		# set contact and address details for supplier, if they are not mentioned
		if self.doc.supplier and not (self.doc.contact_person and self.doc.supplier_address):
			for fieldname, val in self.get_default_address_and_contact("supplier").items():
				if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
					self.doc.fields[fieldname] = val
		
		self.set_missing_item_details(get_item_details)
		
	def set_supplier_defaults(self):
		self.get_default_supplier_address(self.doc.fields)
						
	def get_purchase_tax_details(self):
		self.doclist = self.doc.clear_table(self.doclist, "purchase_tax_details")
		self.set_taxes()
			
	def validate_warehouse_belongs_to_company(self):
		for warehouse, company in webnotes.conn.get_values("Warehouse", 
			self.doclist.get_distinct_values("warehouse"), "company").items():
			if company and company != self.doc.company:
				webnotes.msgprint(_("Company mismatch for Warehouse") + (": %s" % (warehouse,)),
					raise_exception=WrongWarehouseCompany)

	def validate_stock_or_nonstock_items(self):
		items = [d.item_code for d in self.doclist.get({"parentfield": self.fname})]
		if self.stock_items:
			nonstock_items = list(set(items) - set(self.stock_items))
			if nonstock_items:
				webnotes.msgprint(_("Stock and non-stock items can not be entered in the same ") + 
					self.doc.doctype + _(""". You should make separate documents for them.
					Stock Items: """) + ", ".join(self.stock_items) + _("""
					Non-stock Items: """) + ", ".join(nonstock_items), raise_exception=1)
				
		elif items and not self.stock_items:
			tax_for_valuation = [d.account_head for d in 
				self.doclist.get({"parentfield": "purchase_tax_details"}) 
				if d.category in ["Valuation", "Valuation and Total"]]
			if tax_for_valuation:
				webnotes.msgprint(_("""Tax Category can not be 'Valuation' or 'Valuation and Total' 
					as all items are non-stock items"""), raise_exception=1)
			
	def set_total_in_words(self):
		from webnotes.utils import money_in_words
		company_currency = get_company_currency(self.doc.company)
		if self.meta.get_field("in_words"):
			self.doc.in_words = money_in_words(self.doc.grand_total, company_currency)
		if self.meta.get_field("in_words_import"):
			self.doc.in_words_import = money_in_words(self.doc.grand_total_import,
		 		self.doc.currency)
		
	def calculate_taxes_and_totals(self):
		self.other_fname = "purchase_tax_details"
		super(BuyingController, self).calculate_taxes_and_totals()
		self.calculate_total_advance("Purchase Invoice", "advance_allocation_details")
		
	def calculate_item_values(self):
		# hack! - cleaned up in _cleanup()
		if self.doc.doctype != "Purchase Invoice":
			df = self.meta.get_field("purchase_rate", parentfield=self.fname)
			df.fieldname = "rate"
			
		for item in self.item_doclist:
			# hack! - cleaned up in _cleanup()
			if self.doc.doctype != "Purchase Invoice":
				item.rate = item.purchase_rate
				
			self.round_floats_in(item)

			if item.discount_rate == 100.0:
				item.import_rate = 0.0
			elif item.import_ref_rate:
				item.import_rate = flt(item.import_ref_rate * (1.0 - (item.discount_rate / 100.0)),
					self.precision("import_rate", item))
						
			item.import_amount = flt(item.import_rate * item.qty,
				self.precision("import_amount", item))
			item.item_tax_amount = 0.0;
				
			self._set_in_company_currency(item, "import_ref_rate", "purchase_ref_rate")
			self._set_in_company_currency(item, "import_rate", "rate")
			self._set_in_company_currency(item, "import_amount", "amount")
			
	def calculate_net_total(self):
		self.doc.net_total = self.doc.net_total_import = 0.0

		for item in self.item_doclist:
			self.doc.net_total += item.amount
			self.doc.net_total_import += item.import_amount
			
		self.round_floats_in(self.doc, ["net_total", "net_total_import"])
		
	def calculate_totals(self):
		self.doc.grand_total = flt(self.tax_doclist and \
			self.tax_doclist[-1].total or self.doc.net_total, self.precision("grand_total"))
		self.doc.grand_total_import = flt(self.doc.grand_total / self.doc.conversion_rate,
			self.precision("grand_total_import"))

		self.doc.total_tax = flt(self.doc.grand_total - self.doc.net_total,
			self.precision("total_tax"))

		if self.meta.get_field("rounded_total"):
			self.doc.rounded_total = round(self.doc.grand_total)
		
		if self.meta.get_field("rounded_total_import"):
			self.doc.rounded_total_import = round(self.doc.grand_total_import)
			
	def calculate_outstanding_amount(self):
		if self.doc.doctype == "Purchase Invoice" and self.doc.docstatus < 2:
			self.doc.total_advance = flt(self.doc.total_advance,
				self.precision("total_advance"))
			self.doc.total_amount_to_pay = flt(self.doc.grand_total - flt(self.doc.write_off_amount,
				self.precision("write_off_amount")), self.precision("total_amount_to_pay"))
			self.doc.outstanding_amount = flt(self.doc.total_amount_to_pay - self.doc.total_advance,
				self.precision("outstanding_amount"))
			
	def _cleanup(self):
		super(BuyingController, self)._cleanup()
			
		# except in purchase invoice, rate field is purchase_rate		
		# reset fieldname of rate
		if self.doc.doctype != "Purchase Invoice":
			df = self.meta.get_field("rate", parentfield=self.fname)
			df.fieldname = "purchase_rate"
			
			for item in self.item_doclist:
				item.purchase_rate = item.rate
				del item.fields["rate"]
				
		if not self.meta.get_field("item_tax_amount", parentfield=self.fname):
			for item in self.item_doclist:
				del item.fields["item_tax_amount"]
				
	def set_item_tax_amount(self, item, tax, current_tax_amount):
		"""
			item_tax_amount is the total tax amount applied on that item
			stored for valuation 
			
			TODO: rename item_tax_amount to valuation_tax_amount
		"""
		if tax.category in ["Valuation", "Valuation and Total"]:
			item.item_tax_amount += flt(current_tax_amount, self.precision("item_tax_amount", item))
				
	# update valuation rate
	def update_valuation_rate(self, parentfield):
		for item in self.doclist.get({"parentfield": parentfield}):
			item.conversion_factor = item.conversion_factor or flt(webnotes.conn.get_value(
				"UOM Conversion Detail", {"parent": item.item_code, "uom": item.uom}, 
				"conversion_factor")) or 1
			
			if item.item_code and item.qty:
				self.round_floats_in(item)
				
				purchase_rate = item.rate if self.doc.doctype == "Purchase Invoice" else item.purchase_rate
				
				# if no item code, which is sometimes the case in purchase invoice, 
				# then it is not possible to track valuation against it
				item.valuation_rate = flt((purchase_rate + 
					(item.item_tax_amount + item.rm_supp_cost) / item.qty) / item.conversion_factor, 
					self.precision("valuation_rate", item))
			else:
				item.valuation_rate = 0.0
				
	def validate_for_subcontracting(self):
		if not self.doc.is_subcontracted and self.sub_contracted_items:
			webnotes.msgprint(_("""Please enter whether %s is made for subcontracting or purchasing,
			 	in 'Is Subcontracted' field""" % self.doc.doctype), raise_exception=1)
			
		if self.doc.doctype == "Purchase Receipt" and self.doc.is_subcontracted=="Yes" \
			and not self.doc.supplier_warehouse:
				webnotes.msgprint(_("Supplier Warehouse mandatory subcontracted purchase receipt"), 
					raise_exception=1)
										
	def update_raw_materials_supplied(self, raw_material_table):
		self.doclist = self.doc.clear_table(self.doclist, raw_material_table)
		if self.doc.is_subcontracted=="Yes":
			for item in self.doclist.get({"parentfield": self.fname}):
				if item.item_code in self.sub_contracted_items:
					self.add_bom_items(item, raw_material_table)

	def add_bom_items(self, d, raw_material_table):
		bom_items = self.get_items_from_default_bom(d.item_code)
		raw_materials_cost = 0
		for item in bom_items:
			required_qty = flt(item.qty_consumed_per_unit) * flt(d.qty) * flt(d.conversion_factor)
			rm_doclist = {
				"parentfield": raw_material_table,
				"doctype": self.doc.doctype + " Item Supplied",
				"reference_name": d.name,
				"bom_detail_no": item.name,
				"main_item_code": d.item_code,
				"rm_item_code": item.item_code,
				"stock_uom": item.stock_uom,
				"required_qty": required_qty,
				"conversion_factor": d.conversion_factor,
				"rate": item.rate,
				"amount": required_qty * flt(item.rate)
			}
			if self.doc.doctype == "Purchase Receipt":
				rm_doclist.update({
					"consumed_qty": required_qty,
					"description": item.description,
				})
				
			self.doclist.append(rm_doclist)
			
			raw_materials_cost += required_qty * flt(item.rate)
			
		if self.doc.doctype == "Purchase Receipt":
			d.rm_supp_cost = raw_materials_cost

	def get_items_from_default_bom(self, item_code):
		# print webnotes.conn.sql("""select name from `tabBOM` where item = '_Test FG Item'""")
		bom_items = webnotes.conn.sql("""select t2.item_code, t2.qty_consumed_per_unit, 
			t2.rate, t2.stock_uom, t2.name, t2.description 
			from `tabBOM` t1, `tabBOM Item` t2 
			where t2.parent = t1.name and t1.item = %s and t1.is_default = 1 
			and t1.docstatus = 1 and t1.is_active = 1""", item_code, as_dict=1)
		if not bom_items:
			msgprint(_("No default BOM exists for item: ") + item_code, raise_exception=1)
		
		return bom_items

	@property
	def sub_contracted_items(self):
		if not hasattr(self, "_sub_contracted_items"):
			self._sub_contracted_items = []
			item_codes = list(set(item.item_code for item in 
				self.doclist.get({"parentfield": self.fname})))
			if item_codes:
				self._sub_contracted_items = [r[0] for r in webnotes.conn.sql("""select name
					from `tabItem` where name in (%s) and is_sub_contracted_item='Yes'""" % \
					(", ".join((["%s"]*len(item_codes))),), item_codes)]

		return self._sub_contracted_items
		
	@property
	def purchase_items(self):
		if not hasattr(self, "_purchase_items"):
			self._purchase_items = []
			item_codes = list(set(item.item_code for item in 
				self.doclist.get({"parentfield": self.fname})))
			if item_codes:
				self._purchase_items = [r[0] for r in webnotes.conn.sql("""select name
					from `tabItem` where name in (%s) and is_purchase_item='Yes'""" % \
					(", ".join((["%s"]*len(item_codes))),), item_codes)]

		return self._purchase_items
