<commit_before># 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
import webnotes.defaults

from webnotes.utils import add_days, cint, cstr, date_diff, flt, getdate, nowdate, \
	get_first_day, get_last_day

from webnotes.utils.email_lib import sendmail
from webnotes.utils import comma_and
from webnotes.model.doc import make_autoname
from webnotes.model.bean import getlist
from webnotes.model.code import get_obj
from webnotes import _, msgprint

month_map = {'Monthly': 1, 'Quarterly': 3, 'Half-yearly': 6, 'Yearly': 12}

from controllers.selling_controller import SellingController

class DocType(SellingController):
	def __init__(self,d,dl):
		self.doc, self.doclist = d, dl
		self.log = []
		self.tname = 'Sales Invoice Item'
		self.fname = 'entries'

	def validate(self):
		super(DocType, self).validate()
		self.fetch_missing_values()
		self.validate_posting_time()
		self.so_dn_required()
		self.validate_proj_cust()
		sales_com_obj = get_obj('Sales Common')
		sales_com_obj.check_stop_sales_order(self)
		sales_com_obj.check_active_sales_items(self)
		sales_com_obj.check_conversion_rate(self)
		sales_com_obj.validate_max_discount(self, 'entries')
		sales_com_obj.get_allocated_sum(self)
		sales_com_obj.validate_fiscal_year(self.doc.fiscal_year, 
			self.doc.posting_date,'Posting Date')
		self.validate_customer()
		self.validate_customer_account()
		self.validate_debit_acc()
		self.validate_fixed_asset_account()
		self.clear_unallocated_advances("Sales Invoice Advance", "advance_adjustment_details")
		self.add_remarks()
		if cint(self.doc.is_pos):
			self.validate_pos()
			self.validate_write_off_account()
			if cint(self.doc.update_stock):
				sl = get_obj('Stock Ledger')
				sl.validate_serial_no(self, 'entries')
				sl.validate_serial_no(self, 'packing_details')
				self.validate_item_code()
				self.update_current_stock()
				self.validate_delivery_note()
		if not self.doc.is_opening:
			self.doc.is_opening = 'No'
		self.set_aging_date()
		self.set_against_income_account()
		self.validate_c_form()
		self.validate_time_logs_are_submitted()
		self.validate_recurring_invoice()
		
	def on_submit(self):
		if cint(self.doc.is_pos) == 1:
			if cint(self.doc.update_stock) == 1:
				sl_obj = get_obj("Stock Ledger")
				sl_obj.validate_serial_no_warehouse(self, 'entries')
				sl_obj.validate_serial_no_warehouse(self, 'packing_details')
				
				sl_obj.update_serial_record(self, 'entries', is_submit = 1, is_incoming = 0)
				sl_obj.update_serial_record(self, 'packing_details', is_submit = 1, is_incoming = 0)
				
				self.update_stock_ledger(update_stock=1)
		else:
			# Check for Approving Authority
			if not self.doc.recurring_id:
				get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, 
				 	self.doc.company, self.doc.grand_total, self)
				
		self.set_buying_amount()
		self.check_prev_docstatus()
		get_obj("Sales Common").update_prevdoc_detail(1,self)
		
		# this sequence because outstanding may get -ve
		self.make_gl_entries()

		if not cint(self.doc.is_pos) == 1:
			self.update_against_document_in_jv()

		self.update_c_form()
		self.update_time_log_batch(self.doc.name)
		self.convert_to_recurring()

	def before_cancel(self):
		self.update_time_log_batch(None)

	def on_cancel(self):
		if cint(self.doc.is_pos) == 1:
			if cint(self.doc.update_stock) == 1:
				sl = get_obj('Stock Ledger')
				sl.update_serial_record(self, 'entries', is_submit = 0, is_incoming = 0)
				sl.update_serial_record(self, 'packing_details', is_submit = 0, is_incoming = 0)
				
				self.update_stock_ledger(update_stock = -1)
		
		sales_com_obj = get_obj(dt = 'Sales Common')
		sales_com_obj.check_stop_sales_order(self)
		
		from accounts.utils import remove_against_link_from_jv
		remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_invoice")

		sales_com_obj.update_prevdoc_detail(0, self)
		
		self.make_cancel_gl_entries()
		
	def on_update_after_submit(self):
		self.validate_recurring_invoice()
		self.convert_to_recurring()
		
	def fetch_missing_values(self):
		# fetch contact and address details for customer, if they are not mentioned
		if not (self.doc.contact_person and self.doc.customer_address):
			for fieldname, val in self.get_default_address_and_contact("customer").items():
				if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
					self.doc.fields[fieldname] = val
					
		# fetch missing item values
		for item in self.doclist.get({"parentfield": "entries"}):
			if item.fields.get("item_code"):
				ret = get_obj('Sales Common').get_item_details(item.fields, self)
				for fieldname, value in ret.items():
					if self.meta.get_field(fieldname, parentfield="entries") and \
						not item.fields.get(fieldname):
							item.fields[fieldname] = value
		
		# fetch pos details, if they are not fetched
		if cint(self.doc.is_pos):
			self.set_pos_fields(for_validate=True)
			
	def update_time_log_batch(self, sales_invoice):
		for d in self.doclist.get({"doctype":"Sales Invoice Item"}):
			if d.time_log_batch:
				tlb = webnotes.bean("Time Log Batch", d.time_log_batch)
				tlb.doc.sales_invoice = sales_invoice
				tlb.update_after_submit()

	def validate_time_logs_are_submitted(self):
		for d in self.doclist.get({"doctype":"Sales Invoice Item"}):
			if d.time_log_batch:
				status = webnotes.conn.get_value("Time Log Batch", d.time_log_batch, "status")
				if status!="Submitted":
					webnotes.msgprint(_("Time Log Batch status must be 'Submitted'") + ":" + d.time_log_batch,
						raise_exception=True)

	def set_pos_fields(self, for_validate=False):
		"""Set retail related fields from pos settings"""
		if cint(self.doc.is_pos) != 1:
			return
			
		if self.pos_settings:
			pos = self.pos_settings[0]
			
			self.doc.conversion_rate = flt(pos.conversion_rate)
			
			if not self.doc.debit_to:
				self.doc.debit_to = self.doc.customer and webnotes.conn.get_value("Account", {
					"name": self.doc.customer + " - " + self.get_company_abbr(), 
					"docstatus": ["!=", 2]
				}) or pos.customer_account
				
			for fieldname in ('territory', 'naming_series', 'currency', 'charge', 'letter_head', 'tc_name',
				'price_list_name', 'company', 'select_print_heading', 'cash_bank_account'):
					if (not for_validate) or (for_validate and not self.doc.fields.get(fieldname)):
						self.doc.fields[fieldname] = pos.get(fieldname)

			# set pos values in items
			for doc in self.doclist.get({"parentfield": "entries"}):
				if doc.fields.get('item_code'):
					for fieldname, val in self.apply_pos_settings(doc.fields).items():
						if (not for_validate) or (for_validate and not self.doc.fields.get(fieldname)):
							doc.fields[fieldname] = val

			# fetch terms	
			if self.doc.tc_name and not self.doc.terms:
				self.get_tc_details()
			<commit_msg>[sales invoice] [fix] bug fix in setting pos values on save<commit_after># 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
import webnotes.defaults

from webnotes.utils import add_days, cint, cstr, date_diff, flt, getdate, nowdate, \
	get_first_day, get_last_day

from webnotes.utils.email_lib import sendmail
from webnotes.utils import comma_and
from webnotes.model.doc import make_autoname
from webnotes.model.bean import getlist
from webnotes.model.code import get_obj
from webnotes import _, msgprint

month_map = {'Monthly': 1, 'Quarterly': 3, 'Half-yearly': 6, 'Yearly': 12}

from controllers.selling_controller import SellingController

class DocType(SellingController):
	def __init__(self,d,dl):
		self.doc, self.doclist = d, dl
		self.log = []
		self.tname = 'Sales Invoice Item'
		self.fname = 'entries'

	def validate(self):
		super(DocType, self).validate()
		self.fetch_missing_values()
		self.validate_posting_time()
		self.so_dn_required()
		self.validate_proj_cust()
		sales_com_obj = get_obj('Sales Common')
		sales_com_obj.check_stop_sales_order(self)
		sales_com_obj.check_active_sales_items(self)
		sales_com_obj.check_conversion_rate(self)
		sales_com_obj.validate_max_discount(self, 'entries')
		sales_com_obj.get_allocated_sum(self)
		sales_com_obj.validate_fiscal_year(self.doc.fiscal_year, 
			self.doc.posting_date,'Posting Date')
		self.validate_customer()
		self.validate_customer_account()
		self.validate_debit_acc()
		self.validate_fixed_asset_account()
		self.clear_unallocated_advances("Sales Invoice Advance", "advance_adjustment_details")
		self.add_remarks()
		if cint(self.doc.is_pos):
			self.validate_pos()
			self.validate_write_off_account()
			if cint(self.doc.update_stock):
				sl = get_obj('Stock Ledger')
				sl.validate_serial_no(self, 'entries')
				sl.validate_serial_no(self, 'packing_details')
				self.validate_item_code()
				self.update_current_stock()
				self.validate_delivery_note()
		if not self.doc.is_opening:
			self.doc.is_opening = 'No'
		self.set_aging_date()
		self.set_against_income_account()
		self.validate_c_form()
		self.validate_time_logs_are_submitted()
		self.validate_recurring_invoice()
		
	def on_submit(self):
		if cint(self.doc.is_pos) == 1:
			if cint(self.doc.update_stock) == 1:
				sl_obj = get_obj("Stock Ledger")
				sl_obj.validate_serial_no_warehouse(self, 'entries')
				sl_obj.validate_serial_no_warehouse(self, 'packing_details')
				
				sl_obj.update_serial_record(self, 'entries', is_submit = 1, is_incoming = 0)
				sl_obj.update_serial_record(self, 'packing_details', is_submit = 1, is_incoming = 0)
				
				self.update_stock_ledger(update_stock=1)
		else:
			# Check for Approving Authority
			if not self.doc.recurring_id:
				get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, 
				 	self.doc.company, self.doc.grand_total, self)
				
		self.set_buying_amount()
		self.check_prev_docstatus()
		get_obj("Sales Common").update_prevdoc_detail(1,self)
		
		# this sequence because outstanding may get -ve
		self.make_gl_entries()

		if not cint(self.doc.is_pos) == 1:
			self.update_against_document_in_jv()

		self.update_c_form()
		self.update_time_log_batch(self.doc.name)
		self.convert_to_recurring()

	def before_cancel(self):
		self.update_time_log_batch(None)

	def on_cancel(self):
		if cint(self.doc.is_pos) == 1:
			if cint(self.doc.update_stock) == 1:
				sl = get_obj('Stock Ledger')
				sl.update_serial_record(self, 'entries', is_submit = 0, is_incoming = 0)
				sl.update_serial_record(self, 'packing_details', is_submit = 0, is_incoming = 0)
				
				self.update_stock_ledger(update_stock = -1)
		
		sales_com_obj = get_obj(dt = 'Sales Common')
		sales_com_obj.check_stop_sales_order(self)
		
		from accounts.utils import remove_against_link_from_jv
		remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_invoice")

		sales_com_obj.update_prevdoc_detail(0, self)
		
		self.make_cancel_gl_entries()
		
	def on_update_after_submit(self):
		self.validate_recurring_invoice()
		self.convert_to_recurring()
		
	def fetch_missing_values(self):
		# fetch contact and address details for customer, if they are not mentioned
		if not (self.doc.contact_person and self.doc.customer_address):
			for fieldname, val in self.get_default_address_and_contact("customer").items():
				if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
					self.doc.fields[fieldname] = val
					
		# fetch missing item values
		for item in self.doclist.get({"parentfield": "entries"}):
			if item.fields.get("item_code"):
				ret = get_obj('Sales Common').get_item_details(item.fields, self)
				for fieldname, value in ret.items():
					if self.meta.get_field(fieldname, parentfield="entries") and \
						not item.fields.get(fieldname):
							item.fields[fieldname] = value
		
		# fetch pos details, if they are not fetched
		if cint(self.doc.is_pos):
			self.set_pos_fields(for_validate=True)
			
	def update_time_log_batch(self, sales_invoice):
		for d in self.doclist.get({"doctype":"Sales Invoice Item"}):
			if d.time_log_batch:
				tlb = webnotes.bean("Time Log Batch", d.time_log_batch)
				tlb.doc.sales_invoice = sales_invoice
				tlb.update_after_submit()

	def validate_time_logs_are_submitted(self):
		for d in self.doclist.get({"doctype":"Sales Invoice Item"}):
			if d.time_log_batch:
				status = webnotes.conn.get_value("Time Log Batch", d.time_log_batch, "status")
				if status!="Submitted":
					webnotes.msgprint(_("Time Log Batch status must be 'Submitted'") + ":" + d.time_log_batch,
						raise_exception=True)

	def set_pos_fields(self, for_validate=False):
		"""Set retail related fields from pos settings"""
		if cint(self.doc.is_pos) != 1:
			return
			
		if self.pos_settings:
			pos = self.pos_settings[0]
			
			self.doc.conversion_rate = flt(pos.conversion_rate)
			
			if not self.doc.debit_to:
				self.doc.debit_to = self.doc.customer and webnotes.conn.get_value("Account", {
					"name": self.doc.customer + " - " + self.get_company_abbr(), 
					"docstatus": ["!=", 2]
				}) or pos.customer_account
				
			for fieldname in ('territory', 'naming_series', 'currency', 'charge', 'letter_head', 'tc_name',
				'price_list_name', 'company', 'select_print_heading', 'cash_bank_account'):
					if (not for_validate) or (for_validate and not self.doc.fields.get(fieldname)):
						self.doc.fields[fieldname] = pos.get(fieldname)

			# set pos values in items
			for item in self.doclist.get({"parentfield": "entries"}):
				if item.fields.get('item_code'):
					for fieldname, val in self.apply_pos_settings(item.fields).items():
						if (not for_validate) or (for_validate and not item.fields.get(fieldname)):
							item.fields[fieldname] = val

			# fetch terms	
			if self.doc.tc_name and not self.doc.terms:
				self.get_tc_details()
			
{'fraction_non_alphanumeric': 0.10951371405856632, 'fraction_numerical': 0.003975089439512389, 'mean_word_length': 4.58660251665433, 'pattern_counts': {'":': 16, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6605795', 'n_tokens_mistral': 5945, 'n_tokens_neox': 5114, 'n_words': 1122}