mirror of
				https://github.com/itsdave-de/msp.git
				synced 2025-10-30 08:57:09 -03:00 
			
		
		
		
	Auto Invoice Generator Anpassung
This commit is contained in:
		
							parent
							
								
									9141df2e63
								
							
						
					
					
						commit
						f0fe2582dd
					
				| @ -7,7 +7,6 @@ | |||||||
|  "editable_grid": 1, |  "editable_grid": 1, | ||||||
|  "engine": "InnoDB", |  "engine": "InnoDB", | ||||||
|  "field_order": [ |  "field_order": [ | ||||||
|   "invoicing_grouped_by", |  | ||||||
|   "close_invoiced_delivery_notes_section", |   "close_invoiced_delivery_notes_section", | ||||||
|   "close", |   "close", | ||||||
|   "invoices_from_delivery_notes_section", |   "invoices_from_delivery_notes_section", | ||||||
| @ -16,15 +15,10 @@ | |||||||
|   "statistics", |   "statistics", | ||||||
|   "date", |   "date", | ||||||
|   "invoice_count", |   "invoice_count", | ||||||
|   "customer_count" |   "customer_count", | ||||||
|  |   "log" | ||||||
|  ], |  ], | ||||||
|  "fields": [ |  "fields": [ | ||||||
|   { |  | ||||||
|    "fieldname": "invoicing_grouped_by", |  | ||||||
|    "fieldtype": "Select", |  | ||||||
|    "label": "Invoicing grouped by", |  | ||||||
|    "options": "\nService and Goods\nService and Goods and Sales Order" |  | ||||||
|   }, |  | ||||||
|   { |   { | ||||||
|    "fieldname": "close_invoiced_delivery_notes_section", |    "fieldname": "close_invoiced_delivery_notes_section", | ||||||
|    "fieldtype": "Section Break", |    "fieldtype": "Section Break", | ||||||
| @ -75,11 +69,17 @@ | |||||||
|    "fieldname": "statistics", |    "fieldname": "statistics", | ||||||
|    "fieldtype": "Section Break", |    "fieldtype": "Section Break", | ||||||
|    "label": "Statistics" |    "label": "Statistics" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |    "fieldname": "log", | ||||||
|  |    "fieldtype": "Small Text", | ||||||
|  |    "label": "Log" | ||||||
|   } |   } | ||||||
|  ], |  ], | ||||||
|  "index_web_pages_for_search": 1, |  "index_web_pages_for_search": 1, | ||||||
|  "links": [], |  "links": [], | ||||||
|  "modified": "2022-09-02 11:56:18.512522", |  "migration_hash": "81a435d8fdde574c14c22be58f9e32ca", | ||||||
|  |  "modified": "2022-09-22 14:23:33.413375", | ||||||
|  "modified_by": "Administrator", |  "modified_by": "Administrator", | ||||||
|  "module": "MSP", |  "module": "MSP", | ||||||
|  "name": "Auto Invoice Generator", |  "name": "Auto Invoice Generator", | ||||||
|  | |||||||
| @ -8,6 +8,7 @@ import frappe | |||||||
| from frappe.model.document import Document | from frappe.model.document import Document | ||||||
| from erpnext.accounts.party import set_taxes as party_st | from erpnext.accounts.party import set_taxes as party_st | ||||||
| from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice | from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice | ||||||
|  | from msp.billing_tools import get_item_group_assignment_table | ||||||
| from datetime import datetime | from datetime import datetime | ||||||
| from frappe import ValidationError, _ | from frappe import ValidationError, _ | ||||||
| 
 | 
 | ||||||
| @ -33,6 +34,7 @@ class AutoInvoiceGenerator(Document): | |||||||
| 			frappe.db.set_value("Delivery Note", pos, "status", "Closed") | 			frappe.db.set_value("Delivery Note", pos, "status", "Closed") | ||||||
| 		frappe.msgprint( str(count)+ " delivery notes were closed") | 		frappe.msgprint( str(count)+ " delivery notes were closed") | ||||||
| 
 | 
 | ||||||
|  | 	 | ||||||
| 	@frappe.whitelist() | 	@frappe.whitelist() | ||||||
| 	def get_delivery_notes_for_invoicing(self):  | 	def get_delivery_notes_for_invoicing(self):  | ||||||
| 
 | 
 | ||||||
| @ -41,10 +43,9 @@ class AutoInvoiceGenerator(Document): | |||||||
| 		#filters = {"status" : "to bill","is_return": 0, "project": ""} | 		#filters = {"status" : "to bill","is_return": 0, "project": ""} | ||||||
| 		delivery_notes_list = frappe.get_all("Delivery Note", filters = filters, fields = ["name", "customer", "project"])  | 		delivery_notes_list = frappe.get_all("Delivery Note", filters = filters, fields = ["name", "customer", "project"])  | ||||||
| 		print(len(delivery_notes_list)) | 		print(len(delivery_notes_list)) | ||||||
| 		dl = [x.name for x in delivery_notes_list if x.project] | 		#dl = [x.name for x in delivery_notes_list if x.project] | ||||||
| 		print(dl)		 | 		#print(dl)		 | ||||||
| 		print(len(dl)) | 		#print(len(dl)) | ||||||
| 	 |  | ||||||
| 		return delivery_notes_list  | 		return delivery_notes_list  | ||||||
| 	@frappe.whitelist() | 	@frappe.whitelist() | ||||||
| 	def get_customer_for_invoicing(self, delivery_note):  | 	def get_customer_for_invoicing(self, delivery_note):  | ||||||
| @ -60,9 +61,22 @@ class AutoInvoiceGenerator(Document): | |||||||
| 
 | 
 | ||||||
| 		return customer_list_exc_duplicate  | 		return customer_list_exc_duplicate  | ||||||
| 
 | 
 | ||||||
| 	def get_delivery_notes_for_customer(self, cust, delivery_notes):  | 	def get_customer_asap_billing_mode(self): | ||||||
|  | 		del_not = self.get_delivery_notes_for_invoicing() | ||||||
|  | 		cust_list = self.get_customer_for_invoicing(del_not) | ||||||
|  | 		filters = {"name": ["in",cust_list], | ||||||
|  | 					"billing_mode": "ASAP"} | ||||||
|  | 		cust_list_asap = frappe.get_all("Customer", filters = filters ) | ||||||
|  | 		asap_cust = [x.name for x in cust_list_asap] | ||||||
|  | 		print(asap_cust) | ||||||
|  | 		return asap_cust | ||||||
| 
 | 
 | ||||||
| #Funktion listet alle Lieferscheine für den jeweiligen Kunden auf  | 	def get_asap_invoices(self, cust_list): | ||||||
|  | 		pass | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	def get_delivery_notes_for_customer(self, cust, delivery_notes):  | ||||||
|  | 	#Funktion listet alle Lieferscheine für den jeweiligen Kunden auf  | ||||||
| 		cust_del_note = []  | 		cust_del_note = []  | ||||||
| 
 | 
 | ||||||
| 		for el in delivery_notes:  | 		for el in delivery_notes:  | ||||||
| @ -71,12 +85,34 @@ class AutoInvoiceGenerator(Document): | |||||||
| 				cust_del_note.append(el)  | 				cust_del_note.append(el)  | ||||||
| 
 | 
 | ||||||
| 		return cust_del_note  | 		return cust_del_note  | ||||||
| 	@frappe.whitelist() |  | ||||||
| 	def get_invoice_dict(self):  |  | ||||||
| 
 | 
 | ||||||
|  | 	def get_invoicing_items_for_cust(self,cust): | ||||||
|  | 		#Funktion liefert eine Liste aller abrechenbaren Items für den jeweiligen Kunden | ||||||
| 		 | 		 | ||||||
| 		del_not = self.get_delivery_notes_for_invoicing() | 		del_not = self.get_delivery_notes_for_invoicing() | ||||||
| 		print(del_not)  | 		cust_doc = frappe.get_doc("Customer",cust)	 | ||||||
|  | 		delivery_note_list = self.get_delivery_notes_for_customer(cust,del_not)  | ||||||
|  | 		#print(delivery_note_list) | ||||||
|  | 		if len(delivery_note_list) < 1: | ||||||
|  | 			frappe.msgprint("Keine abrechnenbaren Lieferscheine vorhanden") | ||||||
|  | 		else: | ||||||
|  | 			items = [] | ||||||
|  | 			 | ||||||
|  | 			for dn in delivery_note_list:  | ||||||
|  | 
 | ||||||
|  | 				item_doc = frappe.get_doc("Delivery Note", dn["name"])  | ||||||
|  | 				for item in item_doc.items:  | ||||||
|  | 					print(item.item_group) | ||||||
|  | 					item.dn_detail= dn["name"] | ||||||
|  | 					print("item.dn_detail") | ||||||
|  | 					print(item.dn_detail) | ||||||
|  | 					items.append(item) | ||||||
|  | 		return items | ||||||
|  | 	 | ||||||
|  | 	@frappe.whitelist() | ||||||
|  | 	def get_invoice_dict(self):  | ||||||
|  | 		self.get_customer_asap_billing_mode() | ||||||
|  | 		del_not = self.get_delivery_notes_for_invoicing() | ||||||
| 		cust_list = self.get_customer_for_invoicing(del_not) | 		cust_list = self.get_customer_for_invoicing(del_not) | ||||||
| 		if self.customer:  | 		if self.customer:  | ||||||
| 			customer_list = [self.customer] | 			customer_list = [self.customer] | ||||||
| @ -87,91 +123,105 @@ class AutoInvoiceGenerator(Document): | |||||||
| 		cust_count = 0 | 		cust_count = 0 | ||||||
| 		invoice_count = 0 | 		invoice_count = 0 | ||||||
| 		for cust in customer_list: | 		for cust in customer_list: | ||||||
| 			print(cust) |  | ||||||
| 			cust_doc = frappe.get_doc("Customer",cust) | 			cust_doc = frappe.get_doc("Customer",cust) | ||||||
| 			invoice_in_draft = frappe.get_all("Sales Invoice", filters = {"status" : "Draft", "customer": cust}) | 			invoice_in_draft = frappe.get_all("Sales Invoice", filters = {"status" : "Draft", "customer": cust}) | ||||||
| 			if len(invoice_in_draft) > 0: | 			if len(invoice_in_draft) > 0: | ||||||
| 				print("nicht bearbeitet") | 				self.log = "Für Kunde"+ " "+ cust + " wurden keine Rechnungen erstellt, da noch nicht berechnete Rechnungen in Draft vorhanden"  | ||||||
| 				print(cust) |  | ||||||
| 				continue | 				continue | ||||||
| 			else: | 			else: | ||||||
| 				cust_count += 1 | 				cust_count += 1 | ||||||
| 				#if self.invoicing_grouped_by == "None": | 				items = self.get_invoicing_items_for_cust(cust) | ||||||
|  | 				print(items) | ||||||
|  | 				invoicing_items = [] | ||||||
| 
 | 
 | ||||||
| 				delivery_note_list = self.get_delivery_notes_for_customer(cust,del_not)  | 				if cust_doc.billing_mode == "ASAP": | ||||||
| 				#print(delivery_note_list) | 					x = self.get_delivery_notes_for_customer(cust, del_not) | ||||||
| 				if len(delivery_note_list) < 1: | 					for dn in x: | ||||||
| 					frappe.msgprint("Keine abrechnenbaren Lieferscheine vorhanden") | 						item_doc = frappe.get_doc("Delivery Note", dn["name"])  | ||||||
| 				sales_order_items = [] | 						items = [self.create_invoice_doc_item(item) for item in item_doc.items] | ||||||
| 				service_items = [] | 						if len(items) > 0: | ||||||
| 				goods_items =[] | 							self.create_invoice(cust, items, "Abrechnung Lieferschein " + dn["name"]+ " " + cust_doc.customer_name) | ||||||
| 				for dn in delivery_note_list:  | 							invoice_count += 1 | ||||||
| 
 | 				elif cust_doc.billing_mode == "Collective Bill": | ||||||
| 					item_doc = frappe.get_doc("Delivery Note", dn["name"])  | 					for item in items: | ||||||
| 
 | 						invoice_doc_item = self.create_invoice_doc_item(item) | ||||||
| 					for item in item_doc.items:  | 						invoicing_items.append(invoice_doc_item) | ||||||
| 						print(item.item_group) | 					if len(invoicing_items) > 0: | ||||||
| 						invoice_doc_item = frappe.get_doc({ | 						self.create_invoice(cust, invoicing_items, "Sammelrechnung " + cust_doc.customer_name) | ||||||
| 							"doctype": "Sales Invoice Item", |  | ||||||
| 							"item_code": item.item_code, |  | ||||||
| 							"description": item.description, |  | ||||||
| 							"qty": item.qty, |  | ||||||
| 							"uom" : item.uom, |  | ||||||
| 							"rate": item.rate, |  | ||||||
| 							"sales_order": item.against_sales_order, |  | ||||||
| 							"dn_detail": item.name, |  | ||||||
| 							"parent": "delivery_note", |  | ||||||
| 							"delivery_note": dn["name"] |  | ||||||
| 
 |  | ||||||
| 							}) |  | ||||||
| 						print(item.dn_detail) |  | ||||||
| 						print(dn["name"]) |  | ||||||
| 						print(item.qty) |  | ||||||
| 						print(item.uom) |  | ||||||
| 						if item.item_group == "Dienstleistungen" or item.item_group == "Anfahrten" or item.item_group == "Arbeitszeiten Techniker" or item.item_group == "Zuschläge" or item.item_group == "Anwendungsentwicklung": |  | ||||||
| 							service_items.append(invoice_doc_item) |  | ||||||
| 						elif item.against_sales_order: |  | ||||||
| 							sales_order_items.append(invoice_doc_item) |  | ||||||
| 						else: |  | ||||||
| 							goods_items.append(invoice_doc_item) |  | ||||||
| 				 |  | ||||||
| 			if self.invoicing_grouped_by == "Service and Goods and Sales Order": |  | ||||||
| 				self.create_invoice(cust, goods_items, "Ware " + cust_doc.customer_name) |  | ||||||
| 				if len(goods_items) > 0: |  | ||||||
| 					invoice_count += 1 |  | ||||||
| 				self.create_invoice(cust, service_items, "Dienstleistung " + cust_doc.customer_name) |  | ||||||
| 				if len(service_items) > 0:	 |  | ||||||
| 					invoice_count += 1 |  | ||||||
| 				#self.create_invoice(cust, sales_order_items, "Sales Order " + cust_doc.customer_name)	 |  | ||||||
| 				if len(sales_order_items) > 0: |  | ||||||
| 					print("Sales Order Check") |  | ||||||
| 					x = [i.sales_order for i in sales_order_items] |  | ||||||
| 					print(x) |  | ||||||
| 					a = list(set(x)) |  | ||||||
| 					for el in a: |  | ||||||
| 						sal_ord_it = [] |  | ||||||
| 						for i in sales_order_items: |  | ||||||
| 							if i.sales_order == el: |  | ||||||
| 								sal_ord_it.append(i) |  | ||||||
| 						self.create_invoice(cust, sal_ord_it, "Sales Order "+ el+ " " + cust_doc.customer_name) |  | ||||||
| 						invoice_count += 1 | 						invoice_count += 1 | ||||||
| 			elif self.invoicing_grouped_by == "Service and Goods": | 				else:	 | ||||||
| 				invoice_item = sales_order_items + goods_items | 					item_group_separation_dict = get_item_group_assignment_table(cust) | ||||||
| 				self.create_invoice(cust, invoice_item, "Ware " + cust_doc.customer_name) | 					print(item_group_separation_dict) | ||||||
| 				if len(invoice_item) > 0: | 					separation_item_groups = [[item_group_separation_dict[x].item_group,item_group_separation_dict[x].filter]  for x in range(1, len(item_group_separation_dict) + 1) ]	 | ||||||
| 					invoice_count += 1 | 					if cust_doc.billing_mode == "per Item Group": | ||||||
| 				self.create_invoice(cust, service_items, "Dienstleistung " + cust_doc.customer_name) | 						for el in separation_item_groups: | ||||||
| 				if len(service_items) >0: | 							print(el[1]) | ||||||
| 					invoice_count += 1 | 							a = [] | ||||||
| 			else:  | 							for item in items: | ||||||
| 				invoice_item = sales_order_items + service_items + goods_items | 								if item.item_group in el[1]: | ||||||
| 				self.create_invoice(cust, invoice_item, "Dienstleistung und Ware  "+ cust_doc.customer_name) | 									invoice_doc_item = self.create_invoice_doc_item(item) | ||||||
| 				if len(invoice_item) > 0: | 									a.append(invoice_doc_item) | ||||||
| 					invoice_count += 1 | 									items.remove(item) | ||||||
|  | 							if len(a) > 0: | ||||||
|  | 								self.create_invoice(cust, a, el[0] + " " +cust_doc.customer_name) | ||||||
|  | 								invoice_count +=1 | ||||||
|  | 							 | ||||||
|  | 						i_items = [self.create_invoice_doc_item(item) for item in items] | ||||||
|  | 						if len(i_items) > 0: | ||||||
|  | 							self.create_invoice(cust, i_items, "Abrechnung " + cust_doc.customer_name)	 | ||||||
|  | 							invoice_count += 1 | ||||||
|  | 					if cust_doc.billing_mode == "per Sales Order, remaining per Item Group": | ||||||
|  | 						sales_order_items = [] | ||||||
|  | 						for item in items: | ||||||
|  | 							if item.against_sales_order: | ||||||
|  | 								invoice_doc_item = self.create_invoice_doc_item(item) | ||||||
|  | 								sales_order_items.append(invoice_doc_item) | ||||||
|  | 								items.remove(item) | ||||||
|  | 						if len(sales_order_items) > 0: | ||||||
|  | 							x = [i.sales_order for i in sales_order_items] | ||||||
|  | 							a = list(set(x)) | ||||||
|  | 							for el in a: | ||||||
|  | 								sal_ord_it = [] | ||||||
|  | 								for i in sales_order_items: | ||||||
|  | 									if i.sales_order == el: | ||||||
|  | 										sal_ord_it.append(i) | ||||||
|  | 								self.create_invoice(cust, sal_ord_it, "Sales Order "+ el+ " " + cust_doc.customer_name) | ||||||
|  | 								invoice_count += 1 | ||||||
|  | 						for el in separation_item_groups: | ||||||
|  | 							print(el[1]) | ||||||
|  | 							a = [] | ||||||
|  | 							for item in items: | ||||||
|  | 								if item.item_group in el[1]: | ||||||
|  | 									invoice_doc_item = self.create_invoice_doc_item(item) | ||||||
|  | 									a.append(invoice_doc_item) | ||||||
|  | 									items.remove(item) | ||||||
|  | 							self.create_invoice(cust, a, el[0] + " " +cust_doc.customer_name) | ||||||
|  | 			 | ||||||
|  | 						i_items = [self.create_invoice_doc_item(item) for item in items] | ||||||
|  | 						self.create_invoice(cust, i_items, "Abrechnung " + cust_doc.customer_name)	 | ||||||
| 		frappe.msgprint("Für " + str(cust_count)+ " Kunden wurden " + str(invoice_count) + " Rechnungen erstellt.") | 		frappe.msgprint("Für " + str(cust_count)+ " Kunden wurden " + str(invoice_count) + " Rechnungen erstellt.") | ||||||
| 		self.date = datetime.today().strftime('%Y-%m-%d') | 		self.date = datetime.today().strftime('%Y-%m-%d') | ||||||
| 		self.invoice_count = invoice_count | 		self.invoice_count = invoice_count | ||||||
| 		self.customer_count = cust_count				 | 		self.customer_count = cust_count				 | ||||||
|  | 		 | ||||||
|  | 
 | ||||||
|  | 	def create_invoice_doc_item(self, item): | ||||||
|  | 		#Funktion kreiert Invoice Item aus den gegebenen Delivery Note Items | ||||||
|  | 		invoice_doc_item = frappe.get_doc({ | ||||||
|  | 						"doctype": "Sales Invoice Item", | ||||||
|  | 						"item_code": item.item_code, | ||||||
|  | 						"description": item.description, | ||||||
|  | 						"qty": item.qty, | ||||||
|  | 						"uom" : item.uom, | ||||||
|  | 						"rate": item.rate, | ||||||
|  | 						"sales_order": item.against_sales_order, | ||||||
|  | 						"dn_detail": item.name, | ||||||
|  | 						"parent": "delivery_note", | ||||||
|  | 						"delivery_note": item.dn_detail | ||||||
|  | 						}) | ||||||
|  | 		return invoice_doc_item | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 	def create_invoice(self,cust,invoice_doc_items,title): | 	def create_invoice(self,cust,invoice_doc_items,title): | ||||||
| 		invoice_doc = frappe.get_doc({  | 		invoice_doc = frappe.get_doc({  | ||||||
| 				"doctype": "Sales Invoice",  | 				"doctype": "Sales Invoice",  | ||||||
| @ -181,6 +231,7 @@ class AutoInvoiceGenerator(Document): | |||||||
| 				"items": invoice_doc_items | 				"items": invoice_doc_items | ||||||
| 				})  | 				})  | ||||||
| 		if len(invoice_doc_items)>0: | 		if len(invoice_doc_items)>0: | ||||||
|  | 			self.validate_items(invoice_doc_items) | ||||||
| 			settings_doc = frappe.get_single("Auto Invoice Generator Settings") | 			settings_doc = frappe.get_single("Auto Invoice Generator Settings") | ||||||
| 			customer_doc = frappe.get_doc("Customer", cust ) | 			customer_doc = frappe.get_doc("Customer", cust ) | ||||||
|          |          | ||||||
| @ -206,4 +257,12 @@ class AutoInvoiceGenerator(Document): | |||||||
| 			invoice_doc.append("taxes", new_tax) | 			invoice_doc.append("taxes", new_tax) | ||||||
| 			invoice_doc.save() | 			invoice_doc.save() | ||||||
| 
 | 
 | ||||||
| 	 | 	def validate_items(self,item_list): | ||||||
|  | 		print("len(item_list):") | ||||||
|  | 		print(len(item_list)) | ||||||
|  | 		print("len(set(item_list)):") | ||||||
|  | 		print(len(set(item_list))) | ||||||
|  | 		if len(item_list) == len(set(item_list)): | ||||||
|  | 			return True | ||||||
|  | 		else: | ||||||
|  | 			frappe.msgprint("Rechnungspositionen doppelt") | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user