Merge branch 'develop' into escape-company-field
This commit is contained in:
		
						commit
						f7a7cc08d9
					
				| @ -93,6 +93,7 @@ def resolve_dunning(doc, state): | ||||
| 
 | ||||
| def calculate_interest_and_amount(posting_date, outstanding_amount, rate_of_interest, dunning_fee, overdue_days): | ||||
| 	interest_amount = 0 | ||||
| 	grand_total = 0 | ||||
| 	if rate_of_interest: | ||||
| 		interest_per_year = flt(outstanding_amount) * flt(rate_of_interest) / 100 | ||||
| 		interest_amount = (interest_per_year * cint(overdue_days)) / 365  | ||||
|  | ||||
| @ -31,8 +31,7 @@ frappe.ui.form.on('POS Profile', { | ||||
| 		frm.set_query("print_format", function() { | ||||
| 			return { | ||||
| 				filters: [ | ||||
| 					['Print Format', 'doc_type', '=', 'Sales Invoice'], | ||||
| 					['Print Format', 'print_format_type', '=', 'Jinja'], | ||||
| 					['Print Format', 'doc_type', '=', 'POS Invoice'] | ||||
| 				] | ||||
| 			}; | ||||
| 		}); | ||||
| @ -45,10 +44,6 @@ frappe.ui.form.on('POS Profile', { | ||||
| 			}; | ||||
| 		}); | ||||
| 
 | ||||
| 		frm.set_query("print_format", function() { | ||||
| 			return { filters: { doc_type: "Sales Invoice", print_format_type: "JS"} }; | ||||
| 		}); | ||||
| 
 | ||||
| 		frm.set_query('company_address', function(doc) { | ||||
| 			if(!doc.company) { | ||||
| 				frappe.throw(__('Please set Company')); | ||||
|  | ||||
| @ -8,7 +8,7 @@ def get_data(): | ||||
| 		'fieldname': 'taxes_and_charges', | ||||
| 		'non_standard_fieldnames': { | ||||
| 			'Tax Rule': 'sales_tax_template', | ||||
| 			'Subscription': 'tax_template', | ||||
| 			'Subscription': 'sales_tax_template', | ||||
| 			'Restaurant': 'default_tax_template' | ||||
| 		}, | ||||
| 		'transactions': [ | ||||
|  | ||||
| @ -8,6 +8,7 @@ from frappe import _ | ||||
| from frappe.utils import flt, getdate, cint, date_diff, formatdate | ||||
| from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts | ||||
| from frappe.model.document import Document | ||||
| from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_checks_for_pl_and_bs_accounts | ||||
| 
 | ||||
| class AssetValueAdjustment(Document): | ||||
| 	def validate(self): | ||||
| @ -53,17 +54,33 @@ class AssetValueAdjustment(Document): | ||||
| 		je.company = self.company | ||||
| 		je.remark = "Depreciation Entry against {0} worth {1}".format(self.asset, self.difference_amount) | ||||
| 
 | ||||
| 		je.append("accounts", { | ||||
| 		credit_entry = { | ||||
| 			"account": accumulated_depreciation_account, | ||||
| 			"credit_in_account_currency": self.difference_amount, | ||||
| 			"cost_center": depreciation_cost_center or self.cost_center | ||||
| 		}) | ||||
| 		} | ||||
| 
 | ||||
| 		je.append("accounts", { | ||||
| 		debit_entry = { | ||||
| 			"account": depreciation_expense_account, | ||||
| 			"debit_in_account_currency": self.difference_amount, | ||||
| 			"cost_center": depreciation_cost_center or self.cost_center | ||||
| 		}) | ||||
| 		} | ||||
| 
 | ||||
| 		accounting_dimensions = get_checks_for_pl_and_bs_accounts() | ||||
| 
 | ||||
| 		for dimension in accounting_dimensions: | ||||
| 			if dimension.get('mandatory_for_bs'): | ||||
| 				credit_entry.update({ | ||||
| 					dimension['fieldname']: self.get(dimension['fieldname']) or dimension.get('default_dimension') | ||||
| 				}) | ||||
| 
 | ||||
| 			if dimension.get('mandatory_for_pl'): | ||||
| 				debit_entry.update({ | ||||
| 					dimension['fieldname']: self.get(dimension['fieldname']) or dimension.get('default_dimension') | ||||
| 				}) | ||||
| 		 | ||||
| 		je.append("accounts", credit_entry) | ||||
| 		je.append("accounts", debit_entry) | ||||
| 
 | ||||
| 		je.flags.ignore_permissions = True | ||||
| 		je.submit() | ||||
|  | ||||
| @ -613,9 +613,12 @@ def get_tax_template(doctype, txt, searchfield, start, page_len, filters): | ||||
| 	if not taxes: | ||||
| 		return frappe.db.sql(""" SELECT name FROM `tabItem Tax Template` """) | ||||
| 	else: | ||||
| 		valid_from = filters.get('valid_from') | ||||
| 		valid_from = valid_from[1] if isinstance(valid_from, list) else valid_from | ||||
| 
 | ||||
| 		args = { | ||||
| 			'item_code': filters.get('item_code'), | ||||
| 			'posting_date': filters.get('valid_from'), | ||||
| 			'posting_date': valid_from, | ||||
| 			'tax_category': filters.get('tax_category'), | ||||
| 			'company': filters.get('company') | ||||
| 		} | ||||
|  | ||||
| @ -330,7 +330,7 @@ def make_opportunity_from_communication(communication, ignore_communication_link | ||||
| 	opportunity = frappe.get_doc({ | ||||
| 		"doctype": "Opportunity", | ||||
| 		"opportunity_from": opportunity_from, | ||||
| 		"lead": lead | ||||
| 		"party_name": lead | ||||
| 	}).insert(ignore_permissions=True) | ||||
| 
 | ||||
| 	link_communication_to_document(doc, "Opportunity", opportunity.name, ignore_communication_links) | ||||
|  | ||||
| @ -7,7 +7,7 @@ import frappe | ||||
| import unittest | ||||
| from frappe.utils import nowdate | ||||
| from frappe.utils.make_random import get_random | ||||
| 
 | ||||
| from erpnext.education.doctype.program.test_program import make_program_and_linked_courses | ||||
| 
 | ||||
| # test_records = frappe.get_test_records('Fees') | ||||
| 
 | ||||
| @ -15,6 +15,7 @@ class TestFees(unittest.TestCase): | ||||
| 
 | ||||
| 	def test_fees(self): | ||||
| 		student = get_random("Student") | ||||
| 		program = make_program_and_linked_courses("_Test Program 1", ["_Test Course 1", "_Test Course 2"]) | ||||
| 		fee = frappe.new_doc("Fees") | ||||
| 		fee.posting_date = nowdate() | ||||
| 		fee.due_date = nowdate() | ||||
| @ -23,6 +24,7 @@ class TestFees(unittest.TestCase): | ||||
| 		fee.income_account = "Sales - _TC" | ||||
| 		fee.cost_center = "_Test Cost Center - _TC" | ||||
| 		fee.company = "_Test Company" | ||||
| 		fee.program = program.name | ||||
| 
 | ||||
| 		fee.extend("components", [ | ||||
| 			{ | ||||
|  | ||||
| @ -134,7 +134,7 @@ let transfer_patient_dialog = function(frm) { | ||||
| 			{fieldtype: 'Link', label: 'Leave From', fieldname: 'leave_from', options: 'Healthcare Service Unit', reqd: 1, read_only:1}, | ||||
| 			{fieldtype: 'Link', label: 'Service Unit Type', fieldname: 'service_unit_type', options: 'Healthcare Service Unit Type'}, | ||||
| 			{fieldtype: 'Link', label: 'Transfer To', fieldname: 'service_unit', options: 'Healthcare Service Unit', reqd: 1}, | ||||
| 			{fieldtype: 'Datetime', label: 'Check In', fieldname: 'check_in', reqd: 1} | ||||
| 			{fieldtype: 'Datetime', label: 'Check In', fieldname: 'check_in', reqd: 1, default: frappe.datetime.now_datetime()} | ||||
| 		], | ||||
| 		primary_action_label: __('Transfer'), | ||||
| 		primary_action : function() { | ||||
| @ -147,7 +147,12 @@ let transfer_patient_dialog = function(frm) { | ||||
| 			if(dialog.get_value('service_unit')){ | ||||
| 				service_unit = dialog.get_value('service_unit'); | ||||
| 			} | ||||
| 			if(!check_in){ | ||||
| 			if(check_in > frappe.datetime.now_datetime()){ | ||||
| 				frappe.msgprint({ | ||||
| 					title: __('Not Allowed'), | ||||
| 					message: __('Check-in time cannot be greater than the current time'), | ||||
| 					indicator: 'red' | ||||
| 				}); | ||||
| 				return; | ||||
| 			} | ||||
| 			frappe.call({ | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
|   { | ||||
|    "hidden": 0, | ||||
|    "label": "Loan", | ||||
|    "links": "[\n    {\n        \"description\": \"Loan Type for interest and penalty rates\",\n        \"label\": \"Loan Type\",\n        \"name\": \"Loan Type\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Loan Applications from customers and employees.\",\n        \"label\": \"Loan Application\",\n        \"name\": \"Loan Application\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Loans provided to customers and employees.\",\n        \"label\": \"Loan\",\n        \"name\": \"Loan\",\n        \"type\": \"doctype\"\n    }\n]" | ||||
|    "links": "[\n    {\n        \"description\": \"Loan Type for interest and penalty rates\",\n        \"label\": \"Loan Type\",\n        \"name\": \"Loan Type\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Loan Applications from customers and employees.\",\n        \"label\": \"Loan Application\",\n        \"name\": \"Loan Application\",\n        \"type\": \"doctype\"\n    },\n    {   \"dependencies\": [\n            \"Loan Type\"\n        ],\n        \"description\": \"Loans provided to customers and employees.\",\n        \"label\": \"Loan\",\n        \"name\": \"Loan\",\n        \"type\": \"doctype\"\n    }\n]" | ||||
|   }, | ||||
|   { | ||||
|    "hidden": 0, | ||||
|  | ||||
| @ -112,16 +112,19 @@ frappe.ui.form.on('Loan Application', { | ||||
| frappe.ui.form.on("Proposed Pledge", { | ||||
| 	loan_security: function(frm, cdt, cdn) { | ||||
| 		let row = locals[cdt][cdn]; | ||||
| 		frappe.call({ | ||||
| 			method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price", | ||||
| 			args: { | ||||
| 				loan_security: row.loan_security | ||||
| 			}, | ||||
| 			callback: function(r) { | ||||
| 				frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message); | ||||
| 				frm.events.calculate_amounts(frm, cdt, cdn); | ||||
| 			} | ||||
| 		}) | ||||
| 
 | ||||
| 		if (row.loan_security) { | ||||
| 			frappe.call({ | ||||
| 				method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price", | ||||
| 				args: { | ||||
| 					loan_security: row.loan_security | ||||
| 				}, | ||||
| 				callback: function(r) { | ||||
| 					frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message); | ||||
| 					frm.events.calculate_amounts(frm, cdt, cdn); | ||||
| 				} | ||||
| 			}) | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	amount: function(frm, cdt, cdn) { | ||||
|  | ||||
| @ -19,8 +19,8 @@ class LoanInterestAccrual(AccountsController): | ||||
| 		if not self.posting_date: | ||||
| 			self.posting_date = nowdate() | ||||
| 
 | ||||
| 		if not self.interest_amount: | ||||
| 			frappe.throw(_("Interest Amount is mandatory")) | ||||
| 		if not self.interest_amount and not self.payable_principal_amount: | ||||
| 			frappe.throw(_("Interest Amount or Principal Amount is mandatory")) | ||||
| 
 | ||||
| 
 | ||||
| 	def on_submit(self): | ||||
| @ -39,37 +39,38 @@ class LoanInterestAccrual(AccountsController): | ||||
| 	def make_gl_entries(self, cancel=0, adv_adj=0): | ||||
| 		gle_map = [] | ||||
| 
 | ||||
| 		gle_map.append( | ||||
| 			self.get_gl_dict({ | ||||
| 				"account": self.loan_account, | ||||
| 				"party_type": self.applicant_type, | ||||
| 				"party": self.applicant, | ||||
| 				"against": self.interest_income_account, | ||||
| 				"debit": self.interest_amount, | ||||
| 				"debit_in_account_currency": self.interest_amount, | ||||
| 				"against_voucher_type": "Loan", | ||||
| 				"against_voucher": self.loan, | ||||
| 				"remarks": _("Against Loan:") + self.loan, | ||||
| 				"cost_center": erpnext.get_default_cost_center(self.company), | ||||
| 				"posting_date": self.posting_date | ||||
| 			}) | ||||
| 		) | ||||
| 		if self.interest_amount: | ||||
| 			gle_map.append( | ||||
| 				self.get_gl_dict({ | ||||
| 					"account": self.loan_account, | ||||
| 					"party_type": self.applicant_type, | ||||
| 					"party": self.applicant, | ||||
| 					"against": self.interest_income_account, | ||||
| 					"debit": self.interest_amount, | ||||
| 					"debit_in_account_currency": self.interest_amount, | ||||
| 					"against_voucher_type": "Loan", | ||||
| 					"against_voucher": self.loan, | ||||
| 					"remarks": _("Against Loan:") + self.loan, | ||||
| 					"cost_center": erpnext.get_default_cost_center(self.company), | ||||
| 					"posting_date": self.posting_date | ||||
| 				}) | ||||
| 			) | ||||
| 
 | ||||
| 		gle_map.append( | ||||
| 			self.get_gl_dict({ | ||||
| 				"account": self.interest_income_account, | ||||
| 				"party_type": self.applicant_type, | ||||
| 				"party": self.applicant, | ||||
| 				"against": self.loan_account, | ||||
| 				"credit": self.interest_amount, | ||||
| 				"credit_in_account_currency":  self.interest_amount, | ||||
| 				"against_voucher_type": "Loan", | ||||
| 				"against_voucher": self.loan, | ||||
| 				"remarks": _("Against Loan:") + self.loan, | ||||
| 				"cost_center": erpnext.get_default_cost_center(self.company), | ||||
| 				"posting_date": self.posting_date | ||||
| 			}) | ||||
| 		) | ||||
| 			gle_map.append( | ||||
| 				self.get_gl_dict({ | ||||
| 					"account": self.interest_income_account, | ||||
| 					"party_type": self.applicant_type, | ||||
| 					"party": self.applicant, | ||||
| 					"against": self.loan_account, | ||||
| 					"credit": self.interest_amount, | ||||
| 					"credit_in_account_currency":  self.interest_amount, | ||||
| 					"against_voucher_type": "Loan", | ||||
| 					"against_voucher": self.loan, | ||||
| 					"remarks": _("Against Loan:") + self.loan, | ||||
| 					"cost_center": erpnext.get_default_cost_center(self.company), | ||||
| 					"posting_date": self.posting_date | ||||
| 				}) | ||||
| 			) | ||||
| 
 | ||||
| 		if gle_map: | ||||
| 			make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj) | ||||
|  | ||||
| @ -173,7 +173,7 @@ | ||||
|   { | ||||
|    "fieldname": "references_section", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "References" | ||||
|    "label": "Payment References" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "reference_number", | ||||
| @ -221,7 +221,7 @@ | ||||
|  ], | ||||
|  "is_submittable": 1, | ||||
|  "links": [], | ||||
|  "modified": "2020-04-16 18:14:45.166754", | ||||
|  "modified": "2020-05-16 09:40:15.581165", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Loan Management", | ||||
|  "name": "Loan Repayment", | ||||
|  | ||||
| @ -22,16 +22,19 @@ frappe.ui.form.on('Loan Security Pledge', { | ||||
| frappe.ui.form.on("Pledge", { | ||||
| 	loan_security: function(frm, cdt, cdn) { | ||||
| 		let row = locals[cdt][cdn]; | ||||
| 		frappe.call({ | ||||
| 			method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price", | ||||
| 			args: { | ||||
| 				loan_security: row.loan_security | ||||
| 			}, | ||||
| 			callback: function(r) { | ||||
| 				frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message); | ||||
| 				frm.events.calculate_amounts(frm, cdt, cdn); | ||||
| 			} | ||||
| 		}); | ||||
| 
 | ||||
| 		if (row.loan_security) { | ||||
| 			frappe.call({ | ||||
| 				method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price", | ||||
| 				args: { | ||||
| 					loan_security: row.loan_security | ||||
| 				}, | ||||
| 				callback: function(r) { | ||||
| 					frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message); | ||||
| 					frm.events.calculate_amounts(frm, cdt, cdn); | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	qty: function(frm, cdt, cdn) { | ||||
|  | ||||
| @ -29,6 +29,7 @@ | ||||
|    "unique": 1 | ||||
|   }, | ||||
|   { | ||||
|    "description": "Haircut percentage is the percentage difference between market value of the Loan Security and the value ascribed to that Loan Security when used as collateral for that loan.", | ||||
|    "fieldname": "haircut", | ||||
|    "fieldtype": "Percent", | ||||
|    "label": "Haircut %" | ||||
| @ -46,13 +47,14 @@ | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "description": "Loan To Value Ratio expresses the ratio of the loan amount to the value of the security pledged. A loan security shortfall will be triggered if this falls below the specified value for any loan ", | ||||
|    "fieldname": "loan_to_value_ratio", | ||||
|    "fieldtype": "Percent", | ||||
|    "label": "Loan To Value Ratio" | ||||
|   } | ||||
|  ], | ||||
|  "links": [], | ||||
|  "modified": "2020-04-28 14:06:49.046177", | ||||
|  "modified": "2020-05-16 09:38:45.988080", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Loan Management", | ||||
|  "name": "Loan Security Type", | ||||
|  | ||||
| @ -76,6 +76,7 @@ | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "description": "This account is used for booking loan repayments from the borrower and also disbursing loans to the borrower", | ||||
|    "fieldname": "payment_account", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Payment Account", | ||||
| @ -83,6 +84,7 @@ | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "description": "This account is capital account which is used to allocate capital for loan disbursal account ", | ||||
|    "fieldname": "loan_account", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Loan Account", | ||||
| @ -94,6 +96,7 @@ | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "description": "This account will be used for booking loan interest accruals", | ||||
|    "fieldname": "interest_income_account", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Interest Income Account", | ||||
| @ -101,6 +104,7 @@ | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "description": "This account will be used for booking penalties levied due to delayed repayments", | ||||
|    "fieldname": "penalty_income_account", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Penalty Income Account", | ||||
| @ -109,6 +113,7 @@ | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
|    "description": "If this is not checked the loan by default will be considered as a Demand Loan", | ||||
|    "fieldname": "is_term_loan", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Is Term Loan" | ||||
|  | ||||
| @ -8,7 +8,7 @@ frappe.query_reports["Downtime Analysis"] = { | ||||
| 			label: __("From Date"), | ||||
| 			fieldname:"from_date", | ||||
| 			fieldtype: "Datetime", | ||||
| 			default: frappe.datetime.add_months(frappe.datetime.now_datetime(), -1), | ||||
| 			default: frappe.datetime.convert_to_system_tz(frappe.datetime.add_months(frappe.datetime.now_datetime(), -1)), | ||||
| 			reqd: 1 | ||||
| 		}, | ||||
| 		{ | ||||
|  | ||||
| @ -687,6 +687,7 @@ execute:frappe.delete_doc_if_exists("Page", "appointment-analytic") | ||||
| execute:frappe.rename_doc("Desk Page", "Getting Started", "Home", force=True) | ||||
| erpnext.patches.v12_0.unset_customer_supplier_based_on_type_of_item_price | ||||
| erpnext.patches.v12_0.set_valid_till_date_in_supplier_quotation | ||||
| erpnext.patches.v13_0.update_old_loans | ||||
| erpnext.patches.v12_0.set_serial_no_status #2020-05-21 | ||||
| erpnext.patches.v12_0.update_price_list_currency_in_bom | ||||
| execute:frappe.delete_doc_if_exists('Dashboard', 'Accounts') | ||||
|  | ||||
							
								
								
									
										88
									
								
								erpnext/patches/v13_0/update_old_loans.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								erpnext/patches/v13_0/update_old_loans.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | ||||
| from __future__ import unicode_literals | ||||
| import frappe | ||||
| from frappe import _ | ||||
| from frappe.utils import nowdate | ||||
| from erpnext.accounts.doctype.account.test_account import create_account | ||||
| from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans | ||||
| from erpnext.loan_management.doctype.loan.loan import make_repayment_entry | ||||
| 
 | ||||
| def execute(): | ||||
| 
 | ||||
| 	# Create a penalty account for loan types | ||||
| 
 | ||||
| 	frappe.reload_doc('loan_management', 'doctype', 'loan_type') | ||||
| 	frappe.reload_doc('loan_management', 'doctype', 'loan') | ||||
| 	frappe.reload_doc('loan_management', 'doctype', 'repayment_schedule') | ||||
| 	frappe.reload_doc('loan_management', 'doctype', 'process_loan_interest_accrual') | ||||
| 	frappe.reload_doc('loan_management', 'doctype', 'loan_repayment') | ||||
| 	frappe.reload_doc('loan_management', 'doctype', 'loan_repayment_detail') | ||||
| 	frappe.reload_doc('loan_management', 'doctype', 'loan_interest_accrual') | ||||
| 	frappe.reload_doc('accounts', 'doctype', 'gl_entry') | ||||
| 
 | ||||
| 	updated_loan_types = [] | ||||
| 
 | ||||
| 	loans = frappe.get_all('Loan', fields=['name', 'loan_type', 'company', 'status', 'mode_of_payment', | ||||
| 		'applicant_type', 'applicant', 'loan_account', 'payment_account', 'interest_income_account']) | ||||
| 
 | ||||
| 	for loan in loans: | ||||
| 		# Update details in Loan Types and Loan | ||||
| 		loan_type_company = frappe.db.get_value('Loan Type', loan.loan_type, 'company') | ||||
| 
 | ||||
| 		group_income_account = frappe.get_value('Account', {'company': loan.company, | ||||
| 			'is_group': 1, 'root_type': 'Income', 'account_name': _('Indirect Income')}) | ||||
| 
 | ||||
| 		if not group_income_account: | ||||
| 			group_income_account = frappe.get_value('Account', {'company': loan.company, | ||||
| 				'is_group': 1, 'root_type': 'Income'}) | ||||
| 
 | ||||
| 		penalty_account = create_account(company=loan.company, account_type='Income Account', | ||||
| 			account_name='Penalty Account', parent_account=group_income_account) | ||||
| 
 | ||||
| 		if not loan_type_company: | ||||
| 			loan_type_doc = frappe.get_doc('Loan Type', loan.loan_type) | ||||
| 			loan_type_doc.is_term_loan = 1 | ||||
| 			loan_type_doc.company = loan.company | ||||
| 			loan_type_doc.mode_of_payment = loan.mode_of_payment | ||||
| 			loan_type_doc.payment_account = loan.payment_account | ||||
| 			loan_type_doc.loan_account = loan.loan_account | ||||
| 			loan_type_doc.interest_income_account = loan.interest_income_account | ||||
| 			loan_type_doc.penalty_income_account = penalty_account | ||||
| 			loan_type_doc.submit() | ||||
| 			updated_loan_types.append(loan.loan_type) | ||||
| 
 | ||||
| 		if loan.loan_type in updated_loan_types: | ||||
| 			if loan.status == 'Fully Disbursed': | ||||
| 				status = 'Disbursed' | ||||
| 			elif loan.status == 'Repaid/Closed': | ||||
| 				status = 'Closed' | ||||
| 			else: | ||||
| 				status = loan.status | ||||
| 
 | ||||
| 			frappe.db.set_value('Loan', loan.name, { | ||||
| 				'is_term_loan': 1, | ||||
| 				'penalty_income_account': penalty_account, | ||||
| 				'status': status | ||||
| 			}) | ||||
| 
 | ||||
| 			process_loan_interest_accrual_for_term_loans(posting_date=nowdate(), loan_type=loan.loan_type, | ||||
| 				loan=loan.name) | ||||
| 
 | ||||
| 			payments = frappe.db.sql(''' SELECT j.name, a.debit, a.debit_in_account_currency, j.posting_date | ||||
| 				FROM `tabJournal Entry` j, `tabJournal Entry Account` a | ||||
| 				WHERE a.parent = j.name and a.reference_type='Loan' and a.reference_name = %s | ||||
| 				and account = %s | ||||
| 			''', (loan.name, loan.loan_account), as_dict=1) | ||||
| 
 | ||||
| 			for payment in payments: | ||||
| 				repayment_entry = make_repayment_entry(loan.name, loan.loan_applicant_type, loan.applicant, | ||||
| 					loan.loan_type, loan.company) | ||||
| 
 | ||||
| 				repayment_entry.amount_paid = payment.debit_in_account_currency | ||||
| 				repayment_entry.posting_date = payment.posting_date | ||||
| 				repayment_entry.save() | ||||
| 				repayment_entry.submit() | ||||
| 
 | ||||
| 				jv = frappe.get_doc('Journal Entry', payment.name) | ||||
| 				jv.flags.ignore_links = True | ||||
| 				jv.cancel() | ||||
| 
 | ||||
| @ -13,7 +13,7 @@ frappe.ui.form.on("Communication", { | ||||
| 				frappe.confirm(__(confirm_msg, [__("Issue")]), () => { | ||||
| 					frm.trigger('make_issue_from_communication'); | ||||
| 				}) | ||||
| 			}, "Make"); | ||||
| 			}, "Create"); | ||||
| 		} | ||||
| 
 | ||||
| 		if(!in_list(["Lead", "Opportunity"], frm.doc.reference_doctype)) { | ||||
|  | ||||
| @ -1821,7 +1821,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ | ||||
| 	}, | ||||
| 
 | ||||
| 	set_query_for_item_tax_template: function(doc, cdt, cdn) { | ||||
| 
 | ||||
| 		var item = frappe.get_doc(cdt, cdn); | ||||
| 		if(!item.item_code) { | ||||
| 			frappe.throw(__("Please enter Item Code to get item taxes")); | ||||
| @ -1829,7 +1828,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ | ||||
| 
 | ||||
| 			let filters = { | ||||
| 				'item_code': item.item_code, | ||||
| 				'valid_from': doc.transaction_date || doc.bill_date || doc.posting_date, | ||||
| 				'valid_from': ["<=", doc.transaction_date || doc.bill_date || doc.posting_date], | ||||
| 				'item_group': item.item_group, | ||||
| 			} | ||||
| 
 | ||||
|  | ||||
| @ -234,9 +234,6 @@ class GSTR3BReport(Document): | ||||
| 						self.report_dict[supply_type][supply_category][account_map.get(account_type)] += \ | ||||
| 							flt(tax_details.get((account_name, gst_category), {}).get("amount"), 2) | ||||
| 
 | ||||
| 		for k, v in iteritems(account_map): | ||||
| 			txval -= self.report_dict.get(supply_type, {}).get(supply_category, {}).get(v, 0) | ||||
| 
 | ||||
| 		self.report_dict[supply_type][supply_category]["txval"] += flt(txval, 2) | ||||
| 
 | ||||
| 	def set_inter_state_supply(self, inter_state_supply): | ||||
| @ -256,7 +253,7 @@ class GSTR3BReport(Document): | ||||
| 	def get_total_taxable_value(self, doctype, reverse_charge): | ||||
| 
 | ||||
| 		return frappe._dict(frappe.db.sql(""" | ||||
| 			select gst_category, sum(base_grand_total) as total | ||||
| 			select gst_category, sum(net_total) as total | ||||
| 			from `tab{doctype}` | ||||
| 			where docstatus = 1 and month(posting_date) = %s | ||||
| 			and year(posting_date) = %s and reverse_charge = %s | ||||
| @ -309,26 +306,27 @@ class GSTR3BReport(Document): | ||||
| 			inter_state_supply_tax_mapping.setdefault(d.name, { | ||||
| 				'place_of_supply': d.place_of_supply, | ||||
| 				'taxable_value': d.net_total, | ||||
| 				'gst_category': d.gst_category, | ||||
| 				'camt': 0.0, | ||||
| 				'samt': 0.0, | ||||
| 				'iamt': 0.0, | ||||
| 				'csamt': 0.0 | ||||
| 			}) | ||||
| 
 | ||||
| 			if d.account_head in [d.cgst_account for d in self.account_heads]: | ||||
| 			if d.account_head in [a.cgst_account for a in self.account_heads]: | ||||
| 				inter_state_supply_tax_mapping[d.name]['camt'] += d.tax_amount | ||||
| 
 | ||||
| 			if d.account_head in [d.sgst_account for d in self.account_heads]: | ||||
| 			if d.account_head in [a.sgst_account for a in self.account_heads]: | ||||
| 				inter_state_supply_tax_mapping[d.name]['samt'] += d.tax_amount | ||||
| 
 | ||||
| 			if d.account_head in [d.igst_account for d in self.account_heads]: | ||||
| 			if d.account_head in [a.igst_account for a in self.account_heads]: | ||||
| 				inter_state_supply_tax_mapping[d.name]['iamt'] += d.tax_amount | ||||
| 
 | ||||
| 			if d.account_head in [d.cess_account for d in self.account_heads]: | ||||
| 			if d.account_head in [a.cess_account for a in self.account_heads]: | ||||
| 				inter_state_supply_tax_mapping[d.name]['csamt'] += d.tax_amount | ||||
| 
 | ||||
| 		for key, value in iteritems(inter_state_supply_tax_mapping): | ||||
| 			if d.place_of_supply: | ||||
| 			if value.get('place_of_supply'): | ||||
| 				osup_det = self.report_dict["sup_details"]["osup_det"] | ||||
| 				osup_det["txval"] = flt(osup_det["txval"] + value['taxable_value'], 2) | ||||
| 				osup_det["iamt"] = flt(osup_det["iamt"] + value['iamt'], 2) | ||||
| @ -336,15 +334,15 @@ class GSTR3BReport(Document): | ||||
| 				osup_det["samt"] = flt(osup_det["samt"] + value['samt'], 2) | ||||
| 				osup_det["csamt"] = flt(osup_det["csamt"] + value['csamt'], 2) | ||||
| 
 | ||||
| 				if state_number != d.place_of_supply.split("-")[0]: | ||||
| 					inter_state_supply_details.setdefault((d.gst_category, d.place_of_supply), { | ||||
| 				if state_number != value.get('place_of_supply').split("-")[0]: | ||||
| 					inter_state_supply_details.setdefault((value.get('gst_category'), value.get('place_of_supply')), { | ||||
| 						"txval": 0.0, | ||||
| 						"pos": d.place_of_supply.split("-")[0], | ||||
| 						"pos": value.get('place_of_supply').split("-")[0], | ||||
| 						"iamt": 0.0 | ||||
| 					}) | ||||
| 
 | ||||
| 					inter_state_supply_details[(d.gst_category, d.place_of_supply)]['txval'] += value['taxable_value'] | ||||
| 					inter_state_supply_details[(d.gst_category, d.place_of_supply)]['iamt'] += value['iamt'] | ||||
| 					inter_state_supply_details[(value.get('gst_category'), value.get('place_of_supply'))]['txval'] += value['taxable_value'] | ||||
| 					inter_state_supply_details[(value.get('gst_category'), value.get('place_of_supply'))]['iamt'] += value['iamt'] | ||||
| 
 | ||||
| 		return inter_state_supply_details | ||||
| 
 | ||||
|  | ||||
| @ -131,6 +131,9 @@ class Gstr1Report(object): | ||||
| 					taxable_value += abs(net_amount) | ||||
| 				elif tax_rate: | ||||
| 					taxable_value += abs(net_amount) | ||||
| 				elif not tax_rate and self.filters.get('type_of_business') == 'EXPORT' \ | ||||
| 					and invoice_details.get('export_type') == "Without Payment of Tax": | ||||
| 					taxable_value += abs(net_amount) | ||||
| 
 | ||||
| 		row += [tax_rate or 0, taxable_value] | ||||
| 
 | ||||
|  | ||||
| @ -12,7 +12,8 @@ def get_data(): | ||||
| 			'Payment Entry': 'party', | ||||
| 			'Quotation': 'party_name', | ||||
| 			'Opportunity': 'party_name', | ||||
| 			'Bank Account': 'party' | ||||
| 			'Bank Account': 'party', | ||||
| 			'Subscription': 'party' | ||||
| 		}, | ||||
| 		'dynamic_links': { | ||||
| 			'party_name': ['Customer', 'quotation_to'] | ||||
|  | ||||
| @ -14,10 +14,9 @@ from six import string_types | ||||
| def get_items(start, page_length, price_list, item_group, search_value="", pos_profile=None): | ||||
| 	data = dict() | ||||
| 	warehouse = "" | ||||
| 	display_items_in_stock = 0 | ||||
| 
 | ||||
| 	if pos_profile: | ||||
| 		warehouse, display_items_in_stock = frappe.db.get_value('POS Profile', pos_profile, ['warehouse', 'display_items_in_stock']) | ||||
| 		warehouse = frappe.db.get_value('POS Profile', pos_profile, ['warehouse']) | ||||
| 
 | ||||
| 	if not frappe.db.exists('Item Group', item_group): | ||||
| 		item_group = get_root_of('Item Group') | ||||
| @ -85,7 +84,7 @@ def get_items(start, page_length, price_list, item_group, search_value="", pos_p | ||||
| 			item_price = item_prices.get(item_code) or {} | ||||
| 			item_stock_qty = get_stock_availability(item_code, warehouse) | ||||
| 
 | ||||
| 			if display_items_in_stock and not item_stock_qty: | ||||
| 			if not item_stock_qty: | ||||
| 				pass | ||||
| 			else: | ||||
| 				row = {} | ||||
|  | ||||
| @ -35,7 +35,8 @@ erpnext.PointOfSale.Controller = class { | ||||
| 	create_opening_voucher() { | ||||
| 		const table_fields = [ | ||||
| 			{ fieldname: "mode_of_payment", fieldtype: "Link", in_list_view: 1, label: "Mode of Payment", options: "Mode of Payment", reqd: 1 }, | ||||
| 			{ fieldname: "opening_amount", fieldtype: "Currency", in_list_view: 1, label: "Opening Amount", options: "company:company_currency", reqd: 1 } | ||||
| 			{ fieldname: "opening_amount", fieldtype: "Currency", default: 0, in_list_view: 1, label: "Opening Amount",  | ||||
| 				options: "company:company_currency", reqd: 1 } | ||||
| 		]; | ||||
| 
 | ||||
| 		const dialog = new frappe.ui.Dialog({ | ||||
| @ -66,7 +67,7 @@ erpnext.PointOfSale.Controller = class { | ||||
| 							frappe.db.get_doc("POS Closing Entry", pos_closing_entry.name).then(({ payment_reconciliation }) => { | ||||
| 								dialog.fields_dict.balance_details.df.data = []; | ||||
| 								payment_reconciliation.forEach(pay => { | ||||
| 									const { mode_of_payment, closing_amount } = pay; | ||||
| 									const { mode_of_payment } = pay; | ||||
| 									dialog.fields_dict.balance_details.df.data.push({ | ||||
| 										mode_of_payment: mode_of_payment | ||||
| 									}); | ||||
| @ -152,7 +153,7 @@ erpnext.PointOfSale.Controller = class { | ||||
| 			}, | ||||
| 			() => this.make_new_invoice(), | ||||
| 			() => frappe.dom.unfreeze(), | ||||
| 			() => this.page.set_title(__('Point of Sale Beta')), | ||||
| 			() => this.page.set_title(__('Point of Sale')), | ||||
| 		]); | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user