# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
# License: GNU General Public License v3. See license.txt

from __future__ import unicode_literals
import webnotes
from webnotes.utils import cint, flt, comma_or
from setup.utils import get_company_currency
from selling.utils import get_item_details
from webnotes import msgprint, _

from controllers.stock_controller import StockController

class SellingController(StockController):
	def onload_post_render(self):
		# contact, address, item details and pos details (if applicable)
		self.set_missing_values()
		
		self.set_taxes("other_charges", "charge")
		
		if self.meta.get_field("debit_to") and not self.doc.debit_to:
			self.doc.debit_to = self.get_debit_to().get("debit_to")
			
	def set_missing_values(self, for_validate=False):
		super(SellingController, self).set_missing_values(for_validate)
		
		# set contact and address details for customer, if they are not mentioned
		self.set_missing_lead_customer_details()
		
		self.set_price_list_and_item_details()
		
	def set_missing_lead_customer_details(self):
		if self.doc.customer:
			if not (self.doc.contact_person and self.doc.customer_address and self.doc.customer_name):
				for fieldname, val in self.get_customer_defaults().items():
					if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
						self.doc.fields[fieldname] = val
		
		elif self.doc.lead:
			if not (self.doc.customer_address and self.doc.customer_name and \
				self.doc.contact_display):
				for fieldname, val in self.get_lead_defaults().items():
					if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
						self.doc.fields[fieldname] = val
						
	def set_price_list_and_item_details(self):
		self.set_price_list_currency("Selling")
		self.set_missing_item_details(get_item_details)
										
	def get_other_charges(self):
		self.doclist = self.doc.clear_table(self.doclist, "other_charges")
		self.set_taxes("other_charges", "charge")
		
	def apply_shipping_rule(self):
		if self.doc.shipping_rule:
			shipping_rule = webnotes.bean("Shipping Rule", self.doc.shipping_rule)
			value = self.doc.net_total
			
			# TODO
			# shipping rule calculation based on item's net weight
			
			shipping_amount = 0.0
			for condition in shipping_rule.doclist.get({"parentfield": "shipping_rule_conditions"}):
				if not condition.to_value or (flt(condition.from_value) <= value <= flt(condition.to_value)):
					shipping_amount = condition.shipping_amount
					break
			
			self.doclist.append({
				"doctype": "Sales Taxes and Charges",
				"parentfield": "other_charges",
				"charge_type": "Actual",
				"account_head": shipping_rule.doc.account,
				"cost_center": shipping_rule.doc.cost_center,
				"description": shipping_rule.doc.label,
				"rate": shipping_amount
			})
		
	def set_total_in_words(self):
		from webnotes.utils import money_in_words
		company_currency = get_company_currency(self.doc.company)
		
		disable_rounded_total = cint(webnotes.conn.get_value("Global Defaults", None, 
			"disable_rounded_total"))
			
		if self.meta.get_field("in_words"):
			self.doc.in_words = money_in_words(disable_rounded_total and 
				self.doc.grand_total or self.doc.rounded_total, company_currency)
		if self.meta.get_field("in_words_export"):
			self.doc.in_words_export = money_in_words(disable_rounded_total and 
				self.doc.grand_total_export or self.doc.rounded_total_export, self.doc.currency)

	def set_buying_amount(self, stock_ledger_entries = None):
		from stock.utils import get_buying_amount
		if not stock_ledger_entries:
			stock_ledger_entries = self.get_stock_ledger_entries()

		item_sales_bom = {}
		for d in self.doclist.get({"parentfield": "packing_details"}):
			new_d = webnotes._dict(d.fields.copy())
			new_d.total_qty = -1 * d.qty
			item_sales_bom.setdefault(d.parent_item, []).append(new_d)
		
		if stock_ledger_entries:
			for item in self.doclist.get({"parentfield": self.fname}):
				if item.item_code in self.stock_items or \
						(item_sales_bom and item_sales_bom.get(item.item_code)):
					buying_amount = get_buying_amount(item.item_code, self.doc.doctype, self.doc.name, item.name, 
						stock_ledger_entries.get((item.item_code, item.warehouse), []), 
						item_sales_bom)
					
					item.buying_amount = buying_amount >= 0.01 and buying_amount or 0
					webnotes.conn.set_value(item.doctype, item.name, "buying_amount", 
						item.buying_amount)
						
	def check_expense_account(self, item):
		if item.buying_amount and not item.expense_account:
			msgprint(_("""Expense account is mandatory for item: """) + item.item_code, 
				raise_exception=1)
				
		if item.buying_amount and not item.cost_center:
			msgprint(_("""Cost Center is mandatory for item: """) + item.item_code, 
				raise_exception=1)
				
	def calculate_taxes_and_totals(self):
		self.other_fname = "other_charges"
		
		super(SellingController, self).calculate_taxes_and_totals()
		
		self.calculate_total_advance("Sales Invoice", "advance_adjustment_details")
		self.calculate_commission()
		self.calculate_contribution()
				
	def determine_exclusive_rate(self):
		if not any((cint(tax.included_in_print_rate) for tax in self.tax_doclist)):
			# no inclusive tax
			return
		
		for item in self.item_doclist:
			item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
			cumulated_tax_fraction = 0
			for i, tax in enumerate(self.tax_doclist):
				tax.tax_fraction_for_current_item = self.get_current_tax_fraction(tax, item_tax_map)
				
				if i==0:
					tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item
				else:
					tax.grand_total_fraction_for_current_item = \
						self.tax_doclist[i-1].grand_total_fraction_for_current_item \
						+ tax.tax_fraction_for_current_item
						
				cumulated_tax_fraction += tax.tax_fraction_for_current_item
			
			if cumulated_tax_fraction:
				item.amount = flt((item.export_amount * self.doc.conversion_rate) /
					(1 + cumulated_tax_fraction), self.precision("amount", item))
					
				item.basic_rate = flt(item.amount / item.qty, self.precision("basic_rate", item))
				
				if item.adj_rate == 100:
					item.base_ref_rate = item.basic_rate
					item.basic_rate = 0.0
				else:
					item.base_ref_rate = flt(item.basic_rate / (1 - (item.adj_rate / 100.0)),
						self.precision("base_ref_rate", item))
			
	def get_current_tax_fraction(self, tax, item_tax_map):
		"""
			Get tax fraction for calculating tax exclusive amount
			from tax inclusive amount
		"""
		current_tax_fraction = 0
		
		if cint(tax.included_in_print_rate):
			tax_rate = self._get_tax_rate(tax, item_tax_map)
			
			if tax.charge_type == "On Net Total":
				current_tax_fraction = tax_rate / 100.0
			
			elif tax.charge_type == "On Previous Row Amount":
				current_tax_fraction = (tax_rate / 100.0) * \
					self.tax_doclist[cint(tax.row_id) - 1].tax_fraction_for_current_item
			
			elif tax.charge_type == "On Previous Row Total":
				current_tax_fraction = (tax_rate / 100.0) * \
					self.tax_doclist[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
						
		return current_tax_fraction
		
	def calculate_item_values(self):
		for item in self.item_doclist:
			self.round_floats_in(item)
			
			if item.adj_rate == 100:
				item.export_rate = 0
			elif not item.export_rate:
				item.export_rate = flt(item.ref_rate * (1.0 - (item.adj_rate / 100.0)),
					self.precision("export_rate", item))
						
			item.export_amount = flt(item.export_rate * item.qty,
				self.precision("export_amount", item))

			self._set_in_company_currency(item, "ref_rate", "base_ref_rate")
			self._set_in_company_currency(item, "export_rate", "basic_rate")
			self._set_in_company_currency(item, "export_amount", "amount")
			
	def calculate_net_total(self):
		self.doc.net_total = self.doc.net_total_export = 0.0

		for item in self.item_doclist:
			self.doc.net_total += item.amount
			self.doc.net_total_export += item.export_amount
		
		self.round_floats_in(self.doc, ["net_total", "net_total_export"])
				
	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_export = flt(self.doc.grand_total / self.doc.conversion_rate, 
			self.precision("grand_total_export"))
			
		self.doc.other_charges_total = flt(self.doc.grand_total - self.doc.net_total,
			self.precision("other_charges_total"))
		self.doc.other_charges_total_export = flt(self.doc.grand_total_export - self.doc.net_total_export,
			self.precision("other_charges_total_export"))
		
		self.doc.rounded_total = round(self.doc.grand_total)
		self.doc.rounded_total_export = round(self.doc.grand_total_export)
		
	def calculate_outstanding_amount(self):
		# NOTE: 
		# write_off_amount is only for POS Invoice
		# total_advance is only for non POS Invoice
		if self.doc.doctype == "Sales Invoice" and self.doc.docstatus < 2:
			self.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount",
				"paid_amount"])
			total_amount_to_pay = self.doc.grand_total - self.doc.write_off_amount
			self.doc.outstanding_amount = flt(total_amount_to_pay - self.doc.total_advance - self.doc.paid_amount,
				self.precision("outstanding_amount"))
		
	def calculate_commission(self):
		if self.meta.get_field("commission_rate"):
			self.round_floats_in(self.doc, ["net_total", "commission_rate"])
			if self.doc.commission_rate > 100.0:
				msgprint(_(self.meta.get_label("commission_rate")) + " " + 
					_("cannot be greater than 100"), raise_exception=True)
		
			self.doc.total_commission = flt(self.doc.net_total * self.doc.commission_rate / 100.0,
				self.precision("total_commission"))

	def calculate_contribution(self):
		total = 0.0
		sales_team = self.doclist.get({"parentfield": "sales_team"})
		for sales_person in sales_team:
			self.round_floats_in(sales_person)

			sales_person.allocated_amount = flt(
				self.doc.net_total * sales_person.allocated_percentage / 100.0,
				self.precision("allocated_amount", sales_person))
			
			total += sales_person.allocated_percentage
		
		if sales_team and total != 100.0:
			msgprint(_("Total") + " " + 
				_(self.meta.get_label("allocated_percentage", parentfield="sales_team")) + 
				" " + _("should be 100%"), raise_exception=True)
			
	def validate_order_type(self):
		valid_types = ["Sales", "Maintenance", "Shopping Cart"]
		if not self.doc.order_type:
			self.doc.order_type = "Sales"
		elif self.doc.order_type not in valid_types:
			msgprint(_(self.meta.get_label("order_type")) + " " + 
				_("must be one of") + ": " + comma_or(valid_types),
				raise_exception=True)
				
	def update_serial_nos(self, cancel=False):
		from stock.doctype.stock_ledger_entry.stock_ledger_entry import update_serial_nos_after_submit, get_serial_nos
		update_serial_nos_after_submit(self, self.doc.doctype, self.fname)
		update_serial_nos_after_submit(self, self.doc.doctype, "packing_details")

		for table_fieldname in (self.fname, "packing_details"):
			for d in self.doclist.get({"parentfield": table_fieldname}):
				for serial_no in get_serial_nos(d.serial_no):
					sr = webnotes.bean("Serial No", serial_no)
					if cancel:
						sr.doc.status = "Available"
						for fieldname in ("warranty_expiry_date", "delivery_document_type", 
							"delivery_document_no", "delivery_date", "delivery_time", "customer", 
							"customer_name"):
							sr.doc.fields[fieldname] = None
					else:
						sr.doc.delivery_document_type = self.doc.doctype
						sr.doc.delivery_document_no = self.doc.name
						sr.doc.delivery_date = self.doc.posting_date
						sr.doc.delivery_time = self.doc.posting_time
						sr.doc.customer = self.doc.customer
						sr.doc.customer_name	= self.doc.customer_name
						if sr.doc.warranty_period:
							sr.doc.warranty_expiry_date	= add_days(cstr(self.doc.delivery_date), 
								cint(sr.doc.warranty_period))
						sr.doc.status =	'Delivered'

					sr.save()
