79 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			79 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import frappe
 | |
| 
 | |
| from erpnext.accounts.general_ledger import make_reverse_gl_entries
 | |
| 
 | |
| 
 | |
| def execute():
 | |
| 	frappe.reload_doc("accounts", "doctype", "overdue_payment")
 | |
| 	frappe.reload_doc("accounts", "doctype", "dunning")
 | |
| 
 | |
| 	# Migrate schema of all uncancelled dunnings
 | |
| 	filters = {"docstatus": ("!=", 2)}
 | |
| 
 | |
| 	can_edit_accounts_after = get_accounts_closing_date()
 | |
| 	if can_edit_accounts_after:
 | |
| 		# Get dunnings after the date when accounts were frozen/closed
 | |
| 		filters["posting_date"] = (">", can_edit_accounts_after)
 | |
| 
 | |
| 	all_dunnings = frappe.get_all("Dunning", filters=filters, pluck="name")
 | |
| 
 | |
| 	for dunning_name in all_dunnings:
 | |
| 		dunning = frappe.get_doc("Dunning", dunning_name)
 | |
| 		if not dunning.sales_invoice:
 | |
| 			# nothing we can do
 | |
| 			continue
 | |
| 
 | |
| 		if dunning.overdue_payments:
 | |
| 			# something's already here, doesn't need patching
 | |
| 			continue
 | |
| 
 | |
| 		payment_schedules = frappe.get_all(
 | |
| 			"Payment Schedule",
 | |
| 			filters={"parent": dunning.sales_invoice},
 | |
| 			fields=[
 | |
| 				"parent as sales_invoice",
 | |
| 				"name as payment_schedule",
 | |
| 				"payment_term",
 | |
| 				"due_date",
 | |
| 				"invoice_portion",
 | |
| 				"payment_amount",
 | |
| 				# at the time of creating this dunning, the full amount was outstanding
 | |
| 				"payment_amount as outstanding",
 | |
| 				"'0' as paid_amount",
 | |
| 				"discounted_amount",
 | |
| 			],
 | |
| 		)
 | |
| 
 | |
| 		dunning.extend("overdue_payments", payment_schedules)
 | |
| 		dunning.validate()
 | |
| 
 | |
| 		dunning.flags.ignore_validate_update_after_submit = True
 | |
| 		dunning.save()
 | |
| 
 | |
| 		# Reverse entries only if dunning is submitted and not resolved
 | |
| 		if dunning.docstatus == 1 and dunning.status != "Resolved":
 | |
| 			# With the new logic, dunning amount gets recorded as additional income
 | |
| 			# at time of payment. We don't want to record the dunning amount twice,
 | |
| 			# so we reverse previous GL Entries that recorded the dunning amount at
 | |
| 			# time of submission of the Dunning.
 | |
| 			make_reverse_gl_entries(voucher_type="Dunning", voucher_no=dunning.name)
 | |
| 
 | |
| 
 | |
| def get_accounts_closing_date():
 | |
| 	"""Get the date when accounts were frozen/closed"""
 | |
| 	accounts_frozen_till = frappe.db.get_single_value(
 | |
| 		"Accounts Settings", "acc_frozen_upto"
 | |
| 	)  # always returns datetime.date
 | |
| 
 | |
| 	period_closing_date = frappe.db.get_value(
 | |
| 		"Period Closing Voucher", {"docstatus": 1}, "posting_date", order_by="posting_date desc"
 | |
| 	)
 | |
| 
 | |
| 	# Set most recent frozen/closing date as filter
 | |
| 	if accounts_frozen_till and period_closing_date:
 | |
| 		can_edit_accounts_after = max(accounts_frozen_till, period_closing_date)
 | |
| 	else:
 | |
| 		can_edit_accounts_after = accounts_frozen_till or period_closing_date
 | |
| 
 | |
| 	return can_edit_accounts_after
 |