# 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 flt, cstr
from webnotes import msgprint

from webnotes.model.controller import DocListController

class StatusUpdater(DocListController):
	"""
		Updates the status of the calling records
		Delivery Note: Update Delivered Qty, Update Percent and Validate over delivery
		Sales Invoice: Update Billed Amt, Update Percent and Validate over billing
		Installation Note: Update Installed Qty, Update Percent Qty and Validate over installation
	"""

	def update_prevdoc_status(self):
		self.update_qty()
		self.validate_qty()
	
	def validate_qty(self):
		"""
			Validates qty at row level
		"""
		self.tolerance = {}
		self.global_tolerance = None
		
		for args in self.status_updater:
			# get unique transactions to update
			for d in self.doclist:
				if d.doctype == args['source_dt'] and d.fields.get(args["join_field"]):
					args['name'] = d.fields[args['join_field']]

					# get all qty where qty > target_field
					item = webnotes.conn.sql("""select item_code, `%(target_ref_field)s`, 
						`%(target_field)s`, parenttype, parent from `tab%(target_dt)s` 
						where `%(target_ref_field)s` < `%(target_field)s` 
						and name="%(name)s" and docstatus=1""" % args, as_dict=1)
					if item:
						item = item[0]
						item['idx'] = d.idx
						item['target_ref_field'] = args['target_ref_field'].replace('_', ' ')

						if not item[args['target_ref_field']]:
							msgprint("""As %(target_ref_field)s for item: %(item_code)s in \
							%(parenttype)s: %(parent)s is zero, system will not check \
							over-delivery or over-billed""" % item)
						elif args.get('no_tolerance'):
							item['reduce_by'] = item[args['target_field']] - \
								item[args['target_ref_field']]
							if item['reduce_by'] > .01:
								msgprint("""
									Row #%(idx)s: Max %(target_ref_field)s allowed for <b>Item \
									%(item_code)s</b> against <b>%(parenttype)s %(parent)s</b> \
									is <b>""" % item + cstr(item[args['target_ref_field']]) +
									 """</b>.<br>You must reduce the %(target_ref_field)s by \
									%(reduce_by)s""" % item, raise_exception=1)
					
						else:
							self.check_overflow_with_tolerance(item, args)
						
	def check_overflow_with_tolerance(self, item, args):
		"""
			Checks if there is overflow condering a relaxation tolerance
		"""
	
		# check if overflow is within tolerance
		tolerance = self.get_tolerance_for(item['item_code'])
		overflow_percent = ((item[args['target_field']] - item[args['target_ref_field']]) / 
		 	item[args['target_ref_field']]) * 100
	
		if overflow_percent - tolerance > 0.01:
			item['max_allowed'] = flt(item[args['target_ref_field']] * (100+tolerance)/100)
			item['reduce_by'] = item[args['target_field']] - item['max_allowed']
		
			msgprint("""
				Row #%(idx)s: Max %(target_ref_field)s allowed for <b>Item %(item_code)s</b> \
				against <b>%(parenttype)s %(parent)s</b> is <b>%(max_allowed)s</b>. 
				
				If you want to increase your overflow tolerance, please increase tolerance %% in \
				Global Defaults or Item master. 
				
				Or, you must reduce the %(target_ref_field)s by %(reduce_by)s
				
				Also, please check if the order item has already been billed in the Sales Order""" % 
				item, raise_exception=1)
				
	def get_tolerance_for(self, item_code):
		"""
			Returns the tolerance for the item, if not set, returns global tolerance
		"""
		if self.tolerance.get(item_code): return self.tolerance[item_code]
		
		tolerance = flt(webnotes.conn.get_value('Item',item_code,'tolerance') or 0)

		if not tolerance:
			if self.global_tolerance == None:
				self.global_tolerance = flt(webnotes.conn.get_value('Global Defaults', None, 
					'tolerance'))
			tolerance = self.global_tolerance
		
		self.tolerance[item_code] = tolerance
		return tolerance
	

	def update_qty(self, change_modified=True):
		"""
			Updates qty at row level
		"""
		for args in self.status_updater:
			# condition to include current record (if submit or no if cancel)
			if self.doc.docstatus == 1:
				args['cond'] = ' or parent="%s"' % self.doc.name
			else:
				args['cond'] = ' and parent!="%s"' % self.doc.name
			
			args['modified_cond'] = ''
			if change_modified:
				args['modified_cond'] = ', modified = now()'
		
			# update quantities in child table
			for d in self.doclist:
				if d.doctype == args['source_dt']:
					# updates qty in the child table
					args['detail_id'] = d.fields.get(args['join_field'])
					
					args['second_source_condition'] = ""
					if args.get('second_source_dt') and args.get('second_source_field') \
							and args.get('second_join_field'):
						args['second_source_condition'] = """ + (select sum(%(second_source_field)s) 
							from `tab%(second_source_dt)s` 
							where `%(second_join_field)s`="%(detail_id)s" 
							and (docstatus=1))""" % args
			
					if args['detail_id']:
						webnotes.conn.sql("""update `tab%(target_dt)s` 
							set %(target_field)s = (select sum(%(source_field)s) 
								from `tab%(source_dt)s` where `%(join_field)s`="%(detail_id)s" 
								and (docstatus=1 %(cond)s)) %(second_source_condition)s
							where name='%(detail_id)s'""" % args)
		
			# get unique transactions to update
			for name in set([d.fields.get(args['percent_join_field']) for d in self.doclist 
					if d.doctype == args['source_dt']]):
				if name:
					args['name'] = name
				
					# update percent complete in the parent table
					webnotes.conn.sql("""update `tab%(target_parent_dt)s` 
						set %(target_parent_field)s = (select sum(if(%(target_ref_field)s > 
							ifnull(%(target_field)s, 0), %(target_field)s, 
							%(target_ref_field)s))/sum(%(target_ref_field)s)*100 
							from `tab%(target_dt)s` where parent="%(name)s") %(modified_cond)s
						where name='%(name)s'""" % args)

					# update field
					if args.get('status_field'):
						webnotes.conn.sql("""update `tab%(target_parent_dt)s` 
							set %(status_field)s = if(ifnull(%(target_parent_field)s,0)<0.001, 
								'Not %(keyword)s', if(%(target_parent_field)s>=99.99, 
								'Fully %(keyword)s', 'Partly %(keyword)s'))
							where name='%(name)s'""" % args)