Merge branch 'develop' into new-translations
This commit is contained in:
commit
119f2f07a5
@ -47,8 +47,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"label": "Banking and Payments",
|
"links": "[\n {\n \"description\": \"Match non-linked Invoices and Payments.\",\n \"label\": \"Match Payments with Invoices\",\n \"name\": \"Payment Reconciliation\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Update bank payment dates with journals.\",\n \"label\": \"Update Bank Clearance Dates\",\n \"name\": \"Bank Clearance\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Invoice Discounting\",\n \"name\": \"Invoice Discounting\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Bank Reconciliation Statement\",\n \"name\": \"Bank Reconciliation Statement\",\n \"type\": \"report\"\n },\n {\n \"icon\": \"fa fa-bar-chart\",\n \"label\": \"Bank Reconciliation\",\n \"name\": \"bank-reconciliation\",\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Bank Clearance Summary\",\n \"name\": \"Bank Clearance Summary\",\n \"type\": \"report\"\n },\n {\n \"label\": \"Bank Guarantee\",\n \"name\": \"Bank Guarantee\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup cheque dimensions for printing\",\n \"label\": \"Cheque Print Template\",\n \"name\": \"Cheque Print Template\",\n \"type\": \"doctype\"\n }\n]",
|
||||||
"links": "[\n {\n \"description\": \"Match non-linked Invoices and Payments.\",\n \"label\": \"Match Payments with Invoices\",\n \"name\": \"Payment Reconciliation\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Update bank payment dates with journals.\",\n \"label\": \"Update Bank Transaction Dates\",\n \"name\": \"Bank Reconciliation\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Invoice Discounting\",\n \"name\": \"Invoice Discounting\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Bank Reconciliation Statement\",\n \"name\": \"Bank Reconciliation Statement\",\n \"type\": \"report\"\n },\n {\n \"icon\": \"fa fa-bar-chart\",\n \"label\": \"Bank Reconciliation\",\n \"name\": \"bank-reconciliation\",\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Bank Clearance Summary\",\n \"name\": \"Bank Clearance Summary\",\n \"type\": \"report\"\n },\n {\n \"label\": \"Bank Guarantee\",\n \"name\": \"Bank Guarantee\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup cheque dimensions for printing\",\n \"label\": \"Cheque Print Template\",\n \"name\": \"Cheque Print Template\",\n \"type\": \"doctype\"\n }\n]"
|
"title": "Banking and Payments"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
|
@ -42,7 +42,7 @@ class AccountingPeriod(Document):
|
|||||||
def get_doctypes_for_closing(self):
|
def get_doctypes_for_closing(self):
|
||||||
docs_for_closing = []
|
docs_for_closing = []
|
||||||
doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", \
|
doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", \
|
||||||
"Bank Reconciliation", "Asset", "Stock Entry"]
|
"Bank Clearance", "Asset", "Stock Entry"]
|
||||||
closed_doctypes = [{"document_type": doctype, "closed": 1} for doctype in doctypes]
|
closed_doctypes = [{"document_type": doctype, "closed": 1} for doctype in doctypes]
|
||||||
for closed_doctype in closed_doctypes:
|
for closed_doctype in closed_doctypes:
|
||||||
docs_for_closing.append(closed_doctype)
|
docs_for_closing.append(closed_doctype)
|
||||||
|
@ -1,74 +1,32 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_guest_to_view": 0,
|
"creation": "2018-04-16 21:50:05.860195",
|
||||||
"allow_import": 0,
|
"doctype": "DocType",
|
||||||
"allow_rename": 0,
|
"editable_grid": 1,
|
||||||
"beta": 0,
|
"engine": "InnoDB",
|
||||||
"creation": "2018-04-16 21:50:05.860195",
|
"field_order": [
|
||||||
"custom": 0,
|
"company"
|
||||||
"docstatus": 0,
|
],
|
||||||
"doctype": "DocType",
|
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "company",
|
||||||
"allow_on_submit": 0,
|
"fieldtype": "Link",
|
||||||
"bold": 0,
|
"in_list_view": 1,
|
||||||
"collapsible": 0,
|
"label": "Company",
|
||||||
"columns": 0,
|
"options": "Company",
|
||||||
"default": "",
|
"reqd": 1
|
||||||
"fieldname": "company",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Company",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Company",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"istable": 1,
|
||||||
"hide_heading": 0,
|
"links": [],
|
||||||
"hide_toolbar": 0,
|
"modified": "2020-05-01 12:32:34.044911",
|
||||||
"idx": 0,
|
"modified_by": "Administrator",
|
||||||
"image_view": 0,
|
"module": "Accounts",
|
||||||
"in_create": 0,
|
"name": "Allowed To Transact With",
|
||||||
"is_submittable": 0,
|
"owner": "Administrator",
|
||||||
"issingle": 0,
|
"permissions": [],
|
||||||
"istable": 1,
|
"quick_entry": 1,
|
||||||
"max_attachments": 0,
|
"sort_field": "modified",
|
||||||
"modified": "2018-04-20 14:00:46.014502",
|
"sort_order": "DESC",
|
||||||
"modified_by": "Administrator",
|
"track_changes": 1
|
||||||
"module": "Accounts",
|
|
||||||
"name": "Allowed To Transact With",
|
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [],
|
|
||||||
"quick_entry": 1,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 1,
|
|
||||||
"track_seen": 0
|
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
// License: GNU General Public License v3. See license.txt
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
frappe.ui.form.on("Bank Reconciliation", {
|
frappe.ui.form.on("Bank Clearance", {
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
frm.add_fetch("account", "account_currency", "account_currency");
|
frm.add_fetch("account", "account_currency", "account_currency");
|
||||||
},
|
},
|
130
erpnext/accounts/doctype/bank_clearance/bank_clearance.json
Normal file
130
erpnext/accounts/doctype/bank_clearance/bank_clearance.json
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"allow_copy": 1,
|
||||||
|
"creation": "2013-01-10 16:34:05",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"document_type": "Document",
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"account",
|
||||||
|
"account_currency",
|
||||||
|
"from_date",
|
||||||
|
"to_date",
|
||||||
|
"column_break_5",
|
||||||
|
"bank_account",
|
||||||
|
"include_reconciled_entries",
|
||||||
|
"include_pos_transactions",
|
||||||
|
"get_payment_entries",
|
||||||
|
"section_break_10",
|
||||||
|
"payment_entries",
|
||||||
|
"update_clearance_date",
|
||||||
|
"total_amount"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fetch_from": "bank_account.account",
|
||||||
|
"fetch_if_empty": 1,
|
||||||
|
"fieldname": "account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Account",
|
||||||
|
"options": "Account",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "account_currency",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Account Currency",
|
||||||
|
"options": "Currency",
|
||||||
|
"print_hide": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "from_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "From Date",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "to_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "To Date",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_5",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Select the Bank Account to reconcile.",
|
||||||
|
"fieldname": "bank_account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Bank Account",
|
||||||
|
"options": "Bank Account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "include_reconciled_entries",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Include Reconciled Entries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "include_pos_transactions",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Include POS Transactions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "get_payment_entries",
|
||||||
|
"fieldtype": "Button",
|
||||||
|
"label": "Get Payment Entries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_10",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 1,
|
||||||
|
"fieldname": "payment_entries",
|
||||||
|
"fieldtype": "Table",
|
||||||
|
"label": "Payment Entries",
|
||||||
|
"options": "Bank Clearance Detail"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "update_clearance_date",
|
||||||
|
"fieldtype": "Button",
|
||||||
|
"label": "Update Clearance Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "total_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Total Amount",
|
||||||
|
"options": "account_currency",
|
||||||
|
"read_only": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hide_toolbar": 1,
|
||||||
|
"icon": "fa fa-check",
|
||||||
|
"idx": 1,
|
||||||
|
"issingle": 1,
|
||||||
|
"modified": "2020-04-06 16:12:06.628008",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Bank Clearance",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"read": 1,
|
||||||
|
"role": "Accounts User",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"quick_entry": 1,
|
||||||
|
"read_only": 1,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "ASC"
|
||||||
|
}
|
@ -11,7 +11,7 @@ form_grid_templates = {
|
|||||||
"journal_entries": "templates/form_grid/bank_reconciliation_grid.html"
|
"journal_entries": "templates/form_grid/bank_reconciliation_grid.html"
|
||||||
}
|
}
|
||||||
|
|
||||||
class BankReconciliation(Document):
|
class BankClearance(Document):
|
||||||
def get_payment_entries(self):
|
def get_payment_entries(self):
|
||||||
if not (self.from_date and self.to_date):
|
if not (self.from_date and self.to_date):
|
||||||
frappe.throw(_("From Date and To Date are Mandatory"))
|
frappe.throw(_("From Date and To Date are Mandatory"))
|
@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class TestBankClearance(unittest.TestCase):
|
||||||
|
pass
|
1
erpnext/accounts/doctype/bank_clearance_detail/README.md
Normal file
1
erpnext/accounts/doctype/bank_clearance_detail/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
Detail of transaction for parent Bank Clearance.
|
@ -326,7 +326,7 @@
|
|||||||
"modified": "2019-01-07 16:52:07.174687",
|
"modified": "2019-01-07 16:52:07.174687",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Reconciliation Detail",
|
"name": "Bank Clearance Detail",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
@ -5,5 +5,5 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class BankReconciliationDetail(Document):
|
class BankClearanceDetail(Document):
|
||||||
pass
|
pass
|
@ -1,484 +0,0 @@
|
|||||||
{
|
|
||||||
"allow_copy": 1,
|
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2013-01-10 16:34:05",
|
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
|
||||||
"document_type": "Document",
|
|
||||||
"editable_grid": 0,
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_from": "bank_account.account",
|
|
||||||
"fetch_if_empty": 1,
|
|
||||||
"fieldname": "account",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Account",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Account",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "account_currency",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 1,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Account Currency",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Currency",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 1,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "from_date",
|
|
||||||
"fieldtype": "Date",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "From Date",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "to_date",
|
|
||||||
"fieldtype": "Date",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "To Date",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "column_break_5",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "Select the Bank Account to reconcile.",
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "bank_account",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Bank Account",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Bank Account",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "include_reconciled_entries",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Include Reconciled Entries",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "include_pos_transactions",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Include POS Transactions",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "get_payment_entries",
|
|
||||||
"fieldtype": "Button",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Get Payment Entries",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "section_break_10",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 1,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "payment_entries",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Payment Entries",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Bank Reconciliation Detail",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "update_clearance_date",
|
|
||||||
"fieldtype": "Button",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Update Clearance Date",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "total_amount",
|
|
||||||
"fieldtype": "Currency",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Total Amount",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "account_currency",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_toolbar": 1,
|
|
||||||
"icon": "fa fa-check",
|
|
||||||
"idx": 1,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 1,
|
|
||||||
"istable": 0,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"menu_index": 0,
|
|
||||||
"modified": "2020-01-22 00:00:00.000000",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Accounts",
|
|
||||||
"name": "Bank Reconciliation",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [
|
|
||||||
{
|
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
|
||||||
"delete": 0,
|
|
||||||
"email": 0,
|
|
||||||
"export": 0,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 0,
|
|
||||||
"read": 1,
|
|
||||||
"report": 0,
|
|
||||||
"role": "Accounts User",
|
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"quick_entry": 1,
|
|
||||||
"read_only": 1,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_order": "ASC",
|
|
||||||
"track_changes": 0,
|
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
QUnit.module('Account');
|
|
||||||
|
|
||||||
QUnit.test("test Bank Reconciliation", function(assert) {
|
|
||||||
assert.expect(0);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => frappe.set_route('Form', 'Bank Reconciliation'),
|
|
||||||
() => cur_frm.set_value('bank_account','Cash - FT'),
|
|
||||||
() => frappe.click_button('Get Payment Entries'),
|
|
||||||
() => {
|
|
||||||
for(var i=0;i<=cur_frm.doc.payment_entries.length-1;i++){
|
|
||||||
cur_frm.doc.payment_entries[i].clearance_date = frappe.datetime.add_days(frappe.datetime.now_date(), 2);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
() => {cur_frm.refresh_fields('payment_entries');},
|
|
||||||
() => frappe.click_button('Update Clearance Date'),
|
|
||||||
() => frappe.timeout(0.5),
|
|
||||||
() => frappe.click_button('Close'),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
class TestBankReconciliation(unittest.TestCase):
|
|
||||||
pass
|
|
@ -1 +0,0 @@
|
|||||||
Detail of transaction for parent Bank Reconciliation.
|
|
@ -1 +0,0 @@
|
|||||||
from __future__ import unicode_literals
|
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
import unittest
|
import unittest
|
||||||
from frappe.utils import nowdate
|
from frappe.utils import nowdate, now_datetime
|
||||||
from erpnext.accounts.utils import get_fiscal_year
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
|
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
|
||||||
from erpnext.accounts.doctype.budget.budget import get_actual_expense, BudgetError
|
from erpnext.accounts.doctype.budget.budget import get_actual_expense, BudgetError
|
||||||
@ -13,27 +13,28 @@ from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journ
|
|||||||
|
|
||||||
class TestBudget(unittest.TestCase):
|
class TestBudget(unittest.TestCase):
|
||||||
def test_monthly_budget_crossed_ignore(self):
|
def test_monthly_budget_crossed_ignore(self):
|
||||||
set_total_expense_zero("2013-02-28", "cost_center")
|
set_total_expense_zero(nowdate(), "cost_center")
|
||||||
|
|
||||||
budget = make_budget(budget_against="Cost Center")
|
budget = make_budget(budget_against="Cost Center")
|
||||||
|
|
||||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||||
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
|
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True)
|
||||||
|
|
||||||
self.assertTrue(frappe.db.get_value("GL Entry",
|
self.assertTrue(frappe.db.get_value("GL Entry",
|
||||||
{"voucher_type": "Journal Entry", "voucher_no": jv.name}))
|
{"voucher_type": "Journal Entry", "voucher_no": jv.name}))
|
||||||
|
|
||||||
budget.cancel()
|
budget.cancel()
|
||||||
|
jv.cancel()
|
||||||
|
|
||||||
def test_monthly_budget_crossed_stop1(self):
|
def test_monthly_budget_crossed_stop1(self):
|
||||||
set_total_expense_zero("2013-02-28", "cost_center")
|
set_total_expense_zero(nowdate(), "cost_center")
|
||||||
|
|
||||||
budget = make_budget(budget_against="Cost Center")
|
budget = make_budget(budget_against="Cost Center")
|
||||||
|
|
||||||
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
|
|
||||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||||
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date="2013-02-28")
|
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date=nowdate())
|
||||||
|
|
||||||
self.assertRaises(BudgetError, jv.submit)
|
self.assertRaises(BudgetError, jv.submit)
|
||||||
|
|
||||||
@ -41,14 +42,14 @@ class TestBudget(unittest.TestCase):
|
|||||||
budget.cancel()
|
budget.cancel()
|
||||||
|
|
||||||
def test_exception_approver_role(self):
|
def test_exception_approver_role(self):
|
||||||
set_total_expense_zero("2013-02-28", "cost_center")
|
set_total_expense_zero(nowdate(), "cost_center")
|
||||||
|
|
||||||
budget = make_budget(budget_against="Cost Center")
|
budget = make_budget(budget_against="Cost Center")
|
||||||
|
|
||||||
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
|
|
||||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||||
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date="2013-03-02")
|
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date=nowdate())
|
||||||
|
|
||||||
self.assertRaises(BudgetError, jv.submit)
|
self.assertRaises(BudgetError, jv.submit)
|
||||||
|
|
||||||
@ -112,16 +113,17 @@ class TestBudget(unittest.TestCase):
|
|||||||
|
|
||||||
budget.load_from_db()
|
budget.load_from_db()
|
||||||
budget.cancel()
|
budget.cancel()
|
||||||
|
po.cancel()
|
||||||
|
|
||||||
def test_monthly_budget_crossed_stop2(self):
|
def test_monthly_budget_crossed_stop2(self):
|
||||||
set_total_expense_zero("2013-02-28", "project")
|
set_total_expense_zero(nowdate(), "project")
|
||||||
|
|
||||||
budget = make_budget(budget_against="Project")
|
budget = make_budget(budget_against="Project")
|
||||||
|
|
||||||
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
|
|
||||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||||
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", project="_Test Project", posting_date="2013-02-28")
|
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", project="_Test Project", posting_date=nowdate())
|
||||||
|
|
||||||
self.assertRaises(BudgetError, jv.submit)
|
self.assertRaises(BudgetError, jv.submit)
|
||||||
|
|
||||||
@ -129,86 +131,76 @@ class TestBudget(unittest.TestCase):
|
|||||||
budget.cancel()
|
budget.cancel()
|
||||||
|
|
||||||
def test_yearly_budget_crossed_stop1(self):
|
def test_yearly_budget_crossed_stop1(self):
|
||||||
set_total_expense_zero("2013-02-28", "cost_center")
|
set_total_expense_zero(nowdate(), "cost_center")
|
||||||
|
|
||||||
budget = make_budget(budget_against="Cost Center")
|
budget = make_budget(budget_against="Cost Center")
|
||||||
|
|
||||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||||
"_Test Bank - _TC", 150000, "_Test Cost Center - _TC", posting_date="2013-03-28")
|
"_Test Bank - _TC", 250000, "_Test Cost Center - _TC", posting_date=nowdate())
|
||||||
|
|
||||||
self.assertRaises(BudgetError, jv.submit)
|
self.assertRaises(BudgetError, jv.submit)
|
||||||
|
|
||||||
budget.cancel()
|
budget.cancel()
|
||||||
|
|
||||||
def test_yearly_budget_crossed_stop2(self):
|
def test_yearly_budget_crossed_stop2(self):
|
||||||
set_total_expense_zero("2013-02-28", "project")
|
set_total_expense_zero(nowdate(), "project")
|
||||||
|
|
||||||
budget = make_budget(budget_against="Project")
|
budget = make_budget(budget_against="Project")
|
||||||
|
|
||||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||||
"_Test Bank - _TC", 150000, "_Test Cost Center - _TC", project="_Test Project", posting_date="2013-03-28")
|
"_Test Bank - _TC", 250000, "_Test Cost Center - _TC", project="_Test Project", posting_date=nowdate())
|
||||||
|
|
||||||
self.assertRaises(BudgetError, jv.submit)
|
self.assertRaises(BudgetError, jv.submit)
|
||||||
|
|
||||||
budget.cancel()
|
budget.cancel()
|
||||||
|
|
||||||
def test_monthly_budget_on_cancellation1(self):
|
def test_monthly_budget_on_cancellation1(self):
|
||||||
set_total_expense_zero("2013-02-28", "cost_center")
|
set_total_expense_zero(nowdate(), "cost_center")
|
||||||
|
|
||||||
budget = make_budget(budget_against="Cost Center")
|
budget = make_budget(budget_against="Cost Center")
|
||||||
|
|
||||||
jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
for i in range(now_datetime().month):
|
||||||
"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
|
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||||
|
"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True)
|
||||||
|
|
||||||
self.assertTrue(frappe.db.get_value("GL Entry",
|
self.assertTrue(frappe.db.get_value("GL Entry",
|
||||||
{"voucher_type": "Journal Entry", "voucher_no": jv1.name}))
|
{"voucher_type": "Journal Entry", "voucher_no": jv.name}))
|
||||||
|
|
||||||
jv2 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
|
||||||
"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
|
|
||||||
|
|
||||||
self.assertTrue(frappe.db.get_value("GL Entry",
|
|
||||||
{"voucher_type": "Journal Entry", "voucher_no": jv2.name}))
|
|
||||||
|
|
||||||
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
|
|
||||||
self.assertRaises(BudgetError, jv1.cancel)
|
self.assertRaises(BudgetError, jv.cancel)
|
||||||
|
|
||||||
budget.load_from_db()
|
budget.load_from_db()
|
||||||
budget.cancel()
|
budget.cancel()
|
||||||
|
|
||||||
def test_monthly_budget_on_cancellation2(self):
|
def test_monthly_budget_on_cancellation2(self):
|
||||||
set_total_expense_zero("2013-02-28", "project")
|
set_total_expense_zero(nowdate(), "project")
|
||||||
|
|
||||||
budget = make_budget(budget_against="Project")
|
budget = make_budget(budget_against="Project")
|
||||||
|
|
||||||
jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
for i in range(now_datetime().month):
|
||||||
"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True, project="_Test Project")
|
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||||
|
"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True, project="_Test Project")
|
||||||
|
|
||||||
self.assertTrue(frappe.db.get_value("GL Entry",
|
self.assertTrue(frappe.db.get_value("GL Entry",
|
||||||
{"voucher_type": "Journal Entry", "voucher_no": jv1.name}))
|
{"voucher_type": "Journal Entry", "voucher_no": jv.name}))
|
||||||
|
|
||||||
jv2 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
|
||||||
"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True, project="_Test Project")
|
|
||||||
|
|
||||||
self.assertTrue(frappe.db.get_value("GL Entry",
|
|
||||||
{"voucher_type": "Journal Entry", "voucher_no": jv2.name}))
|
|
||||||
|
|
||||||
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
|
|
||||||
self.assertRaises(BudgetError, jv1.cancel)
|
self.assertRaises(BudgetError, jv.cancel)
|
||||||
|
|
||||||
budget.load_from_db()
|
budget.load_from_db()
|
||||||
budget.cancel()
|
budget.cancel()
|
||||||
|
|
||||||
def test_monthly_budget_against_group_cost_center(self):
|
def test_monthly_budget_against_group_cost_center(self):
|
||||||
set_total_expense_zero("2013-02-28", "cost_center")
|
set_total_expense_zero(nowdate(), "cost_center")
|
||||||
set_total_expense_zero("2013-02-28", "cost_center", "_Test Cost Center 2 - _TC")
|
set_total_expense_zero(nowdate(), "cost_center", "_Test Cost Center 2 - _TC")
|
||||||
|
|
||||||
budget = make_budget(budget_against="Cost Center", cost_center="_Test Company - _TC")
|
budget = make_budget(budget_against="Cost Center", cost_center="_Test Company - _TC")
|
||||||
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
|
|
||||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||||
"_Test Bank - _TC", 40000, "_Test Cost Center 2 - _TC", posting_date="2013-02-28")
|
"_Test Bank - _TC", 40000, "_Test Cost Center 2 - _TC", posting_date=nowdate())
|
||||||
|
|
||||||
self.assertRaises(BudgetError, jv.submit)
|
self.assertRaises(BudgetError, jv.submit)
|
||||||
|
|
||||||
@ -231,7 +223,7 @@ class TestBudget(unittest.TestCase):
|
|||||||
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
|
|
||||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||||
"_Test Bank - _TC", 40000, cost_center, posting_date="2013-02-28")
|
"_Test Bank - _TC", 40000, cost_center, posting_date=nowdate())
|
||||||
|
|
||||||
self.assertRaises(BudgetError, jv.submit)
|
self.assertRaises(BudgetError, jv.submit)
|
||||||
|
|
||||||
@ -246,12 +238,14 @@ def set_total_expense_zero(posting_date, budget_against_field=None, budget_again
|
|||||||
else:
|
else:
|
||||||
budget_against = budget_against_CC or "_Test Cost Center - _TC"
|
budget_against = budget_against_CC or "_Test Cost Center - _TC"
|
||||||
|
|
||||||
|
fiscal_year = get_fiscal_year(nowdate())[0]
|
||||||
|
|
||||||
args = frappe._dict({
|
args = frappe._dict({
|
||||||
"account": "_Test Account Cost for Goods Sold - _TC",
|
"account": "_Test Account Cost for Goods Sold - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"monthly_end_date": posting_date,
|
"monthly_end_date": posting_date,
|
||||||
"company": "_Test Company",
|
"company": "_Test Company",
|
||||||
"fiscal_year": "_Test Fiscal Year 2013",
|
"fiscal_year": fiscal_year,
|
||||||
"budget_against_field": budget_against_field,
|
"budget_against_field": budget_against_field,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -263,10 +257,10 @@ def set_total_expense_zero(posting_date, budget_against_field=None, budget_again
|
|||||||
if existing_expense:
|
if existing_expense:
|
||||||
if budget_against_field == "cost_center":
|
if budget_against_field == "cost_center":
|
||||||
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||||
"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
|
"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True)
|
||||||
elif budget_against_field == "project":
|
elif budget_against_field == "project":
|
||||||
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||||
"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True, project="_Test Project", posting_date="2013-02-28")
|
"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True, project="_Test Project", posting_date=nowdate())
|
||||||
|
|
||||||
def make_budget(**args):
|
def make_budget(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
@ -274,10 +268,13 @@ def make_budget(**args):
|
|||||||
budget_against=args.budget_against
|
budget_against=args.budget_against
|
||||||
cost_center=args.cost_center
|
cost_center=args.cost_center
|
||||||
|
|
||||||
|
fiscal_year = get_fiscal_year(nowdate())[0]
|
||||||
|
|
||||||
if budget_against == "Project":
|
if budget_against == "Project":
|
||||||
budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", "_Test Project/_Test Fiscal Year 2013%")})
|
project_name = "{0}%".format("_Test Project/" + fiscal_year)
|
||||||
|
budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", project_name)})
|
||||||
else:
|
else:
|
||||||
cost_center_name = "{0}%".format(cost_center or "_Test Cost Center - _TC/_Test Fiscal Year 2013")
|
cost_center_name = "{0}%".format(cost_center or "_Test Cost Center - _TC/" + fiscal_year)
|
||||||
budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", cost_center_name)})
|
budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", cost_center_name)})
|
||||||
for d in budget_list:
|
for d in budget_list:
|
||||||
frappe.db.sql("delete from `tabBudget` where name = %(name)s", d)
|
frappe.db.sql("delete from `tabBudget` where name = %(name)s", d)
|
||||||
@ -290,8 +287,10 @@ def make_budget(**args):
|
|||||||
else:
|
else:
|
||||||
budget.cost_center =cost_center or "_Test Cost Center - _TC"
|
budget.cost_center =cost_center or "_Test Cost Center - _TC"
|
||||||
|
|
||||||
|
monthly_distribution = frappe.get_doc("Monthly Distribution", "_Test Distribution")
|
||||||
|
monthly_distribution.fiscal_year = fiscal_year
|
||||||
|
|
||||||
budget.fiscal_year = "_Test Fiscal Year 2013"
|
budget.fiscal_year = fiscal_year
|
||||||
budget.monthly_distribution = "_Test Distribution"
|
budget.monthly_distribution = "_Test Distribution"
|
||||||
budget.company = "_Test Company"
|
budget.company = "_Test Company"
|
||||||
budget.applicable_on_booking_actual_expenses = 1
|
budget.applicable_on_booking_actual_expenses = 1
|
||||||
@ -300,7 +299,7 @@ def make_budget(**args):
|
|||||||
budget.budget_against = budget_against
|
budget.budget_against = budget_against
|
||||||
budget.append("accounts", {
|
budget.append("accounts", {
|
||||||
"account": "_Test Account Cost for Goods Sold - _TC",
|
"account": "_Test Account Cost for Goods Sold - _TC",
|
||||||
"budget_amount": 100000
|
"budget_amount": 200000
|
||||||
})
|
})
|
||||||
|
|
||||||
if args.applicable_on_material_request:
|
if args.applicable_on_material_request:
|
||||||
|
@ -18,7 +18,7 @@ frappe.ui.form.on('Cost Center', {
|
|||||||
},
|
},
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if (!frm.is_new()) {
|
if (!frm.is_new()) {
|
||||||
frm.add_custom_button(__('Update Cost Center Number'), function () {
|
frm.add_custom_button(__('Update Cost Center Name / Number'), function () {
|
||||||
frm.trigger("update_cost_center_number");
|
frm.trigger("update_cost_center_number");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -47,35 +47,45 @@ frappe.ui.form.on('Cost Center', {
|
|||||||
},
|
},
|
||||||
update_cost_center_number: function(frm) {
|
update_cost_center_number: function(frm) {
|
||||||
var d = new frappe.ui.Dialog({
|
var d = new frappe.ui.Dialog({
|
||||||
title: __('Update Cost Center Number'),
|
title: __('Update Cost Center Name / Number'),
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
"label": 'Cost Center Number',
|
"label": "Cost Center Name",
|
||||||
|
"fieldname": "cost_center_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"reqd": 1,
|
||||||
|
"default": frm.doc.cost_center_name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Cost Center Number",
|
||||||
"fieldname": "cost_center_number",
|
"fieldname": "cost_center_number",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"reqd": 1
|
"reqd": 1,
|
||||||
|
"default": frm.doc.cost_center_number
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
var data = d.get_values();
|
var data = d.get_values();
|
||||||
if(data.cost_center_number === frm.doc.cost_center_number) {
|
if(data.cost_center_name === frm.doc.cost_center_name && data.cost_center_number === frm.doc.cost_center_number) {
|
||||||
d.hide();
|
d.hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
frappe.dom.freeze();
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.accounts.utils.update_number_field",
|
method: "erpnext.accounts.utils.update_cost_center",
|
||||||
args: {
|
args: {
|
||||||
doctype_name: frm.doc.doctype,
|
docname: frm.doc.name,
|
||||||
name: frm.doc.name,
|
cost_center_name: data.cost_center_name,
|
||||||
field_name: d.fields[0].fieldname,
|
cost_center_number: data.cost_center_number,
|
||||||
number_value: data.cost_center_number,
|
|
||||||
company: frm.doc.company
|
company: frm.doc.company
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
|
frappe.dom.unfreeze();
|
||||||
if(!r.exc) {
|
if(!r.exc) {
|
||||||
if(r.message) {
|
if(r.message) {
|
||||||
frappe.set_route("Form", "Cost Center", r.message);
|
frappe.set_route("Form", "Cost Center", r.message);
|
||||||
} else {
|
} else {
|
||||||
|
me.frm.set_value("cost_center_name", data.cost_center_name);
|
||||||
me.frm.set_value("cost_center_number", data.cost_center_number);
|
me.frm.set_value("cost_center_number", data.cost_center_number);
|
||||||
}
|
}
|
||||||
d.hide();
|
d.hide();
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
"actions": [],
|
"actions": [],
|
||||||
"allow_copy": 1,
|
"allow_copy": 1,
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
|
||||||
"creation": "2013-01-23 19:57:17",
|
"creation": "2013-01-23 19:57:17",
|
||||||
"description": "Track separate Income and Expense for product verticals or divisions.",
|
"description": "Track separate Income and Expense for product verticals or divisions.",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
@ -126,7 +125,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_tree": 1,
|
"is_tree": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-03-18 17:59:04.321637",
|
"modified": "2020-04-29 16:09:30.025214",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Cost Center",
|
"name": "Cost Center",
|
||||||
|
@ -30,7 +30,8 @@
|
|||||||
"company",
|
"company",
|
||||||
"finance_book",
|
"finance_book",
|
||||||
"to_rename",
|
"to_rename",
|
||||||
"due_date"
|
"due_date",
|
||||||
|
"is_cancelled"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -245,12 +246,18 @@
|
|||||||
"fieldname": "due_date",
|
"fieldname": "due_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Due Date"
|
"label": "Due Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "is_cancelled",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Is Cancelled"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-list",
|
"icon": "fa fa-list",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"in_create": 1,
|
"in_create": 1,
|
||||||
"modified": "2020-03-28 16:22:33.766994",
|
"modified": "2020-04-07 16:22:33.766994",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "GL Entry",
|
"name": "GL Entry",
|
||||||
|
@ -30,23 +30,20 @@ class GLEntry(Document):
|
|||||||
self.pl_must_have_cost_center()
|
self.pl_must_have_cost_center()
|
||||||
self.validate_cost_center()
|
self.validate_cost_center()
|
||||||
|
|
||||||
if not self.flags.from_repost:
|
self.check_pl_account()
|
||||||
self.check_pl_account()
|
self.validate_party()
|
||||||
self.validate_party()
|
self.validate_currency()
|
||||||
self.validate_currency()
|
|
||||||
|
|
||||||
def on_update_with_args(self, adv_adj, update_outstanding = 'Yes', from_repost=False):
|
def on_update_with_args(self, adv_adj, update_outstanding = 'Yes'):
|
||||||
if not from_repost:
|
self.validate_account_details(adv_adj)
|
||||||
self.validate_account_details(adv_adj)
|
self.validate_dimensions_for_pl_and_bs()
|
||||||
self.validate_dimensions_for_pl_and_bs()
|
|
||||||
check_freezing_date(self.posting_date, adv_adj)
|
|
||||||
|
|
||||||
validate_frozen_account(self.account, adv_adj)
|
validate_frozen_account(self.account, adv_adj)
|
||||||
validate_balance_type(self.account, adv_adj)
|
validate_balance_type(self.account, adv_adj)
|
||||||
|
|
||||||
# Update outstanding amt on against voucher
|
# Update outstanding amt on against voucher
|
||||||
if self.against_voucher_type in ['Journal Entry', 'Sales Invoice', 'Purchase Invoice', 'Fees'] \
|
if self.against_voucher_type in ['Journal Entry', 'Sales Invoice', 'Purchase Invoice', 'Fees'] \
|
||||||
and self.against_voucher and update_outstanding == 'Yes' and not from_repost:
|
and self.against_voucher and update_outstanding == 'Yes':
|
||||||
update_outstanding_amt(self.account, self.party_type, self.party, self.against_voucher_type,
|
update_outstanding_amt(self.account, self.party_type, self.party, self.against_voucher_type,
|
||||||
self.against_voucher)
|
self.against_voucher)
|
||||||
|
|
||||||
@ -159,7 +156,6 @@ class GLEntry(Document):
|
|||||||
if self.party_type and self.party:
|
if self.party_type and self.party:
|
||||||
validate_party_gle_currency(self.party_type, self.party, self.company, self.account_currency)
|
validate_party_gle_currency(self.party_type, self.party, self.company, self.account_currency)
|
||||||
|
|
||||||
|
|
||||||
def validate_and_set_fiscal_year(self):
|
def validate_and_set_fiscal_year(self):
|
||||||
if not self.fiscal_year:
|
if not self.fiscal_year:
|
||||||
self.fiscal_year = get_fiscal_year(self.posting_date, company=self.company)[0]
|
self.fiscal_year = get_fiscal_year(self.posting_date, company=self.company)[0]
|
||||||
@ -176,19 +172,6 @@ def validate_balance_type(account, adv_adj=False):
|
|||||||
(balance_must_be=="Credit" and flt(balance) > 0):
|
(balance_must_be=="Credit" and flt(balance) > 0):
|
||||||
frappe.throw(_("Balance for Account {0} must always be {1}").format(account, _(balance_must_be)))
|
frappe.throw(_("Balance for Account {0} must always be {1}").format(account, _(balance_must_be)))
|
||||||
|
|
||||||
def check_freezing_date(posting_date, adv_adj=False):
|
|
||||||
"""
|
|
||||||
Nobody can do GL Entries where posting date is before freezing date
|
|
||||||
except authorized person
|
|
||||||
"""
|
|
||||||
if not adv_adj:
|
|
||||||
acc_frozen_upto = frappe.db.get_value('Accounts Settings', None, 'acc_frozen_upto')
|
|
||||||
if acc_frozen_upto:
|
|
||||||
frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
|
|
||||||
if getdate(posting_date) <= getdate(acc_frozen_upto) \
|
|
||||||
and not frozen_accounts_modifier in frappe.get_roles():
|
|
||||||
frappe.throw(_("You are not authorized to add or update entries before {0}").format(formatdate(acc_frozen_upto)))
|
|
||||||
|
|
||||||
def update_outstanding_amt(account, party_type, party, against_voucher_type, against_voucher, on_cancel=False):
|
def update_outstanding_amt(account, party_type, party, against_voucher_type, against_voucher, on_cancel=False):
|
||||||
if party_type and party:
|
if party_type and party:
|
||||||
party_condition = " and party_type={0} and party={1}"\
|
party_condition = " and party_type={0} and party={1}"\
|
||||||
|
@ -57,6 +57,7 @@ class JournalEntry(AccountsController):
|
|||||||
from erpnext.hr.doctype.salary_slip.salary_slip import unlink_ref_doc_from_salary_slip
|
from erpnext.hr.doctype.salary_slip.salary_slip import unlink_ref_doc_from_salary_slip
|
||||||
unlink_ref_doc_from_payment_entries(self)
|
unlink_ref_doc_from_payment_entries(self)
|
||||||
unlink_ref_doc_from_salary_slip(self.name)
|
unlink_ref_doc_from_salary_slip(self.name)
|
||||||
|
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
|
||||||
self.make_gl_entries(1)
|
self.make_gl_entries(1)
|
||||||
self.update_advance_paid()
|
self.update_advance_paid()
|
||||||
self.update_expense_claim()
|
self.update_expense_claim()
|
||||||
@ -594,7 +595,7 @@ class JournalEntry(AccountsController):
|
|||||||
for d in self.accounts:
|
for d in self.accounts:
|
||||||
if d.reference_type=="Expense Claim" and d.reference_name:
|
if d.reference_type=="Expense Claim" and d.reference_name:
|
||||||
doc = frappe.get_doc("Expense Claim", d.reference_name)
|
doc = frappe.get_doc("Expense Claim", d.reference_name)
|
||||||
update_reimbursed_amount(doc)
|
update_reimbursed_amount(doc, jv=self.name)
|
||||||
|
|
||||||
|
|
||||||
def validate_expense_claim(self):
|
def validate_expense_claim(self):
|
||||||
|
@ -60,6 +60,7 @@ class PaymentEntry(AccountsController):
|
|||||||
self.set_remarks()
|
self.set_remarks()
|
||||||
self.validate_duplicate_entry()
|
self.validate_duplicate_entry()
|
||||||
self.validate_allocated_amount()
|
self.validate_allocated_amount()
|
||||||
|
self.validate_paid_invoices()
|
||||||
self.ensure_supplier_is_not_blocked()
|
self.ensure_supplier_is_not_blocked()
|
||||||
self.set_status()
|
self.set_status()
|
||||||
|
|
||||||
@ -75,6 +76,7 @@ class PaymentEntry(AccountsController):
|
|||||||
self.set_status()
|
self.set_status()
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
|
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
|
||||||
self.setup_party_account_field()
|
self.setup_party_account_field()
|
||||||
self.make_gl_entries(cancel=1)
|
self.make_gl_entries(cancel=1)
|
||||||
self.update_outstanding_amounts()
|
self.update_outstanding_amounts()
|
||||||
@ -265,6 +267,25 @@ class PaymentEntry(AccountsController):
|
|||||||
frappe.throw(_("{0} {1} must be submitted")
|
frappe.throw(_("{0} {1} must be submitted")
|
||||||
.format(d.reference_doctype, d.reference_name))
|
.format(d.reference_doctype, d.reference_name))
|
||||||
|
|
||||||
|
def validate_paid_invoices(self):
|
||||||
|
no_oustanding_refs = {}
|
||||||
|
|
||||||
|
for d in self.get("references"):
|
||||||
|
if not d.allocated_amount:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if d.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Fees"):
|
||||||
|
outstanding_amount, is_return = frappe.get_cached_value(d.reference_doctype, d.reference_name, ["outstanding_amount", "is_return"])
|
||||||
|
if outstanding_amount <= 0 and not is_return:
|
||||||
|
no_oustanding_refs.setdefault(d.reference_doctype, []).append(d)
|
||||||
|
|
||||||
|
for k, v in no_oustanding_refs.items():
|
||||||
|
frappe.msgprint(_("{} - {} now have {} as they had no outstanding amount left before submitting the Payment Entry.<br><br>\
|
||||||
|
If this is undesirable please cancel the corresponding Payment Entry.")
|
||||||
|
.format(k, frappe.bold(", ".join([d.reference_name for d in v])), frappe.bold("negative outstanding amount")),
|
||||||
|
title=_("Warning"), indicator="orange")
|
||||||
|
|
||||||
|
|
||||||
def validate_journal_entry(self):
|
def validate_journal_entry(self):
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
if d.allocated_amount and d.reference_doctype == "Journal Entry":
|
if d.allocated_amount and d.reference_doctype == "Journal Entry":
|
||||||
@ -571,7 +592,7 @@ class PaymentEntry(AccountsController):
|
|||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
if d.reference_doctype=="Expense Claim" and d.reference_name:
|
if d.reference_doctype=="Expense Claim" and d.reference_name:
|
||||||
doc = frappe.get_doc("Expense Claim", d.reference_name)
|
doc = frappe.get_doc("Expense Claim", d.reference_name)
|
||||||
update_reimbursed_amount(doc)
|
update_reimbursed_amount(doc, self.name)
|
||||||
|
|
||||||
def on_recurring(self, reference_doc, auto_repeat_doc):
|
def on_recurring(self, reference_doc, auto_repeat_doc):
|
||||||
self.reference_no = reference_doc.name
|
self.reference_no = reference_doc.name
|
||||||
|
12
erpnext/accounts/doctype/payment_entry/payment_entry_list.js
Normal file
12
erpnext/accounts/doctype/payment_entry/payment_entry_list.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
frappe.listview_settings['Payment Entry'] = {
|
||||||
|
|
||||||
|
onload: function(listview) {
|
||||||
|
listview.page.fields_dict.party_type.get_query = function() {
|
||||||
|
return {
|
||||||
|
"filters": {
|
||||||
|
"name": ["in", Object.keys(frappe.boot.party_account_types)],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
@ -35,8 +35,6 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
|
|
||||||
pe.cancel()
|
pe.cancel()
|
||||||
|
|
||||||
self.assertFalse(self.get_gle(pe.name))
|
|
||||||
|
|
||||||
so_advance_paid = frappe.db.get_value("Sales Order", so.name, "advance_paid")
|
so_advance_paid = frappe.db.get_value("Sales Order", so.name, "advance_paid")
|
||||||
self.assertEqual(so_advance_paid, 0)
|
self.assertEqual(so_advance_paid, 0)
|
||||||
|
|
||||||
@ -124,7 +122,6 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
self.assertEqual(outstanding_amount, 0)
|
self.assertEqual(outstanding_amount, 0)
|
||||||
|
|
||||||
pe.cancel()
|
pe.cancel()
|
||||||
self.assertFalse(self.get_gle(pe.name))
|
|
||||||
|
|
||||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
||||||
self.assertEqual(outstanding_amount, 100)
|
self.assertEqual(outstanding_amount, 100)
|
||||||
@ -381,7 +378,6 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
self.assertEqual(outstanding_amount, 0)
|
self.assertEqual(outstanding_amount, 0)
|
||||||
|
|
||||||
pe3.cancel()
|
pe3.cancel()
|
||||||
self.assertFalse(self.get_gle(pe3.name))
|
|
||||||
|
|
||||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount"))
|
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount"))
|
||||||
self.assertEqual(outstanding_amount, -100)
|
self.assertEqual(outstanding_amount, -100)
|
||||||
|
@ -326,7 +326,7 @@ def make_payment_request(**args):
|
|||||||
"reference_doctype": args.dt,
|
"reference_doctype": args.dt,
|
||||||
"reference_name": args.dn,
|
"reference_name": args.dn,
|
||||||
"party_type": args.get("party_type") or "Customer",
|
"party_type": args.get("party_type") or "Customer",
|
||||||
"party": args.get("party") or ref_doc.customer,
|
"party": args.get("party") or ref_doc.get("customer"),
|
||||||
"bank_account": bank_account
|
"bank_account": bank_account
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -420,7 +420,7 @@ def make_payment_entry(docname):
|
|||||||
|
|
||||||
def update_payment_req_status(doc, method):
|
def update_payment_req_status(doc, method):
|
||||||
from erpnext.accounts.doctype.payment_entry.payment_entry import get_reference_details
|
from erpnext.accounts.doctype.payment_entry.payment_entry import get_reference_details
|
||||||
|
|
||||||
for ref in doc.references:
|
for ref in doc.references:
|
||||||
payment_request_name = frappe.db.get_value("Payment Request",
|
payment_request_name = frappe.db.get_value("Payment Request",
|
||||||
{"reference_doctype": ref.reference_doctype, "reference_name": ref.reference_name,
|
{"reference_doctype": ref.reference_doctype, "reference_name": ref.reference_name,
|
||||||
@ -430,7 +430,7 @@ def update_payment_req_status(doc, method):
|
|||||||
ref_details = get_reference_details(ref.reference_doctype, ref.reference_name, doc.party_account_currency)
|
ref_details = get_reference_details(ref.reference_doctype, ref.reference_name, doc.party_account_currency)
|
||||||
pay_req_doc = frappe.get_doc('Payment Request', payment_request_name)
|
pay_req_doc = frappe.get_doc('Payment Request', payment_request_name)
|
||||||
status = pay_req_doc.status
|
status = pay_req_doc.status
|
||||||
|
|
||||||
if status != "Paid" and not ref_details.outstanding_amount:
|
if status != "Paid" and not ref_details.outstanding_amount:
|
||||||
status = 'Paid'
|
status = 'Paid'
|
||||||
elif status != "Partially Paid" and ref_details.outstanding_amount != ref_details.total_amount:
|
elif status != "Partially Paid" and ref_details.outstanding_amount != ref_details.total_amount:
|
||||||
|
@ -5,7 +5,7 @@ frappe.ui.form.on('Period Closing Voucher', {
|
|||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
if (!frm.doc.transaction_date) frm.doc.transaction_date = frappe.datetime.obj_to_str(new Date());
|
if (!frm.doc.transaction_date) frm.doc.transaction_date = frappe.datetime.obj_to_str(new Date());
|
||||||
},
|
},
|
||||||
|
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
frm.set_query("closing_account_head", function() {
|
frm.set_query("closing_account_head", function() {
|
||||||
return {
|
return {
|
||||||
@ -18,9 +18,9 @@ frappe.ui.form.on('Period Closing Voucher', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if(frm.doc.docstatus==1) {
|
if(frm.doc.docstatus > 0) {
|
||||||
frm.add_custom_button(__('Ledger'), function() {
|
frm.add_custom_button(__('Ledger'), function() {
|
||||||
frappe.route_options = {
|
frappe.route_options = {
|
||||||
"voucher_no": frm.doc.name,
|
"voucher_no": frm.doc.name,
|
||||||
@ -33,5 +33,5 @@ frappe.ui.form.on('Period Closing Voucher', {
|
|||||||
}, "fa fa-table");
|
}, "fa fa-table");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -17,8 +17,9 @@ class PeriodClosingVoucher(AccountsController):
|
|||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
frappe.db.sql("""delete from `tabGL Entry`
|
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
|
||||||
where voucher_type = 'Period Closing Voucher' and voucher_no=%s""", self.name)
|
from erpnext.accounts.general_ledger import make_reverse_gl_entries
|
||||||
|
make_reverse_gl_entries(voucher_type="Period Closing Voucher", voucher_no=self.name, cancel=True)
|
||||||
|
|
||||||
def validate_account_head(self):
|
def validate_account_head(self):
|
||||||
closing_account_type = frappe.db.get_value("Account", self.closing_account_head, "root_type")
|
closing_account_type = frappe.db.get_value("Account", self.closing_account_head, "root_type")
|
||||||
|
@ -1,123 +1,39 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_guest_to_view": 0,
|
"creation": "2017-10-27 16:46:06.060930",
|
||||||
"allow_import": 0,
|
"doctype": "DocType",
|
||||||
"allow_rename": 0,
|
"editable_grid": 1,
|
||||||
"beta": 0,
|
"engine": "InnoDB",
|
||||||
"creation": "2017-10-27 16:46:06.060930",
|
"field_order": [
|
||||||
"custom": 0,
|
"default",
|
||||||
"docstatus": 0,
|
"user"
|
||||||
"doctype": "DocType",
|
],
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"default": "0",
|
||||||
"allow_on_submit": 0,
|
"fieldname": "default",
|
||||||
"bold": 0,
|
"fieldtype": "Check",
|
||||||
"collapsible": 0,
|
"in_list_view": 1,
|
||||||
"columns": 0,
|
"label": "Default"
|
||||||
"fieldname": "default",
|
},
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Default",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "user",
|
||||||
"allow_on_submit": 0,
|
"fieldtype": "Link",
|
||||||
"bold": 0,
|
"in_list_view": 1,
|
||||||
"collapsible": 0,
|
"label": "User",
|
||||||
"columns": 0,
|
"options": "User"
|
||||||
"fieldname": "user",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "User",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "User",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"istable": 1,
|
||||||
"hide_heading": 0,
|
"links": [],
|
||||||
"hide_toolbar": 0,
|
"modified": "2020-05-01 09:46:47.599173",
|
||||||
"idx": 0,
|
"modified_by": "Administrator",
|
||||||
"image_view": 0,
|
"module": "Accounts",
|
||||||
"in_create": 0,
|
"name": "POS Profile User",
|
||||||
"is_submittable": 0,
|
"owner": "Administrator",
|
||||||
"issingle": 0,
|
"permissions": [],
|
||||||
"istable": 0,
|
"quick_entry": 1,
|
||||||
"max_attachments": 0,
|
"sort_field": "modified",
|
||||||
"modified": "2017-11-23 17:13:16.005475",
|
"sort_order": "DESC",
|
||||||
"modified_by": "Administrator",
|
"track_changes": 1
|
||||||
"module": "Accounts",
|
|
||||||
"name": "POS Profile User",
|
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [
|
|
||||||
{
|
|
||||||
"amend": 0,
|
|
||||||
"apply_user_permissions": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "System Manager",
|
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"quick_entry": 1,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 1,
|
|
||||||
"track_seen": 0
|
|
||||||
}
|
}
|
@ -382,11 +382,6 @@ function hide_fields(doc) {
|
|||||||
cur_frm.refresh_fields();
|
cur_frm.refresh_fields();
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.cscript.update_stock = function(doc, dt, dn) {
|
|
||||||
hide_fields(doc, dt, dn);
|
|
||||||
this.frm.fields_dict.items.grid.toggle_reqd("item_code", doc.update_stock? true: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.fields_dict.cash_bank_account.get_query = function(doc) {
|
cur_frm.fields_dict.cash_bank_account.get_query = function(doc) {
|
||||||
return {
|
return {
|
||||||
filters: [
|
filters: [
|
||||||
@ -528,5 +523,10 @@ frappe.ui.form.on("Purchase Invoice", {
|
|||||||
erpnext.buying.get_default_bom(frm);
|
erpnext.buying.get_default_bom(frm);
|
||||||
}
|
}
|
||||||
frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted==="Yes");
|
frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted==="Yes");
|
||||||
|
},
|
||||||
|
|
||||||
|
update_stock: function(frm) {
|
||||||
|
hide_fields(frm.doc);
|
||||||
|
frm.fields_dict.items.grid.toggle_reqd("item_code", frm.doc.update_stock? true: false);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -14,7 +14,7 @@ from erpnext.accounts.party import get_party_account, get_due_date
|
|||||||
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
|
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
|
||||||
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billed_amount_based_on_po
|
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billed_amount_based_on_po
|
||||||
from erpnext.stock import get_warehouse_account_map
|
from erpnext.stock import get_warehouse_account_map
|
||||||
from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entries, delete_gl_entries
|
from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entries, make_reverse_gl_entries
|
||||||
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
|
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
|
||||||
from erpnext.buying.utils import check_on_hold_or_closed_status
|
from erpnext.buying.utils import check_on_hold_or_closed_status
|
||||||
from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center
|
from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center
|
||||||
@ -382,7 +382,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.update_project()
|
self.update_project()
|
||||||
update_linked_doc(self.doctype, self.name, self.inter_company_invoice_reference)
|
update_linked_doc(self.doctype, self.name, self.inter_company_invoice_reference)
|
||||||
|
|
||||||
def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
|
def make_gl_entries(self, gl_entries=None):
|
||||||
if not self.grand_total:
|
if not self.grand_total:
|
||||||
return
|
return
|
||||||
if not gl_entries:
|
if not gl_entries:
|
||||||
@ -391,21 +391,17 @@ class PurchaseInvoice(BuyingController):
|
|||||||
if gl_entries:
|
if gl_entries:
|
||||||
update_outstanding = "No" if (cint(self.is_paid) or self.write_off_account) else "Yes"
|
update_outstanding = "No" if (cint(self.is_paid) or self.write_off_account) else "Yes"
|
||||||
|
|
||||||
make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
|
if self.docstatus == 1:
|
||||||
update_outstanding=update_outstanding, merge_entries=False, from_repost=from_repost)
|
make_gl_entries(gl_entries, update_outstanding=update_outstanding, merge_entries=False)
|
||||||
|
elif self.docstatus == 2:
|
||||||
|
make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
|
||||||
|
|
||||||
if update_outstanding == "No":
|
if update_outstanding == "No":
|
||||||
update_outstanding_amt(self.credit_to, "Supplier", self.supplier,
|
update_outstanding_amt(self.credit_to, "Supplier", self.supplier,
|
||||||
self.doctype, self.return_against if cint(self.is_return) and self.return_against else self.name)
|
self.doctype, self.return_against if cint(self.is_return) and self.return_against else self.name)
|
||||||
|
|
||||||
if (repost_future_gle or self.flags.repost_future_gle) and cint(self.update_stock) and self.auto_accounting_for_stock:
|
|
||||||
from erpnext.controllers.stock_controller import update_gl_entries_after
|
|
||||||
items, warehouses = self.get_items_and_warehouses()
|
|
||||||
update_gl_entries_after(self.posting_date, self.posting_time,
|
|
||||||
warehouses, items, company = self.company)
|
|
||||||
|
|
||||||
elif self.docstatus == 2 and cint(self.update_stock) and self.auto_accounting_for_stock:
|
elif self.docstatus == 2 and cint(self.update_stock) and self.auto_accounting_for_stock:
|
||||||
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
|
make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
|
||||||
|
|
||||||
def get_gl_entries(self, warehouse_account=None):
|
def get_gl_entries(self, warehouse_account=None):
|
||||||
self.auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
|
self.auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
|
||||||
@ -934,6 +930,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
frappe.db.set(self, 'status', 'Cancelled')
|
frappe.db.set(self, 'status', 'Cancelled')
|
||||||
|
|
||||||
unlink_inter_company_doc(self.doctype, self.name, self.inter_company_invoice_reference)
|
unlink_inter_company_doc(self.doctype, self.name, self.inter_company_invoice_reference)
|
||||||
|
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
|
||||||
|
|
||||||
def update_project(self):
|
def update_project(self):
|
||||||
project_list = []
|
project_list = []
|
||||||
|
@ -138,13 +138,12 @@
|
|||||||
"row_id": 7
|
"row_id": 7
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"posting_date": "2013-02-03",
|
|
||||||
"supplier": "_Test Supplier",
|
"supplier": "_Test Supplier",
|
||||||
"supplier_name": "_Test Supplier"
|
"supplier_name": "_Test Supplier"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"bill_no": "NA",
|
"bill_no": "NA",
|
||||||
"buying_price_list": "_Test Price List",
|
"buying_price_list": "_Test Price List",
|
||||||
@ -204,7 +203,6 @@
|
|||||||
"tax_amount": 150.0
|
"tax_amount": 150.0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"posting_date": "2013-02-03",
|
|
||||||
"supplier": "_Test Supplier",
|
"supplier": "_Test Supplier",
|
||||||
"supplier_name": "_Test Supplier"
|
"supplier_name": "_Test Supplier"
|
||||||
}
|
}
|
||||||
|
@ -345,7 +345,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
|
|
||||||
set_dynamic_labels: function() {
|
set_dynamic_labels: function() {
|
||||||
this._super();
|
this._super();
|
||||||
this.hide_fields(this.frm.doc);
|
this.frm.events.hide_fields(this.frm)
|
||||||
},
|
},
|
||||||
|
|
||||||
items_on_form_rendered: function() {
|
items_on_form_rendered: function() {
|
||||||
@ -404,7 +404,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
if(r.message && r.message.print_format) {
|
if(r.message && r.message.print_format) {
|
||||||
me.frm.pos_print_format = r.message.print_format;
|
me.frm.pos_print_format = r.message.print_format;
|
||||||
}
|
}
|
||||||
me.frm.script_manager.trigger("update_stock");
|
me.frm.trigger("update_stock");
|
||||||
if(me.frm.doc.taxes_and_charges) {
|
if(me.frm.doc.taxes_and_charges) {
|
||||||
me.frm.script_manager.trigger("taxes_and_charges");
|
me.frm.script_manager.trigger("taxes_and_charges");
|
||||||
}
|
}
|
||||||
@ -446,35 +446,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
// for backward compatibility: combine new and previous states
|
// for backward compatibility: combine new and previous states
|
||||||
$.extend(cur_frm.cscript, new erpnext.accounts.SalesInvoiceController({frm: cur_frm}));
|
$.extend(cur_frm.cscript, new erpnext.accounts.SalesInvoiceController({frm: cur_frm}));
|
||||||
|
|
||||||
// Hide Fields
|
|
||||||
// ------------
|
|
||||||
cur_frm.cscript.hide_fields = function(doc) {
|
|
||||||
var parent_fields = ['project', 'due_date', 'is_opening', 'source', 'total_advance', 'get_advances',
|
|
||||||
'advances', 'from_date', 'to_date'];
|
|
||||||
|
|
||||||
if(cint(doc.is_pos) == 1) {
|
|
||||||
hide_field(parent_fields);
|
|
||||||
} else {
|
|
||||||
for (var i in parent_fields) {
|
|
||||||
var docfield = frappe.meta.docfield_map[doc.doctype][parent_fields[i]];
|
|
||||||
if(!docfield.hidden) unhide_field(parent_fields[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// India related fields
|
|
||||||
if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']);
|
|
||||||
else hide_field(['c_form_applicable', 'c_form_no']);
|
|
||||||
|
|
||||||
this.frm.toggle_enable("write_off_amount", !!!cint(doc.write_off_outstanding_amount_automatically));
|
|
||||||
|
|
||||||
cur_frm.refresh_fields();
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript.update_stock = function(doc, dt, dn) {
|
|
||||||
cur_frm.cscript.hide_fields(doc, dt, dn);
|
|
||||||
this.frm.fields_dict.items.grid.toggle_reqd("item_code", doc.update_stock? true: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript['Make Delivery Note'] = function() {
|
cur_frm.cscript['Make Delivery Note'] = function() {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_delivery_note",
|
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_delivery_note",
|
||||||
@ -719,6 +690,12 @@ frappe.ui.form.on('Sales Invoice', {
|
|||||||
frm.redemption_conversion_factor = null;
|
frm.redemption_conversion_factor = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
update_stock: function(frm, dt, dn) {
|
||||||
|
frm.events.hide_fields(frm);
|
||||||
|
frm.fields_dict.items.grid.toggle_reqd("item_code", frm.doc.update_stock);
|
||||||
|
frm.trigger('reset_posting_time');
|
||||||
|
},
|
||||||
|
|
||||||
redeem_loyalty_points: function(frm) {
|
redeem_loyalty_points: function(frm) {
|
||||||
frm.events.get_loyalty_details(frm);
|
frm.events.get_loyalty_details(frm);
|
||||||
},
|
},
|
||||||
@ -742,6 +719,29 @@ frappe.ui.form.on('Sales Invoice', {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
hide_fields: function(frm) {
|
||||||
|
let doc = frm.doc;
|
||||||
|
var parent_fields = ['project', 'due_date', 'is_opening', 'source', 'total_advance', 'get_advances',
|
||||||
|
'advances', 'from_date', 'to_date'];
|
||||||
|
|
||||||
|
if(cint(doc.is_pos) == 1) {
|
||||||
|
hide_field(parent_fields);
|
||||||
|
} else {
|
||||||
|
for (var i in parent_fields) {
|
||||||
|
var docfield = frappe.meta.docfield_map[doc.doctype][parent_fields[i]];
|
||||||
|
if(!docfield.hidden) unhide_field(parent_fields[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// India related fields
|
||||||
|
if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']);
|
||||||
|
else hide_field(['c_form_applicable', 'c_form_no']);
|
||||||
|
|
||||||
|
frm.toggle_enable("write_off_amount", !!!cint(doc.write_off_outstanding_amount_automatically));
|
||||||
|
|
||||||
|
frm.refresh_fields();
|
||||||
|
},
|
||||||
|
|
||||||
get_loyalty_details: function(frm) {
|
get_loyalty_details: function(frm) {
|
||||||
if (frm.doc.customer && frm.doc.redeem_loyalty_points) {
|
if (frm.doc.customer && frm.doc.redeem_loyalty_points) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
|
@ -149,9 +149,9 @@
|
|||||||
"edit_printing_settings",
|
"edit_printing_settings",
|
||||||
"letter_head",
|
"letter_head",
|
||||||
"group_same_items",
|
"group_same_items",
|
||||||
"language",
|
|
||||||
"column_break_84",
|
|
||||||
"select_print_heading",
|
"select_print_heading",
|
||||||
|
"column_break_84",
|
||||||
|
"language",
|
||||||
"more_information",
|
"more_information",
|
||||||
"inter_company_invoice_reference",
|
"inter_company_invoice_reference",
|
||||||
"is_internal_customer",
|
"is_internal_customer",
|
||||||
@ -1579,7 +1579,7 @@
|
|||||||
"idx": 181,
|
"idx": 181,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-17 12:38:41.435728",
|
"modified": "2020-04-29 13:37:09.355300",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice",
|
"name": "Sales Invoice",
|
||||||
|
@ -7,7 +7,6 @@ import frappe.defaults
|
|||||||
from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr, nowdate
|
from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr, nowdate
|
||||||
from frappe import _, msgprint, throw
|
from frappe import _, msgprint, throw
|
||||||
from erpnext.accounts.party import get_party_account, get_due_date
|
from erpnext.accounts.party import get_party_account, get_due_date
|
||||||
from erpnext.controllers.stock_controller import update_gl_entries_after
|
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
from erpnext.accounts.doctype.sales_invoice.pos import update_multi_mode_option
|
from erpnext.accounts.doctype.sales_invoice.pos import update_multi_mode_option
|
||||||
|
|
||||||
@ -282,6 +281,8 @@ class SalesInvoice(SellingController):
|
|||||||
if "Healthcare" in active_domains:
|
if "Healthcare" in active_domains:
|
||||||
manage_invoice_submit_cancel(self, "on_cancel")
|
manage_invoice_submit_cancel(self, "on_cancel")
|
||||||
|
|
||||||
|
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
|
||||||
|
|
||||||
def update_status_updater_args(self):
|
def update_status_updater_args(self):
|
||||||
if cint(self.update_stock):
|
if cint(self.update_stock):
|
||||||
self.status_updater.append({
|
self.status_updater.append({
|
||||||
@ -717,7 +718,9 @@ class SalesInvoice(SellingController):
|
|||||||
if d.delivery_note and frappe.db.get_value("Delivery Note", d.delivery_note, "docstatus") != 1:
|
if d.delivery_note and frappe.db.get_value("Delivery Note", d.delivery_note, "docstatus") != 1:
|
||||||
throw(_("Delivery Note {0} is not submitted").format(d.delivery_note))
|
throw(_("Delivery Note {0} is not submitted").format(d.delivery_note))
|
||||||
|
|
||||||
def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
|
def make_gl_entries(self, gl_entries=None):
|
||||||
|
from erpnext.accounts.general_ledger import make_reverse_gl_entries
|
||||||
|
|
||||||
auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
|
auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
|
||||||
if not gl_entries:
|
if not gl_entries:
|
||||||
gl_entries = self.get_gl_entries()
|
gl_entries = self.get_gl_entries()
|
||||||
@ -729,23 +732,19 @@ class SalesInvoice(SellingController):
|
|||||||
update_outstanding = "No" if (cint(self.is_pos) or self.write_off_account or
|
update_outstanding = "No" if (cint(self.is_pos) or self.write_off_account or
|
||||||
cint(self.redeem_loyalty_points)) else "Yes"
|
cint(self.redeem_loyalty_points)) else "Yes"
|
||||||
|
|
||||||
make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
|
if self.docstatus == 1:
|
||||||
update_outstanding=update_outstanding, merge_entries=False, from_repost=from_repost)
|
make_gl_entries(gl_entries, update_outstanding=update_outstanding, merge_entries=False)
|
||||||
|
elif self.docstatus == 2:
|
||||||
|
make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
|
||||||
|
|
||||||
if update_outstanding == "No":
|
if update_outstanding == "No":
|
||||||
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
|
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
|
||||||
update_outstanding_amt(self.debit_to, "Customer", self.customer,
|
update_outstanding_amt(self.debit_to, "Customer", self.customer,
|
||||||
self.doctype, self.return_against if cint(self.is_return) and self.return_against else self.name)
|
self.doctype, self.return_against if cint(self.is_return) and self.return_against else self.name)
|
||||||
|
|
||||||
if (repost_future_gle or self.flags.repost_future_gle) and cint(self.update_stock) \
|
|
||||||
and cint(auto_accounting_for_stock):
|
|
||||||
items, warehouses = self.get_items_and_warehouses()
|
|
||||||
update_gl_entries_after(self.posting_date, self.posting_time,
|
|
||||||
warehouses, items, company = self.company)
|
|
||||||
elif self.docstatus == 2 and cint(self.update_stock) \
|
elif self.docstatus == 2 and cint(self.update_stock) \
|
||||||
and cint(auto_accounting_for_stock):
|
and cint(auto_accounting_for_stock):
|
||||||
from erpnext.accounts.general_ledger import delete_gl_entries
|
make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
|
||||||
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
|
|
||||||
|
|
||||||
def get_gl_entries(self, warehouse_account=None):
|
def get_gl_entries(self, warehouse_account=None):
|
||||||
from erpnext.accounts.general_ledger import merge_similar_entries
|
from erpnext.accounts.general_ledger import merge_similar_entries
|
||||||
|
@ -364,7 +364,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
gle = frappe.db.sql("""select * from `tabGL Entry`
|
gle = frappe.db.sql("""select * from `tabGL Entry`
|
||||||
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
|
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
|
||||||
|
|
||||||
self.assertFalse(gle)
|
self.assertTrue(gle)
|
||||||
|
|
||||||
def test_tax_calculation_with_multiple_items(self):
|
def test_tax_calculation_with_multiple_items(self):
|
||||||
si = create_sales_invoice(qty=84, rate=4.6, do_not_save=True)
|
si = create_sales_invoice(qty=84, rate=4.6, do_not_save=True)
|
||||||
@ -678,14 +678,15 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
gle = frappe.db.sql("""select * from `tabGL Entry`
|
gle = frappe.db.sql("""select * from `tabGL Entry`
|
||||||
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
|
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
|
||||||
|
|
||||||
self.assertFalse(gle)
|
self.assertTrue(gle)
|
||||||
|
|
||||||
def test_pos_gl_entry_with_perpetual_inventory(self):
|
def test_pos_gl_entry_with_perpetual_inventory(self):
|
||||||
make_pos_profile()
|
make_pos_profile()
|
||||||
|
|
||||||
pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
|
pr = make_purchase_receipt(company= "_Test Company with perpetual inventory", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
|
||||||
|
|
||||||
pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
|
pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1",
|
||||||
|
income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
|
||||||
|
|
||||||
pos.is_pos = 1
|
pos.is_pos = 1
|
||||||
pos.update_stock = 1
|
pos.update_stock = 1
|
||||||
@ -766,9 +767,13 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
def test_pos_change_amount(self):
|
def test_pos_change_amount(self):
|
||||||
make_pos_profile()
|
make_pos_profile()
|
||||||
|
|
||||||
pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
|
pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",
|
||||||
|
item_code= "_Test FG Item",warehouse= "Stores - TCP1", cost_center= "Main - TCP1")
|
||||||
|
|
||||||
pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
|
pos = create_sales_invoice(company= "_Test Company with perpetual inventory",
|
||||||
|
debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1",
|
||||||
|
income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1",
|
||||||
|
cost_center = "Main - TCP1", do_not_save=True)
|
||||||
|
|
||||||
pos.is_pos = 1
|
pos.is_pos = 1
|
||||||
pos.update_stock = 1
|
pos.update_stock = 1
|
||||||
@ -787,8 +792,15 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
|
from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
|
||||||
|
|
||||||
pos_profile = make_pos_profile()
|
pos_profile = make_pos_profile()
|
||||||
pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
|
|
||||||
pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
|
pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",
|
||||||
|
item_code= "_Test FG Item",
|
||||||
|
warehouse= "Stores - TCP1", cost_center= "Main - TCP1")
|
||||||
|
|
||||||
|
pos = create_sales_invoice(company= "_Test Company with perpetual inventory",
|
||||||
|
debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1",
|
||||||
|
income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1",
|
||||||
|
cost_center = "Main - TCP1", do_not_save=True)
|
||||||
|
|
||||||
pos.is_pos = 1
|
pos.is_pos = 1
|
||||||
pos.update_stock = 1
|
pos.update_stock = 1
|
||||||
@ -891,11 +903,9 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
gle = frappe.db.sql("""select * from `tabGL Entry`
|
gle = frappe.db.sql("""select * from `tabGL Entry`
|
||||||
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
|
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
|
||||||
|
|
||||||
self.assertFalse(gle)
|
self.assertTrue(gle)
|
||||||
|
|
||||||
|
|
||||||
frappe.db.sql("delete from `tabPOS Profile`")
|
frappe.db.sql("delete from `tabPOS Profile`")
|
||||||
si.delete()
|
|
||||||
|
|
||||||
def test_pos_si_without_payment(self):
|
def test_pos_si_without_payment(self):
|
||||||
set_perpetual_inventory()
|
set_perpetual_inventory()
|
||||||
@ -1012,9 +1022,6 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
si.cancel()
|
si.cancel()
|
||||||
|
|
||||||
self.assertTrue(not frappe.db.sql("""select name from `tabJournal Entry Account`
|
|
||||||
where reference_name=%s""", si.name))
|
|
||||||
|
|
||||||
def test_serialized(self):
|
def test_serialized(self):
|
||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||||
@ -1230,7 +1237,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
gle = frappe.db.sql("""select name from `tabGL Entry`
|
gle = frappe.db.sql("""select name from `tabGL Entry`
|
||||||
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
|
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
|
||||||
|
|
||||||
self.assertFalse(gle)
|
self.assertTrue(gle)
|
||||||
|
|
||||||
def test_invalid_currency(self):
|
def test_invalid_currency(self):
|
||||||
# Customer currency = USD
|
# Customer currency = USD
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe, erpnext
|
import frappe, erpnext
|
||||||
from frappe.utils import flt, cstr, cint, comma_and
|
from frappe.utils import flt, cstr, cint, comma_and, today, getdate, formatdate, now
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from erpnext.accounts.utils import get_stock_and_account_balance
|
from erpnext.accounts.utils import get_stock_and_account_balance
|
||||||
from frappe.model.meta import get_field_precision
|
from frappe.model.meta import get_field_precision
|
||||||
@ -15,17 +15,17 @@ class ClosedAccountingPeriod(frappe.ValidationError): pass
|
|||||||
class StockAccountInvalidTransaction(frappe.ValidationError): pass
|
class StockAccountInvalidTransaction(frappe.ValidationError): pass
|
||||||
class StockValueAndAccountBalanceOutOfSync(frappe.ValidationError): pass
|
class StockValueAndAccountBalanceOutOfSync(frappe.ValidationError): pass
|
||||||
|
|
||||||
def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes', from_repost=False):
|
def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes'):
|
||||||
if gl_map:
|
if gl_map:
|
||||||
if not cancel:
|
if not cancel:
|
||||||
validate_accounting_period(gl_map)
|
validate_accounting_period(gl_map)
|
||||||
gl_map = process_gl_map(gl_map, merge_entries)
|
gl_map = process_gl_map(gl_map, merge_entries)
|
||||||
if gl_map and len(gl_map) > 1:
|
if gl_map and len(gl_map) > 1:
|
||||||
save_entries(gl_map, adv_adj, update_outstanding, from_repost)
|
save_entries(gl_map, adv_adj, update_outstanding)
|
||||||
else:
|
else:
|
||||||
frappe.throw(_("Incorrect number of General Ledger Entries found. You might have selected a wrong Account in the transaction."))
|
frappe.throw(_("Incorrect number of General Ledger Entries found. You might have selected a wrong Account in the transaction."))
|
||||||
else:
|
else:
|
||||||
delete_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding)
|
make_reverse_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding)
|
||||||
|
|
||||||
def validate_accounting_period(gl_map):
|
def validate_accounting_period(gl_map):
|
||||||
accounting_periods = frappe.db.sql(""" SELECT
|
accounting_periods = frappe.db.sql(""" SELECT
|
||||||
@ -119,33 +119,36 @@ def check_if_in_list(gle, gl_map, dimensions=None):
|
|||||||
if same_head:
|
if same_head:
|
||||||
return e
|
return e
|
||||||
|
|
||||||
def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
|
def save_entries(gl_map, adv_adj, update_outstanding):
|
||||||
if not from_repost:
|
validate_cwip_accounts(gl_map)
|
||||||
validate_cwip_accounts(gl_map)
|
|
||||||
|
|
||||||
round_off_debit_credit(gl_map)
|
round_off_debit_credit(gl_map)
|
||||||
|
|
||||||
|
if gl_map:
|
||||||
|
check_freezing_date(gl_map[0]["posting_date"], adv_adj)
|
||||||
|
|
||||||
for entry in gl_map:
|
for entry in gl_map:
|
||||||
make_entry(entry, adv_adj, update_outstanding, from_repost)
|
make_entry(entry, adv_adj, update_outstanding)
|
||||||
|
|
||||||
# check against budget
|
# check against budget
|
||||||
if not from_repost:
|
validate_expense_against_budget(entry)
|
||||||
validate_expense_against_budget(entry)
|
|
||||||
|
|
||||||
if not from_repost:
|
validate_account_for_perpetual_inventory(gl_map)
|
||||||
validate_account_for_perpetual_inventory(gl_map)
|
|
||||||
|
|
||||||
|
|
||||||
def make_entry(args, adv_adj, update_outstanding, from_repost=False):
|
def make_entry(args, adv_adj, update_outstanding):
|
||||||
gle = frappe.new_doc("GL Entry")
|
gle = frappe.new_doc("GL Entry")
|
||||||
gle.update(args)
|
gle.update(args)
|
||||||
gle.flags.ignore_permissions = 1
|
gle.flags.ignore_permissions = 1
|
||||||
gle.flags.from_repost = from_repost
|
|
||||||
gle.validate()
|
gle.validate()
|
||||||
gle.db_insert()
|
gle.db_insert()
|
||||||
gle.run_method("on_update_with_args", adv_adj, update_outstanding, from_repost)
|
gle.run_method("on_update_with_args", adv_adj, update_outstanding)
|
||||||
gle.flags.ignore_validate = True
|
gle.flags.ignore_validate = True
|
||||||
gle.submit()
|
gle.submit()
|
||||||
|
|
||||||
|
# check against budget
|
||||||
|
validate_expense_against_budget(args)
|
||||||
|
|
||||||
def validate_account_for_perpetual_inventory(gl_map):
|
def validate_account_for_perpetual_inventory(gl_map):
|
||||||
if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)):
|
if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)):
|
||||||
account_list = [gl_entries.account for gl_entries in gl_map]
|
account_list = [gl_entries.account for gl_entries in gl_map]
|
||||||
@ -169,33 +172,33 @@ def validate_account_for_perpetual_inventory(gl_map):
|
|||||||
.format(account), StockAccountInvalidTransaction)
|
.format(account), StockAccountInvalidTransaction)
|
||||||
|
|
||||||
# This has been comment for a temporary, will add this code again on release of immutable ledger
|
# This has been comment for a temporary, will add this code again on release of immutable ledger
|
||||||
# elif account_bal != stock_bal:
|
elif account_bal != stock_bal:
|
||||||
# precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
|
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
|
||||||
# currency=frappe.get_cached_value('Company', gl_map[0].company, "default_currency"))
|
currency=frappe.get_cached_value('Company', gl_map[0].company, "default_currency"))
|
||||||
|
|
||||||
# diff = flt(stock_bal - account_bal, precision)
|
diff = flt(stock_bal - account_bal, precision)
|
||||||
# error_reason = _("Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.").format(
|
error_reason = _("Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.").format(
|
||||||
# stock_bal, account_bal, frappe.bold(account))
|
stock_bal, account_bal, frappe.bold(account))
|
||||||
# error_resolution = _("Please create adjustment Journal Entry for amount {0} ").format(frappe.bold(diff))
|
error_resolution = _("Please create adjustment Journal Entry for amount {0} ").format(frappe.bold(diff))
|
||||||
# stock_adjustment_account = frappe.db.get_value("Company",gl_map[0].company,"stock_adjustment_account")
|
stock_adjustment_account = frappe.db.get_value("Company",gl_map[0].company,"stock_adjustment_account")
|
||||||
|
|
||||||
# db_or_cr_warehouse_account =('credit_in_account_currency' if diff < 0 else 'debit_in_account_currency')
|
db_or_cr_warehouse_account =('credit_in_account_currency' if diff < 0 else 'debit_in_account_currency')
|
||||||
# db_or_cr_stock_adjustment_account = ('debit_in_account_currency' if diff < 0 else 'credit_in_account_currency')
|
db_or_cr_stock_adjustment_account = ('debit_in_account_currency' if diff < 0 else 'credit_in_account_currency')
|
||||||
|
|
||||||
# journal_entry_args = {
|
journal_entry_args = {
|
||||||
# 'accounts':[
|
'accounts':[
|
||||||
# {'account': account, db_or_cr_warehouse_account : abs(diff)},
|
{'account': account, db_or_cr_warehouse_account : abs(diff)},
|
||||||
# {'account': stock_adjustment_account, db_or_cr_stock_adjustment_account : abs(diff) }]
|
{'account': stock_adjustment_account, db_or_cr_stock_adjustment_account : abs(diff) }]
|
||||||
# }
|
}
|
||||||
|
|
||||||
# frappe.msgprint(msg="""{0}<br></br>{1}<br></br>""".format(error_reason, error_resolution),
|
frappe.msgprint(msg="""{0}<br></br>{1}<br></br>""".format(error_reason, error_resolution),
|
||||||
# raise_exception=StockValueAndAccountBalanceOutOfSync,
|
raise_exception=StockValueAndAccountBalanceOutOfSync,
|
||||||
# title=_('Values Out Of Sync'),
|
title=_('Values Out Of Sync'),
|
||||||
# primary_action={
|
primary_action={
|
||||||
# 'label': _('Make Journal Entry'),
|
'label': _('Make Journal Entry'),
|
||||||
# 'client_action': 'erpnext.route_to_adjustment_jv',
|
'client_action': 'erpnext.route_to_adjustment_jv',
|
||||||
# 'args': journal_entry_args
|
'args': journal_entry_args
|
||||||
# })
|
})
|
||||||
|
|
||||||
def validate_cwip_accounts(gl_map):
|
def validate_cwip_accounts(gl_map):
|
||||||
cwip_enabled = any([cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting")])
|
cwip_enabled = any([cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting")])
|
||||||
@ -282,31 +285,64 @@ def get_round_off_account_and_cost_center(company):
|
|||||||
|
|
||||||
return round_off_account, round_off_cost_center
|
return round_off_account, round_off_cost_center
|
||||||
|
|
||||||
def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
|
def make_reverse_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
|
||||||
adv_adj=False, update_outstanding="Yes"):
|
adv_adj=False, update_outstanding="Yes"):
|
||||||
|
"""
|
||||||
from erpnext.accounts.doctype.gl_entry.gl_entry import validate_balance_type, \
|
Get original gl entries of the voucher
|
||||||
check_freezing_date, update_outstanding_amt, validate_frozen_account
|
and make reverse gl entries by swapping debit and credit
|
||||||
|
"""
|
||||||
|
|
||||||
if not gl_entries:
|
if not gl_entries:
|
||||||
gl_entries = frappe.db.sql("""
|
gl_entries = frappe.get_all("GL Entry",
|
||||||
select account, posting_date, party_type, party, cost_center, fiscal_year,voucher_type,
|
fields = ["*"],
|
||||||
voucher_no, against_voucher_type, against_voucher, cost_center, company
|
filters = {
|
||||||
from `tabGL Entry`
|
"voucher_type": voucher_type,
|
||||||
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no), as_dict=True)
|
"voucher_no": voucher_no
|
||||||
|
})
|
||||||
|
|
||||||
if gl_entries:
|
if gl_entries:
|
||||||
|
set_as_cancel(gl_entries[0]['voucher_type'], gl_entries[0]['voucher_no'])
|
||||||
check_freezing_date(gl_entries[0]["posting_date"], adv_adj)
|
check_freezing_date(gl_entries[0]["posting_date"], adv_adj)
|
||||||
|
|
||||||
frappe.db.sql("""delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s""",
|
for entry in gl_entries:
|
||||||
(voucher_type or gl_entries[0]["voucher_type"], voucher_no or gl_entries[0]["voucher_no"]))
|
entry['name'] = None
|
||||||
|
debit = entry.get('debit', 0)
|
||||||
|
credit = entry.get('credit', 0)
|
||||||
|
|
||||||
for entry in gl_entries:
|
debit_in_account_currency = entry.get('debit_in_account_currency', 0)
|
||||||
validate_frozen_account(entry["account"], adv_adj)
|
credit_in_account_currency = entry.get('credit_in_account_currency', 0)
|
||||||
validate_balance_type(entry["account"], adv_adj)
|
|
||||||
if not adv_adj:
|
|
||||||
validate_expense_against_budget(entry)
|
|
||||||
|
|
||||||
if entry.get("against_voucher") and update_outstanding == 'Yes' and not adv_adj:
|
entry['debit'] = credit
|
||||||
update_outstanding_amt(entry["account"], entry.get("party_type"), entry.get("party"), entry.get("against_voucher_type"),
|
entry['credit'] = debit
|
||||||
entry.get("against_voucher"), on_cancel=True)
|
entry['debit_in_account_currency'] = credit_in_account_currency
|
||||||
|
entry['credit_in_account_currency'] = debit_in_account_currency
|
||||||
|
|
||||||
|
entry['remarks'] = "On cancellation of " + entry['voucher_no']
|
||||||
|
entry['is_cancelled'] = 1
|
||||||
|
entry['posting_date'] = today()
|
||||||
|
|
||||||
|
if entry['debit'] or entry['credit']:
|
||||||
|
make_entry(entry, adv_adj, "Yes")
|
||||||
|
|
||||||
|
|
||||||
|
def check_freezing_date(posting_date, adv_adj=False):
|
||||||
|
"""
|
||||||
|
Nobody can do GL Entries where posting date is before freezing date
|
||||||
|
except authorized person
|
||||||
|
"""
|
||||||
|
if not adv_adj:
|
||||||
|
acc_frozen_upto = frappe.db.get_value('Accounts Settings', None, 'acc_frozen_upto')
|
||||||
|
if acc_frozen_upto:
|
||||||
|
frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
|
||||||
|
if getdate(posting_date) <= getdate(acc_frozen_upto) \
|
||||||
|
and not frozen_accounts_modifier in frappe.get_roles():
|
||||||
|
frappe.throw(_("You are not authorized to add or update entries before {0}").format(formatdate(acc_frozen_upto)))
|
||||||
|
|
||||||
|
def set_as_cancel(voucher_type, voucher_no):
|
||||||
|
"""
|
||||||
|
Set is_cancelled=1 in all original gl entries for the voucher
|
||||||
|
"""
|
||||||
|
frappe.db.sql("""update `tabGL Entry` set is_cancelled = 1,
|
||||||
|
modified=%s, modified_by=%s
|
||||||
|
where voucher_type=%s and voucher_no=%s and is_cancelled = 0""",
|
||||||
|
(now(), frappe.session.user, voucher_type, voucher_no))
|
||||||
|
@ -154,8 +154,12 @@ frappe.query_reports["General Ledger"] = {
|
|||||||
{
|
{
|
||||||
"fieldname": "include_default_book_entries",
|
"fieldname": "include_default_book_entries",
|
||||||
"label": __("Include Default Book Entries"),
|
"label": __("Include Default Book Entries"),
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check"
|
||||||
"default": 1
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "show_cancelled_entries",
|
||||||
|
"label": __("Show Cancelled Entries"),
|
||||||
|
"fieldtype": "Check"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -188,6 +188,9 @@ def get_conditions(filters):
|
|||||||
else:
|
else:
|
||||||
conditions.append("finance_book in (%(finance_book)s)")
|
conditions.append("finance_book in (%(finance_book)s)")
|
||||||
|
|
||||||
|
if not filters.get("show_cancelled_entries"):
|
||||||
|
conditions.append("is_cancelled = 0")
|
||||||
|
|
||||||
from frappe.desk.reportview import build_match_conditions
|
from frappe.desk.reportview import build_match_conditions
|
||||||
match_conditions = build_match_conditions("GL Entry")
|
match_conditions = build_match_conditions("GL Entry")
|
||||||
|
|
||||||
|
@ -35,6 +35,12 @@ def execute(filters=None):
|
|||||||
})
|
})
|
||||||
return columns, data
|
return columns, data
|
||||||
|
|
||||||
|
# to avoid error eg: gross_income[0] : list index out of range
|
||||||
|
if not gross_income:
|
||||||
|
gross_income = [{}]
|
||||||
|
if not gross_expense:
|
||||||
|
gross_expense = [{}]
|
||||||
|
|
||||||
data.append({
|
data.append({
|
||||||
"account_name": "'" + _("Included in Gross Profit") + "'",
|
"account_name": "'" + _("Included in Gross Profit") + "'",
|
||||||
"account": "'" + _("Included in Gross Profit") + "'"
|
"account": "'" + _("Included in Gross Profit") + "'"
|
||||||
|
@ -102,7 +102,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
|||||||
|
|
||||||
data.append(row)
|
data.append(row)
|
||||||
|
|
||||||
if filters.get('group_by'):
|
if filters.get('group_by') and item_list:
|
||||||
total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
|
total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
|
||||||
total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
|
total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
|
||||||
data.append(total_row)
|
data.append(total_row)
|
||||||
|
@ -111,7 +111,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
|||||||
|
|
||||||
data.append(row)
|
data.append(row)
|
||||||
|
|
||||||
if filters.get('group_by'):
|
if filters.get('group_by') and item_list:
|
||||||
total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
|
total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
|
||||||
total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
|
total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
|
||||||
data.append(total_row)
|
data.append(total_row)
|
||||||
|
@ -817,48 +817,37 @@ def create_payment_gateway_account(gateway):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def update_number_field(doctype_name, name, field_name, number_value, company):
|
def update_cost_center(docname, cost_center_name, cost_center_number, company):
|
||||||
'''
|
'''
|
||||||
doctype_name = Name of the DocType
|
|
||||||
name = Docname being referred
|
|
||||||
field_name = Name of the field thats holding the 'number' attribute
|
|
||||||
number_value = Numeric value entered in field_name
|
|
||||||
|
|
||||||
Stores the number entered in the dialog to the DocType's field.
|
|
||||||
|
|
||||||
Renames the document by adding the number as a prefix to the current name and updates
|
Renames the document by adding the number as a prefix to the current name and updates
|
||||||
all transaction where it was present.
|
all transaction where it was present.
|
||||||
'''
|
'''
|
||||||
doc_title = frappe.db.get_value(doctype_name, name, frappe.scrub(doctype_name)+"_name")
|
validate_field_number("Cost Center", docname, cost_center_number, company, "cost_center_number")
|
||||||
|
|
||||||
validate_field_number(doctype_name, name, number_value, company, field_name)
|
if cost_center_number:
|
||||||
|
frappe.db.set_value("Cost Center", docname, "cost_center_number", cost_center_number.strip())
|
||||||
|
else:
|
||||||
|
frappe.db.set_value("Cost Center", docname, "cost_center_number", "")
|
||||||
|
|
||||||
frappe.db.set_value(doctype_name, name, field_name, number_value)
|
frappe.db.set_value("Cost Center", docname, "cost_center_name", cost_center_name.strip())
|
||||||
|
|
||||||
if doc_title[0].isdigit():
|
new_name = get_autoname_with_number(cost_center_number, cost_center_name, docname, company)
|
||||||
separator = " - " if " - " in doc_title else " "
|
if docname != new_name:
|
||||||
doc_title = doc_title.split(separator, 1)[1]
|
frappe.rename_doc("Cost Center", docname, new_name, force=1)
|
||||||
|
|
||||||
frappe.db.set_value(doctype_name, name, frappe.scrub(doctype_name)+"_name", doc_title)
|
|
||||||
|
|
||||||
new_name = get_autoname_with_number(number_value, doc_title, name, company)
|
|
||||||
|
|
||||||
if name != new_name:
|
|
||||||
frappe.rename_doc(doctype_name, name, new_name)
|
|
||||||
return new_name
|
return new_name
|
||||||
|
|
||||||
def validate_field_number(doctype_name, name, number_value, company, field_name):
|
def validate_field_number(doctype_name, docname, number_value, company, field_name):
|
||||||
''' Validate if the number entered isn't already assigned to some other document. '''
|
''' Validate if the number entered isn't already assigned to some other document. '''
|
||||||
if number_value:
|
if number_value:
|
||||||
|
filters = {field_name: number_value, "name": ["!=", docname]}
|
||||||
if company:
|
if company:
|
||||||
doctype_with_same_number = frappe.db.get_value(doctype_name,
|
filters["company"] = company
|
||||||
{field_name: number_value, "company": company, "name": ["!=", name]})
|
|
||||||
else:
|
doctype_with_same_number = frappe.db.get_value(doctype_name, filters)
|
||||||
doctype_with_same_number = frappe.db.get_value(doctype_name,
|
|
||||||
{field_name: number_value, "name": ["!=", name]})
|
|
||||||
if doctype_with_same_number:
|
if doctype_with_same_number:
|
||||||
frappe.throw(_("{0} Number {1} already used in account {2}")
|
frappe.throw(_("{0} Number {1} is already used in {2} {3}")
|
||||||
.format(doctype_name, number_value, doctype_with_same_number))
|
.format(doctype_name, number_value, doctype_name.lower(), doctype_with_same_number))
|
||||||
|
|
||||||
def get_autoname_with_number(number_value, doc_title, name, company):
|
def get_autoname_with_number(number_value, doc_title, name, company):
|
||||||
''' append title with prefix as number and suffix as company's abbreviation separated by '-' '''
|
''' append title with prefix as number and suffix as company's abbreviation separated by '-' '''
|
||||||
@ -897,4 +886,60 @@ def get_stock_accounts(company):
|
|||||||
return frappe.get_all("Account", filters = {
|
return frappe.get_all("Account", filters = {
|
||||||
"account_type": "Stock",
|
"account_type": "Stock",
|
||||||
"company": company
|
"company": company
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
|
||||||
|
warehouse_account=None, company=None):
|
||||||
|
def _delete_gl_entries(voucher_type, voucher_no):
|
||||||
|
frappe.db.sql("""delete from `tabGL Entry`
|
||||||
|
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
|
||||||
|
|
||||||
|
if not warehouse_account:
|
||||||
|
warehouse_account = get_warehouse_account_map(company)
|
||||||
|
|
||||||
|
future_stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items)
|
||||||
|
gle = get_voucherwise_gl_entries(future_stock_vouchers, posting_date)
|
||||||
|
|
||||||
|
for voucher_type, voucher_no in future_stock_vouchers:
|
||||||
|
existing_gle = gle.get((voucher_type, voucher_no), [])
|
||||||
|
voucher_obj = frappe.get_doc(voucher_type, voucher_no)
|
||||||
|
expected_gle = voucher_obj.get_gl_entries(warehouse_account)
|
||||||
|
if expected_gle:
|
||||||
|
if not existing_gle or not compare_existing_and_expected_gle(existing_gle, expected_gle):
|
||||||
|
_delete_gl_entries(voucher_type, voucher_no)
|
||||||
|
voucher_obj.make_gl_entries(gl_entries=expected_gle, repost_future_gle=False, from_repost=True)
|
||||||
|
else:
|
||||||
|
_delete_gl_entries(voucher_type, voucher_no)
|
||||||
|
|
||||||
|
def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, for_items=None):
|
||||||
|
future_stock_vouchers = []
|
||||||
|
|
||||||
|
values = []
|
||||||
|
condition = ""
|
||||||
|
if for_items:
|
||||||
|
condition += " and item_code in ({})".format(", ".join(["%s"] * len(for_items)))
|
||||||
|
values += for_items
|
||||||
|
|
||||||
|
if for_warehouses:
|
||||||
|
condition += " and warehouse in ({})".format(", ".join(["%s"] * len(for_warehouses)))
|
||||||
|
values += for_warehouses
|
||||||
|
|
||||||
|
for d in frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
|
||||||
|
from `tabStock Ledger Entry` sle
|
||||||
|
where timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s) {condition}
|
||||||
|
order by timestamp(sle.posting_date, sle.posting_time) asc, creation asc for update""".format(condition=condition),
|
||||||
|
tuple([posting_date, posting_time] + values), as_dict=True):
|
||||||
|
future_stock_vouchers.append([d.voucher_type, d.voucher_no])
|
||||||
|
|
||||||
|
return future_stock_vouchers
|
||||||
|
|
||||||
|
def get_voucherwise_gl_entries(future_stock_vouchers, posting_date):
|
||||||
|
gl_entries = {}
|
||||||
|
if future_stock_vouchers:
|
||||||
|
for d in frappe.db.sql("""select * from `tabGL Entry`
|
||||||
|
where posting_date >= %s and voucher_no in (%s)""" %
|
||||||
|
('%s', ', '.join(['%s']*len(future_stock_vouchers))),
|
||||||
|
tuple([posting_date] + [d[1] for d in future_stock_vouchers]), as_dict=1):
|
||||||
|
gl_entries.setdefault((d.voucher_type, d.voucher_no), []).append(d)
|
||||||
|
|
||||||
|
return gl_entries
|
@ -11,7 +11,7 @@ from frappe.model.document import Document
|
|||||||
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
|
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
|
||||||
from erpnext.assets.doctype.asset.depreciation \
|
from erpnext.assets.doctype.asset.depreciation \
|
||||||
import get_disposal_account_and_cost_center, get_depreciation_accounts
|
import get_disposal_account_and_cost_center, get_depreciation_accounts
|
||||||
from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries
|
from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries
|
||||||
from erpnext.accounts.utils import get_account_currency
|
from erpnext.accounts.utils import get_account_currency
|
||||||
from erpnext.controllers.accounts_controller import AccountsController
|
from erpnext.controllers.accounts_controller import AccountsController
|
||||||
|
|
||||||
@ -41,7 +41,8 @@ class Asset(AccountsController):
|
|||||||
self.validate_cancellation()
|
self.validate_cancellation()
|
||||||
self.delete_depreciation_entries()
|
self.delete_depreciation_entries()
|
||||||
self.set_status()
|
self.set_status()
|
||||||
delete_gl_entries(voucher_type='Asset', voucher_no=self.name)
|
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
|
||||||
|
make_reverse_gl_entries(voucher_type='Asset', voucher_no=self.name)
|
||||||
self.db_set('booked_fixed_asset', 0)
|
self.db_set('booked_fixed_asset', 0)
|
||||||
|
|
||||||
def validate_asset_and_reference(self):
|
def validate_asset_and_reference(self):
|
||||||
|
@ -66,9 +66,6 @@ class TestAsset(unittest.TestCase):
|
|||||||
pr.cancel()
|
pr.cancel()
|
||||||
self.assertEqual(asset.docstatus, 2)
|
self.assertEqual(asset.docstatus, 2)
|
||||||
|
|
||||||
self.assertFalse(frappe.db.get_value("GL Entry",
|
|
||||||
{"voucher_type": "Purchase Invoice", "voucher_no": pi.name}))
|
|
||||||
|
|
||||||
def test_is_fixed_asset_set(self):
|
def test_is_fixed_asset_set(self):
|
||||||
asset = create_asset(is_existing_asset = 1)
|
asset = create_asset(is_existing_asset = 1)
|
||||||
doc = frappe.new_doc('Purchase Invoice')
|
doc = frappe.new_doc('Purchase Invoice')
|
||||||
|
@ -11,7 +11,8 @@ from frappe.model.document import Document
|
|||||||
class AssetCategory(Document):
|
class AssetCategory(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_finance_books()
|
self.validate_finance_books()
|
||||||
self.validate_accounts()
|
self.validate_account_types()
|
||||||
|
self.validate_account_currency()
|
||||||
|
|
||||||
def validate_finance_books(self):
|
def validate_finance_books(self):
|
||||||
for d in self.finance_books:
|
for d in self.finance_books:
|
||||||
@ -19,7 +20,26 @@ class AssetCategory(Document):
|
|||||||
if cint(d.get(frappe.scrub(field)))<1:
|
if cint(d.get(frappe.scrub(field)))<1:
|
||||||
frappe.throw(_("Row {0}: {1} must be greater than 0").format(d.idx, field), frappe.MandatoryError)
|
frappe.throw(_("Row {0}: {1} must be greater than 0").format(d.idx, field), frappe.MandatoryError)
|
||||||
|
|
||||||
def validate_accounts(self):
|
def validate_account_currency(self):
|
||||||
|
account_types = [
|
||||||
|
'fixed_asset_account', 'accumulated_depreciation_account', 'depreciation_expense_account', 'capital_work_in_progress_account'
|
||||||
|
]
|
||||||
|
invalid_accounts = []
|
||||||
|
for d in self.accounts:
|
||||||
|
company_currency = frappe.get_value('Company', d.get('company_name'), 'default_currency')
|
||||||
|
for type_of_account in account_types:
|
||||||
|
if d.get(type_of_account):
|
||||||
|
account_currency = frappe.get_value("Account", d.get(type_of_account), "account_currency")
|
||||||
|
if account_currency != company_currency:
|
||||||
|
invalid_accounts.append(frappe._dict({ 'type': type_of_account, 'idx': d.idx, 'account': d.get(type_of_account) }))
|
||||||
|
|
||||||
|
for d in invalid_accounts:
|
||||||
|
frappe.throw(_("Row #{}: Currency of {} - {} doesn't matches company currency.")
|
||||||
|
.format(d.idx, frappe.bold(frappe.unscrub(d.type)), frappe.bold(d.account)),
|
||||||
|
title=_("Invalid Account"))
|
||||||
|
|
||||||
|
|
||||||
|
def validate_account_types(self):
|
||||||
account_type_map = {
|
account_type_map = {
|
||||||
'fixed_asset_account': { 'account_type': 'Fixed Asset' },
|
'fixed_asset_account': { 'account_type': 'Fixed Asset' },
|
||||||
'accumulated_depreciation_account': { 'account_type': 'Accumulated Depreciation' },
|
'accumulated_depreciation_account': { 'account_type': 'Accumulated Depreciation' },
|
||||||
|
@ -23,15 +23,11 @@ def get_data():
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Payments'),
|
'label': _('Payments'),
|
||||||
'items': ['Payment Entry']
|
'items': ['Payment Entry', 'Bank Account']
|
||||||
},
|
|
||||||
{
|
|
||||||
'label': _('Bank'),
|
|
||||||
'items': ['Bank Account']
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Pricing'),
|
'label': _('Pricing'),
|
||||||
'items': ['Pricing Rule']
|
'items': ['Pricing Rule']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -183,8 +183,8 @@ def get_data():
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"label": _("Update Bank Transaction Dates"),
|
"label": _("Update Bank Clearance Dates"),
|
||||||
"name": "Bank Reconciliation",
|
"name": "Bank Clearance",
|
||||||
"description": _("Update bank payment dates with journals.")
|
"description": _("Update bank payment dates with journals.")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -170,6 +170,10 @@ def get_data():
|
|||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"name": "Payroll Period",
|
"name": "Payroll Period",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "doctype",
|
||||||
|
"name": "Income Tax Slab",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"name": "Salary Component",
|
"name": "Salary Component",
|
||||||
@ -209,6 +213,10 @@ def get_data():
|
|||||||
"name": "Employee Tax Exemption Proof Submission",
|
"name": "Employee Tax Exemption Proof Submission",
|
||||||
"dependencies": ["Employee"]
|
"dependencies": ["Employee"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "doctype",
|
||||||
|
"name": "Employee Other Income",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"name": "Employee Benefit Application",
|
"name": "Employee Benefit Application",
|
||||||
|
@ -664,23 +664,26 @@ class AccountsController(TransactionBase):
|
|||||||
def set_total_advance_paid(self):
|
def set_total_advance_paid(self):
|
||||||
if self.doctype == "Sales Order":
|
if self.doctype == "Sales Order":
|
||||||
dr_or_cr = "credit_in_account_currency"
|
dr_or_cr = "credit_in_account_currency"
|
||||||
|
rev_dr_or_cr = "debit_in_account_currency"
|
||||||
party = self.customer
|
party = self.customer
|
||||||
else:
|
else:
|
||||||
dr_or_cr = "debit_in_account_currency"
|
dr_or_cr = "debit_in_account_currency"
|
||||||
|
rev_dr_or_cr = "credit_in_account_currency"
|
||||||
party = self.supplier
|
party = self.supplier
|
||||||
|
|
||||||
advance = frappe.db.sql("""
|
advance = frappe.db.sql("""
|
||||||
select
|
select
|
||||||
account_currency, sum({dr_or_cr}) as amount
|
account_currency, sum({dr_or_cr}) - sum({rev_dr_cr}) as amount
|
||||||
from
|
from
|
||||||
`tabGL Entry`
|
`tabGL Entry`
|
||||||
where
|
where
|
||||||
against_voucher_type = %s and against_voucher = %s and party=%s
|
against_voucher_type = %s and against_voucher = %s and party=%s
|
||||||
and docstatus = 1
|
and docstatus = 1
|
||||||
""".format(dr_or_cr=dr_or_cr), (self.doctype, self.name, party), as_dict=1)
|
""".format(dr_or_cr=dr_or_cr, rev_dr_cr=rev_dr_or_cr), (self.doctype, self.name, party), as_dict=1) #nosec
|
||||||
|
|
||||||
if advance:
|
if advance:
|
||||||
advance = advance[0]
|
advance = advance[0]
|
||||||
|
|
||||||
advance_paid = flt(advance.amount, self.precision("advance_paid"))
|
advance_paid = flt(advance.amount, self.precision("advance_paid"))
|
||||||
formatted_advance_paid = fmt_money(advance_paid, precision=self.precision("advance_paid"),
|
formatted_advance_paid = fmt_money(advance_paid, precision=self.precision("advance_paid"),
|
||||||
currency=advance.account_currency)
|
currency=advance.account_currency)
|
||||||
|
@ -7,7 +7,7 @@ from frappe.utils import cint, flt, cstr, get_link_to_form, today, getdate
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
import frappe.defaults
|
import frappe.defaults
|
||||||
from erpnext.accounts.utils import get_fiscal_year
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries, process_gl_map
|
from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries, process_gl_map
|
||||||
from erpnext.controllers.accounts_controller import AccountsController
|
from erpnext.controllers.accounts_controller import AccountsController
|
||||||
from erpnext.stock.stock_ledger import get_valuation_rate
|
from erpnext.stock.stock_ledger import get_valuation_rate
|
||||||
from erpnext.stock import get_warehouse_account_map
|
from erpnext.stock import get_warehouse_account_map
|
||||||
@ -23,9 +23,9 @@ class StockController(AccountsController):
|
|||||||
self.validate_serialized_batch()
|
self.validate_serialized_batch()
|
||||||
self.validate_customer_provided_item()
|
self.validate_customer_provided_item()
|
||||||
|
|
||||||
def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
|
def make_gl_entries(self, gl_entries=None):
|
||||||
if self.docstatus == 2:
|
if self.docstatus == 2:
|
||||||
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
|
make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
|
||||||
|
|
||||||
if cint(erpnext.is_perpetual_inventory_enabled(self.company)):
|
if cint(erpnext.is_perpetual_inventory_enabled(self.company)):
|
||||||
warehouse_account = get_warehouse_account_map(self.company)
|
warehouse_account = get_warehouse_account_map(self.company)
|
||||||
@ -33,16 +33,12 @@ class StockController(AccountsController):
|
|||||||
if self.docstatus==1:
|
if self.docstatus==1:
|
||||||
if not gl_entries:
|
if not gl_entries:
|
||||||
gl_entries = self.get_gl_entries(warehouse_account)
|
gl_entries = self.get_gl_entries(warehouse_account)
|
||||||
make_gl_entries(gl_entries, from_repost=from_repost)
|
make_gl_entries(gl_entries)
|
||||||
|
|
||||||
if (repost_future_gle or self.flags.repost_future_gle):
|
|
||||||
items, warehouses = self.get_items_and_warehouses()
|
|
||||||
update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items,
|
|
||||||
warehouse_account, company=self.company)
|
|
||||||
elif self.doctype in ['Purchase Receipt', 'Purchase Invoice'] and self.docstatus == 1:
|
elif self.doctype in ['Purchase Receipt', 'Purchase Invoice'] and self.docstatus == 1:
|
||||||
gl_entries = []
|
gl_entries = []
|
||||||
gl_entries = self.get_asset_gl_entry(gl_entries)
|
gl_entries = self.get_asset_gl_entry(gl_entries)
|
||||||
make_gl_entries(gl_entries, from_repost=from_repost)
|
make_gl_entries(gl_entries)
|
||||||
|
|
||||||
def validate_serialized_batch(self):
|
def validate_serialized_batch(self):
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||||
@ -274,21 +270,21 @@ class StockController(AccountsController):
|
|||||||
"batch_no": cstr(d.get("batch_no")).strip(),
|
"batch_no": cstr(d.get("batch_no")).strip(),
|
||||||
"serial_no": d.get("serial_no"),
|
"serial_no": d.get("serial_no"),
|
||||||
"project": d.get("project") or self.get('project'),
|
"project": d.get("project") or self.get('project'),
|
||||||
"is_cancelled": self.docstatus==2 and "Yes" or "No"
|
"is_cancelled": 1 if self.docstatus==2 else 0
|
||||||
})
|
})
|
||||||
|
|
||||||
sl_dict.update(args)
|
sl_dict.update(args)
|
||||||
return sl_dict
|
return sl_dict
|
||||||
|
|
||||||
def make_sl_entries(self, sl_entries, is_amended=None, allow_negative_stock=False,
|
def make_sl_entries(self, sl_entries, allow_negative_stock=False,
|
||||||
via_landed_cost_voucher=False):
|
via_landed_cost_voucher=False):
|
||||||
from erpnext.stock.stock_ledger import make_sl_entries
|
from erpnext.stock.stock_ledger import make_sl_entries
|
||||||
make_sl_entries(sl_entries, is_amended, allow_negative_stock, via_landed_cost_voucher)
|
make_sl_entries(sl_entries, allow_negative_stock, via_landed_cost_voucher)
|
||||||
|
|
||||||
def make_gl_entries_on_cancel(self, repost_future_gle=True):
|
def make_gl_entries_on_cancel(self):
|
||||||
if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s
|
if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s
|
||||||
and voucher_no=%s""", (self.doctype, self.name)):
|
and voucher_no=%s""", (self.doctype, self.name)):
|
||||||
self.make_gl_entries(repost_future_gle=repost_future_gle)
|
self.make_gl_entries()
|
||||||
|
|
||||||
def get_serialized_items(self):
|
def get_serialized_items(self):
|
||||||
serialized_items = []
|
serialized_items = []
|
||||||
@ -391,29 +387,6 @@ class StockController(AccountsController):
|
|||||||
if frappe.db.get_value('Item', d.item_code, 'is_customer_provided_item'):
|
if frappe.db.get_value('Item', d.item_code, 'is_customer_provided_item'):
|
||||||
d.allow_zero_valuation_rate = 1
|
d.allow_zero_valuation_rate = 1
|
||||||
|
|
||||||
def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
|
|
||||||
warehouse_account=None, company=None):
|
|
||||||
def _delete_gl_entries(voucher_type, voucher_no):
|
|
||||||
frappe.db.sql("""delete from `tabGL Entry`
|
|
||||||
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
|
|
||||||
|
|
||||||
if not warehouse_account:
|
|
||||||
warehouse_account = get_warehouse_account_map(company)
|
|
||||||
|
|
||||||
future_stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items)
|
|
||||||
gle = get_voucherwise_gl_entries(future_stock_vouchers, posting_date)
|
|
||||||
|
|
||||||
for voucher_type, voucher_no in future_stock_vouchers:
|
|
||||||
existing_gle = gle.get((voucher_type, voucher_no), [])
|
|
||||||
voucher_obj = frappe.get_doc(voucher_type, voucher_no)
|
|
||||||
expected_gle = voucher_obj.get_gl_entries(warehouse_account)
|
|
||||||
if expected_gle:
|
|
||||||
if not existing_gle or not compare_existing_and_expected_gle(existing_gle, expected_gle):
|
|
||||||
_delete_gl_entries(voucher_type, voucher_no)
|
|
||||||
voucher_obj.make_gl_entries(gl_entries=expected_gle, repost_future_gle=False, from_repost=True)
|
|
||||||
else:
|
|
||||||
_delete_gl_entries(voucher_type, voucher_no)
|
|
||||||
|
|
||||||
def compare_existing_and_expected_gle(existing_gle, expected_gle):
|
def compare_existing_and_expected_gle(existing_gle, expected_gle):
|
||||||
matched = True
|
matched = True
|
||||||
for entry in expected_gle:
|
for entry in expected_gle:
|
||||||
@ -430,36 +403,3 @@ def compare_existing_and_expected_gle(existing_gle, expected_gle):
|
|||||||
matched = False
|
matched = False
|
||||||
break
|
break
|
||||||
return matched
|
return matched
|
||||||
|
|
||||||
def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, for_items=None):
|
|
||||||
future_stock_vouchers = []
|
|
||||||
|
|
||||||
values = []
|
|
||||||
condition = ""
|
|
||||||
if for_items:
|
|
||||||
condition += " and item_code in ({})".format(", ".join(["%s"] * len(for_items)))
|
|
||||||
values += for_items
|
|
||||||
|
|
||||||
if for_warehouses:
|
|
||||||
condition += " and warehouse in ({})".format(", ".join(["%s"] * len(for_warehouses)))
|
|
||||||
values += for_warehouses
|
|
||||||
|
|
||||||
for d in frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
|
|
||||||
from `tabStock Ledger Entry` sle
|
|
||||||
where timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s) {condition}
|
|
||||||
order by timestamp(sle.posting_date, sle.posting_time) asc, creation asc for update""".format(condition=condition),
|
|
||||||
tuple([posting_date, posting_time] + values), as_dict=True):
|
|
||||||
future_stock_vouchers.append([d.voucher_type, d.voucher_no])
|
|
||||||
|
|
||||||
return future_stock_vouchers
|
|
||||||
|
|
||||||
def get_voucherwise_gl_entries(future_stock_vouchers, posting_date):
|
|
||||||
gl_entries = {}
|
|
||||||
if future_stock_vouchers:
|
|
||||||
for d in frappe.db.sql("""select * from `tabGL Entry`
|
|
||||||
where posting_date >= %s and voucher_no in (%s)""" %
|
|
||||||
('%s', ', '.join(['%s']*len(future_stock_vouchers))),
|
|
||||||
tuple([posting_date] + [d[1] for d in future_stock_vouchers]), as_dict=1):
|
|
||||||
gl_entries.setdefault((d.voucher_type, d.voucher_no), []).append(d)
|
|
||||||
|
|
||||||
return gl_entries
|
|
||||||
|
24
erpnext/crm/utils.py
Normal file
24
erpnext/crm/utils.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def update_lead_phone_numbers(contact, method):
|
||||||
|
if contact.phone_nos:
|
||||||
|
contact_lead = contact.get_link_for("Lead")
|
||||||
|
if contact_lead:
|
||||||
|
phone = mobile_no = contact.phone_nos[0].phone
|
||||||
|
|
||||||
|
if len(contact.phone_nos) > 1:
|
||||||
|
# get the default phone number
|
||||||
|
primary_phones = [phone_doc.phone for phone_doc in contact.phone_nos if phone_doc.is_primary_phone]
|
||||||
|
if primary_phones:
|
||||||
|
phone = primary_phones[0]
|
||||||
|
|
||||||
|
# get the default mobile number
|
||||||
|
primary_mobile_nos = [phone_doc.phone for phone_doc in contact.phone_nos if phone_doc.is_primary_mobile_no]
|
||||||
|
if primary_mobile_nos:
|
||||||
|
mobile_no = primary_mobile_nos[0]
|
||||||
|
|
||||||
|
lead = frappe.get_doc("Lead", contact_lead)
|
||||||
|
lead.phone = phone
|
||||||
|
lead.mobile_no = mobile_no
|
||||||
|
lead.save()
|
@ -112,6 +112,8 @@ frappe.ui.form.on("Fees", {
|
|||||||
args: {
|
args: {
|
||||||
"dt": frm.doc.doctype,
|
"dt": frm.doc.doctype,
|
||||||
"dn": frm.doc.name,
|
"dn": frm.doc.name,
|
||||||
|
"party_type": "Student",
|
||||||
|
"party": frm.doc.student,
|
||||||
"recipient_id": frm.doc.student_email
|
"recipient_id": frm.doc.student_email
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
|
@ -10,7 +10,7 @@ from frappe.utils import money_in_words
|
|||||||
from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request
|
from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request
|
||||||
from frappe.utils.csvutils import getlink
|
from frappe.utils.csvutils import getlink
|
||||||
from erpnext.controllers.accounts_controller import AccountsController
|
from erpnext.controllers.accounts_controller import AccountsController
|
||||||
from erpnext.accounts.general_ledger import delete_gl_entries
|
from erpnext.accounts.general_ledger import make_reverse_gl_entries
|
||||||
|
|
||||||
|
|
||||||
class Fees(AccountsController):
|
class Fees(AccountsController):
|
||||||
@ -75,12 +75,14 @@ class Fees(AccountsController):
|
|||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
|
|
||||||
if self.send_payment_request and self.student_email:
|
if self.send_payment_request and self.student_email:
|
||||||
pr = make_payment_request(dt="Fees", dn=self.name, recipient_id=self.student_email,
|
pr = make_payment_request(party_type="Student", party=self.student, dt="Fees",
|
||||||
|
dn=self.name, recipient_id=self.student_email,
|
||||||
submit_doc=True, use_dummy_message=True)
|
submit_doc=True, use_dummy_message=True)
|
||||||
frappe.msgprint(_("Payment request {0} created").format(getlink("Payment Request", pr.name)))
|
frappe.msgprint(_("Payment request {0} created").format(getlink("Payment Request", pr.name)))
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
|
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
|
||||||
|
make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name, cancel=True)
|
||||||
# frappe.db.set(self, 'status', 'Cancelled')
|
# frappe.db.set(self, 'status', 'Cancelled')
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,6 +6,9 @@ def get_data():
|
|||||||
'heatmap': True,
|
'heatmap': True,
|
||||||
'heatmap_message': _('This is based on the attendance of this Student'),
|
'heatmap_message': _('This is based on the attendance of this Student'),
|
||||||
'fieldname': 'student',
|
'fieldname': 'student',
|
||||||
|
'non_standard_fieldnames': {
|
||||||
|
'Bank Account': 'party'
|
||||||
|
},
|
||||||
'transactions': [
|
'transactions': [
|
||||||
{
|
{
|
||||||
'label': _('Admission'),
|
'label': _('Admission'),
|
||||||
@ -29,7 +32,7 @@ def get_data():
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Fee'),
|
'label': _('Fee'),
|
||||||
'items': ['Fees']
|
'items': ['Fees', 'Bank Account']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
/* eslint-disable */
|
|
||||||
// rename this file from _test_[name] to test_[name] to activate
|
|
||||||
// and remove above this line
|
|
||||||
|
|
||||||
QUnit.test("test: Video", function (assert) {
|
|
||||||
let done = assert.async();
|
|
||||||
|
|
||||||
// number of asserts
|
|
||||||
assert.expect(1);
|
|
||||||
|
|
||||||
frappe.run_serially([
|
|
||||||
// insert a new Video
|
|
||||||
() => frappe.tests.make('Video', [
|
|
||||||
// values to be set
|
|
||||||
{key: 'value'}
|
|
||||||
]),
|
|
||||||
() => {
|
|
||||||
assert.equal(cur_frm.doc.key, 'value');
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
|
|
||||||
});
|
|
@ -1,10 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
class TestVideo(unittest.TestCase):
|
|
||||||
pass
|
|
@ -1,8 +0,0 @@
|
|||||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
// For license information, please see license.txt
|
|
||||||
|
|
||||||
frappe.ui.form.on('Video', {
|
|
||||||
refresh: function(frm) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,112 +0,0 @@
|
|||||||
{
|
|
||||||
"allow_import": 1,
|
|
||||||
"allow_rename": 1,
|
|
||||||
"autoname": "field:title",
|
|
||||||
"creation": "2018-10-17 05:47:13.087395",
|
|
||||||
"doctype": "DocType",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"field_order": [
|
|
||||||
"title",
|
|
||||||
"provider",
|
|
||||||
"url",
|
|
||||||
"column_break_4",
|
|
||||||
"publish_date",
|
|
||||||
"duration",
|
|
||||||
"section_break_7",
|
|
||||||
"description"
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldname": "title",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Title",
|
|
||||||
"reqd": 1,
|
|
||||||
"unique": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "description",
|
|
||||||
"fieldtype": "Text Editor",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Description",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "duration",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Duration"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "url",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "URL",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "publish_date",
|
|
||||||
"fieldtype": "Date",
|
|
||||||
"label": "Publish Date"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "provider",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Provider",
|
|
||||||
"options": "YouTube\nVimeo",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_4",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "section_break_7",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"modified": "2019-06-12 12:36:48.753092",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Education",
|
|
||||||
"name": "Video",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [
|
|
||||||
{
|
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "Academics User",
|
|
||||||
"share": 1,
|
|
||||||
"write": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "Instructor",
|
|
||||||
"share": 1,
|
|
||||||
"write": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "LMS User",
|
|
||||||
"share": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 1
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
class Video(Document):
|
|
||||||
|
|
||||||
|
|
||||||
def get_video(self):
|
|
||||||
pass
|
|
@ -80,6 +80,7 @@ frappe.ui.form.on('Clinical Procedure', {
|
|||||||
frappe.call({
|
frappe.call({
|
||||||
method: 'complete_procedure',
|
method: 'complete_procedure',
|
||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
|
freeze: true,
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if (r.message) {
|
if (r.message) {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
@ -87,8 +88,8 @@ frappe.ui.form.on('Clinical Procedure', {
|
|||||||
['<a class="bold" href="#Form/Stock Entry/'+ r.message + '">' + r.message + '</a>']),
|
['<a class="bold" href="#Form/Stock Entry/'+ r.message + '">' + r.message + '</a>']),
|
||||||
indicator: 'green'
|
indicator: 'green'
|
||||||
});
|
});
|
||||||
frm.reload_doc();
|
|
||||||
}
|
}
|
||||||
|
frm.reload_doc();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -111,9 +112,10 @@ frappe.ui.form.on('Clinical Procedure', {
|
|||||||
frappe.call({
|
frappe.call({
|
||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
method: 'make_material_receipt',
|
method: 'make_material_receipt',
|
||||||
|
freeze: true,
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if (!r.exc) {
|
if (!r.exc) {
|
||||||
cur_frm.reload_doc();
|
frm.reload_doc();
|
||||||
let doclist = frappe.model.sync(r.message);
|
let doclist = frappe.model.sync(r.message);
|
||||||
frappe.set_route('Form', doclist[0].doctype, doclist[0].name);
|
frappe.set_route('Form', doclist[0].doctype, doclist[0].name);
|
||||||
}
|
}
|
||||||
@ -122,7 +124,7 @@ frappe.ui.form.on('Clinical Procedure', {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
cur_frm.reload_doc();
|
frm.reload_doc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,8 @@ class ClinicalProcedure(Document):
|
|||||||
else:
|
else:
|
||||||
frappe.throw(_('Please set Customer in Patient {0}').format(frappe.bold(self.patient)), title=_('Customer Not Found'))
|
frappe.throw(_('Please set Customer in Patient {0}').format(frappe.bold(self.patient)), title=_('Customer Not Found'))
|
||||||
|
|
||||||
frappe.db.set_value('Clinical Procedure', self.name, 'status', 'Completed')
|
self.db_set('status', 'Completed')
|
||||||
|
|
||||||
if self.consume_stock and self.items:
|
if self.consume_stock and self.items:
|
||||||
return stock_entry
|
return stock_entry
|
||||||
|
|
||||||
@ -245,9 +246,9 @@ def make_procedure(source_name, target_doc=None):
|
|||||||
|
|
||||||
|
|
||||||
def insert_clinical_procedure_to_medical_record(doc):
|
def insert_clinical_procedure_to_medical_record(doc):
|
||||||
subject = cstr(doc.procedure_template)
|
subject = frappe.bold(_("Clinical Procedure conducted: ")) + cstr(doc.procedure_template) + "<br>"
|
||||||
if doc.practitioner:
|
if doc.practitioner:
|
||||||
subject += ' ' + doc.practitioner
|
subject += frappe.bold(_('Healthcare Practitioner: ')) + doc.practitioner
|
||||||
if subject and doc.notes:
|
if subject and doc.notes:
|
||||||
subject += '<br/>' + doc.notes
|
subject += '<br/>' + doc.notes
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ erpnext.ExerciseEditor = Class.extend({
|
|||||||
|
|
||||||
this.exercise_cards = $('<div class="exercise-cards"></div>').appendTo(this.wrapper);
|
this.exercise_cards = $('<div class="exercise-cards"></div>').appendTo(this.wrapper);
|
||||||
|
|
||||||
|
this.row = $('<div class="exercise-row"></div>').appendTo(this.wrapper);
|
||||||
|
|
||||||
let me = this;
|
let me = this;
|
||||||
|
|
||||||
this.exercise_toolbar.find(".btn-add")
|
this.exercise_toolbar.find(".btn-add")
|
||||||
@ -32,7 +34,7 @@ erpnext.ExerciseEditor = Class.extend({
|
|||||||
me.show_add_card_dialog(frm);
|
me.show_add_card_dialog(frm);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (frm.doc.steps_table.length > 0) {
|
if (frm.doc.steps_table && frm.doc.steps_table.length > 0) {
|
||||||
this.make_cards(frm);
|
this.make_cards(frm);
|
||||||
this.make_buttons(frm);
|
this.make_buttons(frm);
|
||||||
}
|
}
|
||||||
@ -41,7 +43,6 @@ erpnext.ExerciseEditor = Class.extend({
|
|||||||
make_cards: function(frm) {
|
make_cards: function(frm) {
|
||||||
var me = this;
|
var me = this;
|
||||||
$(me.exercise_cards).empty();
|
$(me.exercise_cards).empty();
|
||||||
this.row = $('<div class="exercise-row"></div>').appendTo(me.exercise_cards);
|
|
||||||
|
|
||||||
$.each(frm.doc.steps_table, function(i, step) {
|
$.each(frm.doc.steps_table, function(i, step) {
|
||||||
$(repl(`
|
$(repl(`
|
||||||
@ -78,6 +79,7 @@ erpnext.ExerciseEditor = Class.extend({
|
|||||||
frm.doc.steps_table.pop(id);
|
frm.doc.steps_table.pop(id);
|
||||||
frm.refresh_field('steps_table');
|
frm.refresh_field('steps_table');
|
||||||
$('#col-'+id).remove();
|
$('#col-'+id).remove();
|
||||||
|
frm.dirty();
|
||||||
}, 300);
|
}, 300);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -106,7 +108,10 @@ erpnext.ExerciseEditor = Class.extend({
|
|||||||
],
|
],
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
let data = d.get_values();
|
let data = d.get_values();
|
||||||
let i = frm.doc.steps_table.length;
|
let i = 0;
|
||||||
|
if (frm.doc.steps_table) {
|
||||||
|
i = frm.doc.steps_table.length;
|
||||||
|
}
|
||||||
$(repl(`
|
$(repl(`
|
||||||
<div class="exercise-col col-sm-4" id="%(col_id)s">
|
<div class="exercise-col col-sm-4" id="%(col_id)s">
|
||||||
<div class="card h-100 exercise-card" id="%(card_id)s">
|
<div class="card h-100 exercise-card" id="%(card_id)s">
|
||||||
@ -165,9 +170,10 @@ erpnext.ExerciseEditor = Class.extend({
|
|||||||
frm.doc.steps_table[id].image = data.image;
|
frm.doc.steps_table[id].image = data.image;
|
||||||
frm.doc.steps_table[id].description = data.step_description;
|
frm.doc.steps_table[id].description = data.step_description;
|
||||||
refresh_field('steps_table');
|
refresh_field('steps_table');
|
||||||
|
frm.dirty();
|
||||||
new_dialog.hide();
|
new_dialog.hide();
|
||||||
},
|
},
|
||||||
primary_action_label: __("Save"),
|
primary_action_label: __("Edit"),
|
||||||
});
|
});
|
||||||
|
|
||||||
new_dialog.set_values({
|
new_dialog.set_values({
|
||||||
|
@ -288,23 +288,23 @@ def insert_lab_test_to_medical_record(doc):
|
|||||||
table_row = False
|
table_row = False
|
||||||
subject = cstr(doc.lab_test_name)
|
subject = cstr(doc.lab_test_name)
|
||||||
if doc.practitioner:
|
if doc.practitioner:
|
||||||
subject += " "+ doc.practitioner
|
subject += frappe.bold(_("Healthcare Practitioner: "))+ doc.practitioner + "<br>"
|
||||||
if doc.normal_test_items:
|
if doc.normal_test_items:
|
||||||
item = doc.normal_test_items[0]
|
item = doc.normal_test_items[0]
|
||||||
comment = ""
|
comment = ""
|
||||||
if item.lab_test_comment:
|
if item.lab_test_comment:
|
||||||
comment = str(item.lab_test_comment)
|
comment = str(item.lab_test_comment)
|
||||||
table_row = item.lab_test_name
|
table_row = frappe.bold(_("Lab Test Conducted: ")) + item.lab_test_name
|
||||||
|
|
||||||
if item.lab_test_event:
|
if item.lab_test_event:
|
||||||
table_row += " " + item.lab_test_event
|
table_row += frappe.bold(_("Lab Test Event: ")) + item.lab_test_event
|
||||||
|
|
||||||
if item.result_value:
|
if item.result_value:
|
||||||
table_row += " " + item.result_value
|
table_row += " " + frappe.bold(_("Lab Test Result: ")) + item.result_value
|
||||||
|
|
||||||
if item.normal_range:
|
if item.normal_range:
|
||||||
table_row += " normal_range("+item.normal_range+")"
|
table_row += " " + _("Normal Range:") + item.normal_range
|
||||||
table_row += " "+comment
|
table_row += " " + comment
|
||||||
|
|
||||||
elif doc.special_test_items:
|
elif doc.special_test_items:
|
||||||
item = doc.special_test_items[0]
|
item = doc.special_test_items[0]
|
||||||
@ -316,12 +316,12 @@ def insert_lab_test_to_medical_record(doc):
|
|||||||
item = doc.sensitivity_test_items[0]
|
item = doc.sensitivity_test_items[0]
|
||||||
|
|
||||||
if item.antibiotic and item.antibiotic_sensitivity:
|
if item.antibiotic and item.antibiotic_sensitivity:
|
||||||
table_row = item.antibiotic +" "+ item.antibiotic_sensitivity
|
table_row = item.antibiotic + " " + item.antibiotic_sensitivity
|
||||||
|
|
||||||
if table_row:
|
if table_row:
|
||||||
subject += "<br/>"+table_row
|
subject += "<br>" + table_row
|
||||||
if doc.lab_test_comment:
|
if doc.lab_test_comment:
|
||||||
subject += "<br/>"+ cstr(doc.lab_test_comment)
|
subject += "<br>" + cstr(doc.lab_test_comment)
|
||||||
|
|
||||||
medical_record = frappe.new_doc("Patient Medical Record")
|
medical_record = frappe.new_doc("Patient Medical Record")
|
||||||
medical_record.patient = doc.patient
|
medical_record.patient = doc.patient
|
||||||
|
@ -18,6 +18,9 @@ class PatientEncounter(Document):
|
|||||||
def after_insert(self):
|
def after_insert(self):
|
||||||
insert_encounter_to_medical_record(self)
|
insert_encounter_to_medical_record(self)
|
||||||
|
|
||||||
|
def on_submit(self):
|
||||||
|
update_encounter_medical_record(self)
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
if self.appointment:
|
if self.appointment:
|
||||||
frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Open')
|
frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Open')
|
||||||
@ -66,22 +69,26 @@ def delete_medical_record(encounter):
|
|||||||
frappe.db.delete_doc_if_exists('Patient Medical Record', 'reference_name', encounter.name)
|
frappe.db.delete_doc_if_exists('Patient Medical Record', 'reference_name', encounter.name)
|
||||||
|
|
||||||
def set_subject_field(encounter):
|
def set_subject_field(encounter):
|
||||||
subject = encounter.practitioner + '\n'
|
subject = frappe.bold(_('Healthcare Practitioner: ')) + encounter.practitioner + '<br>'
|
||||||
if encounter.symptoms:
|
if encounter.symptoms:
|
||||||
subject += _('Symptoms: ') + cstr(encounter.symptoms) + '\n'
|
subject += frappe.bold(_('Symptoms: ')) + '<br>'
|
||||||
|
for entry in encounter.symptoms:
|
||||||
|
subject += cstr(entry.complaint) + '<br>'
|
||||||
else:
|
else:
|
||||||
subject += _('No Symptoms') + '\n'
|
subject += frappe.bold(_('No Symptoms')) + '<br>'
|
||||||
|
|
||||||
if encounter.diagnosis:
|
if encounter.diagnosis:
|
||||||
subject += _('Diagnosis: ') + cstr(encounter.diagnosis) + '\n'
|
subject += frappe.bold(_('Diagnosis: ')) + '<br>'
|
||||||
|
for entry in encounter.diagnosis:
|
||||||
|
subject += cstr(entry.diagnosis) + '<br>'
|
||||||
else:
|
else:
|
||||||
subject += _('No Diagnosis') + '\n'
|
subject += frappe.bold(_('No Diagnosis')) + '<br>'
|
||||||
|
|
||||||
if encounter.drug_prescription:
|
if encounter.drug_prescription:
|
||||||
subject += '\n' + _('Drug(s) Prescribed.')
|
subject += '<br>' + _('Drug(s) Prescribed.')
|
||||||
if encounter.lab_test_prescription:
|
if encounter.lab_test_prescription:
|
||||||
subject += '\n' + _('Test(s) Prescribed.')
|
subject += '<br>' + _('Test(s) Prescribed.')
|
||||||
if encounter.procedure_prescription:
|
if encounter.procedure_prescription:
|
||||||
subject += '\n' + _('Procedure(s) Prescribed.')
|
subject += '<br>' + _('Procedure(s) Prescribed.')
|
||||||
|
|
||||||
return subject
|
return subject
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "subject",
|
"fieldname": "subject",
|
||||||
"fieldtype": "Small Text",
|
"fieldtype": "Text Editor",
|
||||||
"ignore_xss_filter": 1,
|
"ignore_xss_filter": 1,
|
||||||
"label": "Subject"
|
"label": "Subject"
|
||||||
},
|
},
|
||||||
@ -125,7 +125,7 @@
|
|||||||
],
|
],
|
||||||
"in_create": 1,
|
"in_create": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-03-23 19:26:59.308383",
|
"modified": "2020-04-29 12:26:57.679402",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Healthcare",
|
"module": "Healthcare",
|
||||||
"name": "Patient Medical Record",
|
"name": "Patient Medical Record",
|
||||||
|
@ -21,8 +21,14 @@ class TherapyPlan(Document):
|
|||||||
self.status = 'Completed'
|
self.status = 'Completed'
|
||||||
|
|
||||||
def set_totals(self):
|
def set_totals(self):
|
||||||
total_sessions = sum([int(d.no_of_sessions) for d in self.get('therapy_plan_details')])
|
total_sessions = 0
|
||||||
total_sessions_completed = sum([int(d.sessions_completed) for d in self.get('therapy_plan_details')])
|
total_sessions_completed = 0
|
||||||
|
for entry in self.therapy_plan_details:
|
||||||
|
if entry.no_of_sessions:
|
||||||
|
total_sessions += entry.no_of_sessions
|
||||||
|
if entry.sessions_completed:
|
||||||
|
total_sessions_completed += entry.sessions_completed
|
||||||
|
|
||||||
self.db_set('total_sessions', total_sessions)
|
self.db_set('total_sessions', total_sessions)
|
||||||
self.db_set('total_sessions_completed', total_sessions_completed)
|
self.db_set('total_sessions_completed', total_sessions_completed)
|
||||||
|
|
||||||
|
@ -13,23 +13,92 @@ frappe.ui.form.on('Therapy Session', {
|
|||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if (!frm.doc.__islocal) {
|
if (!frm.doc.__islocal) {
|
||||||
let target = 0;
|
frm.dashboard.add_indicator(__('Counts Targeted: {0}', [frm.doc.total_counts_targeted]), 'blue');
|
||||||
let completed = 0;
|
frm.dashboard.add_indicator(__('Counts Completed: {0}', [frm.doc.total_counts_completed]),
|
||||||
$.each(frm.doc.exercises, function(_i, e) {
|
(frm.doc.total_counts_completed < frm.doc.total_counts_targeted) ? 'orange' : 'green');
|
||||||
target += e.counts_target;
|
|
||||||
completed += e.counts_completed;
|
|
||||||
});
|
|
||||||
frm.dashboard.add_indicator(__('Counts Targetted: {0}', [target]), 'blue');
|
|
||||||
frm.dashboard.add_indicator(__('Counts Completed: {0}', [completed]), (completed < target) ? 'orange' : 'green');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frm.doc.docstatus === 1) {
|
if (frm.doc.docstatus === 1) {
|
||||||
frm.add_custom_button(__('Patient Assessment'),function() {
|
frm.add_custom_button(__('Patient Assessment'), function() {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: 'erpnext.healthcare.doctype.patient_assessment.patient_assessment.create_patient_assessment',
|
method: 'erpnext.healthcare.doctype.patient_assessment.patient_assessment.create_patient_assessment',
|
||||||
frm: frm,
|
frm: frm,
|
||||||
})
|
})
|
||||||
}, 'Create');
|
}, 'Create');
|
||||||
|
|
||||||
|
frm.add_custom_button(__('Sales Invoice'), function() {
|
||||||
|
frappe.model.open_mapped_doc({
|
||||||
|
method: 'erpnext.healthcare.doctype.therapy_session.therapy_session.invoice_therapy_session',
|
||||||
|
frm: frm,
|
||||||
|
})
|
||||||
|
}, 'Create');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
patient: function(frm) {
|
||||||
|
if (frm.doc.patient) {
|
||||||
|
frappe.call({
|
||||||
|
'method': 'erpnext.healthcare.doctype.patient.patient.get_patient_detail',
|
||||||
|
args: {
|
||||||
|
patient: frm.doc.patient
|
||||||
|
},
|
||||||
|
callback: function (data) {
|
||||||
|
let age = '';
|
||||||
|
if (data.message.dob) {
|
||||||
|
age = calculate_age(data.message.dob);
|
||||||
|
} else if (data.message.age) {
|
||||||
|
age = data.message.age;
|
||||||
|
if (data.message.age_as_on) {
|
||||||
|
age = __('{0} as on {1}', [age, data.message.age_as_on]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frm.set_value('patient_age', age);
|
||||||
|
frm.set_value('gender', data.message.sex);
|
||||||
|
frm.set_value('patient_name', data.message.patient_name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
frm.set_value('patient_age', '');
|
||||||
|
frm.set_value('gender', '');
|
||||||
|
frm.set_value('patient_name', '');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
appointment: function(frm) {
|
||||||
|
if (frm.doc.appointment) {
|
||||||
|
frappe.call({
|
||||||
|
'method': 'frappe.client.get',
|
||||||
|
args: {
|
||||||
|
doctype: 'Patient Appointment',
|
||||||
|
name: frm.doc.appointment
|
||||||
|
},
|
||||||
|
callback: function(data) {
|
||||||
|
let values = {
|
||||||
|
'patient':data.message.patient,
|
||||||
|
'therapy_type': data.message.therapy_type,
|
||||||
|
'therapy_plan': data.message.therapy_plan,
|
||||||
|
'practitioner': data.message.practitioner,
|
||||||
|
'department': data.message.department,
|
||||||
|
'start_date': data.message.appointment_date,
|
||||||
|
'start_time': data.message.appointment_time,
|
||||||
|
'service_unit': data.message.service_unit,
|
||||||
|
'company': data.message.company
|
||||||
|
};
|
||||||
|
frm.set_value(values);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let values = {
|
||||||
|
'patient': '',
|
||||||
|
'therapy_type': '',
|
||||||
|
'therapy_plan': '',
|
||||||
|
'practitioner': '',
|
||||||
|
'department': '',
|
||||||
|
'start_date': '',
|
||||||
|
'start_time': '',
|
||||||
|
'service_unit': '',
|
||||||
|
};
|
||||||
|
frm.set_value(values);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -44,6 +113,8 @@ frappe.ui.form.on('Therapy Session', {
|
|||||||
callback: function(data) {
|
callback: function(data) {
|
||||||
frm.set_value('duration', data.message.default_duration);
|
frm.set_value('duration', data.message.default_duration);
|
||||||
frm.set_value('rate', data.message.rate);
|
frm.set_value('rate', data.message.rate);
|
||||||
|
frm.set_value('service_unit', data.message.healthcare_service_unit);
|
||||||
|
frm.set_value('department', data.message.medical_department);
|
||||||
frm.doc.exercises = [];
|
frm.doc.exercises = [];
|
||||||
$.each(data.message.exercises, function(_i, e) {
|
$.each(data.message.exercises, function(_i, e) {
|
||||||
let exercise = frm.add_child('exercises');
|
let exercise = frm.add_child('exercises');
|
||||||
|
@ -9,9 +9,11 @@
|
|||||||
"naming_series",
|
"naming_series",
|
||||||
"appointment",
|
"appointment",
|
||||||
"patient",
|
"patient",
|
||||||
|
"patient_name",
|
||||||
"patient_age",
|
"patient_age",
|
||||||
"gender",
|
"gender",
|
||||||
"column_break_5",
|
"column_break_5",
|
||||||
|
"company",
|
||||||
"therapy_plan",
|
"therapy_plan",
|
||||||
"therapy_type",
|
"therapy_type",
|
||||||
"practitioner",
|
"practitioner",
|
||||||
@ -20,7 +22,6 @@
|
|||||||
"duration",
|
"duration",
|
||||||
"rate",
|
"rate",
|
||||||
"location",
|
"location",
|
||||||
"company",
|
|
||||||
"column_break_12",
|
"column_break_12",
|
||||||
"service_unit",
|
"service_unit",
|
||||||
"start_date",
|
"start_date",
|
||||||
@ -28,6 +29,10 @@
|
|||||||
"invoiced",
|
"invoiced",
|
||||||
"exercises_section",
|
"exercises_section",
|
||||||
"exercises",
|
"exercises",
|
||||||
|
"section_break_23",
|
||||||
|
"total_counts_targeted",
|
||||||
|
"column_break_25",
|
||||||
|
"total_counts_completed",
|
||||||
"amended_from"
|
"amended_from"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
@ -159,7 +164,8 @@
|
|||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Company",
|
"label": "Company",
|
||||||
"options": "Company"
|
"options": "Company",
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
@ -173,11 +179,38 @@
|
|||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Patient Age",
|
"label": "Patient Age",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "total_counts_targeted",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"label": "Total Counts Targeted",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "total_counts_completed",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"label": "Total Counts Completed",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_23",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_25",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "patient.patient_name",
|
||||||
|
"fieldname": "patient_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Patient Name",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-21 13:16:46.378798",
|
"modified": "2020-04-29 16:49:16.286006",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Healthcare",
|
"module": "Healthcare",
|
||||||
"name": "Therapy Session",
|
"name": "Therapy Session",
|
||||||
|
@ -6,10 +6,17 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
|
from frappe import _
|
||||||
|
from frappe.utils import cstr, getdate
|
||||||
|
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account
|
||||||
|
|
||||||
class TherapySession(Document):
|
class TherapySession(Document):
|
||||||
|
def validate(self):
|
||||||
|
self.set_total_counts()
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.update_sessions_count_in_therapy_plan()
|
self.update_sessions_count_in_therapy_plan()
|
||||||
|
insert_session_medical_record(self)
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.update_sessions_count_in_therapy_plan(on_cancel=True)
|
self.update_sessions_count_in_therapy_plan(on_cancel=True)
|
||||||
@ -24,6 +31,18 @@ class TherapySession(Document):
|
|||||||
entry.sessions_completed += 1
|
entry.sessions_completed += 1
|
||||||
therapy_plan.save()
|
therapy_plan.save()
|
||||||
|
|
||||||
|
def set_total_counts(self):
|
||||||
|
target_total = 0
|
||||||
|
counts_completed = 0
|
||||||
|
for entry in self.exercises:
|
||||||
|
if entry.counts_target:
|
||||||
|
target_total += entry.counts_target
|
||||||
|
if entry.counts_completed:
|
||||||
|
counts_completed += entry.counts_completed
|
||||||
|
|
||||||
|
self.db_set('total_counts_targeted', target_total)
|
||||||
|
self.db_set('total_counts_completed', counts_completed)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def create_therapy_session(source_name, target_doc=None):
|
def create_therapy_session(source_name, target_doc=None):
|
||||||
@ -52,4 +71,62 @@ def create_therapy_session(source_name, target_doc=None):
|
|||||||
}
|
}
|
||||||
}, target_doc, set_missing_values)
|
}, target_doc, set_missing_values)
|
||||||
|
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def invoice_therapy_session(source_name, target_doc=None):
|
||||||
|
def set_missing_values(source, target):
|
||||||
|
target.customer = frappe.db.get_value('Patient', source.patient, 'customer')
|
||||||
|
target.due_date = getdate()
|
||||||
|
target.debit_to = get_receivable_account(source.company)
|
||||||
|
item = target.append('items', {})
|
||||||
|
item = get_therapy_item(source, item)
|
||||||
|
target.set_missing_values(for_validate=True)
|
||||||
|
|
||||||
|
doc = get_mapped_doc('Therapy Session', source_name, {
|
||||||
|
'Therapy Session': {
|
||||||
|
'doctype': 'Sales Invoice',
|
||||||
|
'field_map': [
|
||||||
|
['patient', 'patient'],
|
||||||
|
['referring_practitioner', 'practitioner'],
|
||||||
|
['company', 'company'],
|
||||||
|
['due_date', 'start_date']
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}, target_doc, set_missing_values)
|
||||||
|
|
||||||
|
return doc
|
||||||
|
|
||||||
|
|
||||||
|
def get_therapy_item(therapy, item):
|
||||||
|
item.item_code = frappe.db.get_value('Therapy Type', therapy.therapy_type, 'item')
|
||||||
|
item.description = _('Therapy Session Charges: {0}').format(therapy.practitioner)
|
||||||
|
item.income_account = get_income_account(therapy.practitioner, therapy.company)
|
||||||
|
item.cost_center = frappe.get_cached_value('Company', therapy.company, 'cost_center')
|
||||||
|
item.rate = therapy.rate
|
||||||
|
item.amount = therapy.rate
|
||||||
|
item.qty = 1
|
||||||
|
item.reference_dt = 'Therapy Session'
|
||||||
|
item.reference_dn = therapy.name
|
||||||
|
return item
|
||||||
|
|
||||||
|
|
||||||
|
def insert_session_medical_record(doc):
|
||||||
|
subject = frappe.bold(_('Therapy: ')) + cstr(doc.therapy_type) + '<br>'
|
||||||
|
if doc.therapy_plan:
|
||||||
|
subject += frappe.bold(_('Therapy Plan: ')) + cstr(doc.therapy_plan) + '<br>'
|
||||||
|
if doc.practitioner:
|
||||||
|
subject += frappe.bold(_('Healthcare Practitioner: ')) + doc.practitioner
|
||||||
|
subject += frappe.bold(_('Total Counts Targeted: ')) + cstr(doc.total_counts_targeted) + '<br>'
|
||||||
|
subject += frappe.bold(_('Total Counts Completed: ')) + cstr(doc.total_counts_completed) + '<br>'
|
||||||
|
|
||||||
|
medical_record = frappe.new_doc('Patient Medical Record')
|
||||||
|
medical_record.patient = doc.patient
|
||||||
|
medical_record.subject = subject
|
||||||
|
medical_record.status = 'Open'
|
||||||
|
medical_record.communication_date = doc.start_date
|
||||||
|
medical_record.reference_doctype = 'Therapy Session'
|
||||||
|
medical_record.reference_name = doc.name
|
||||||
|
medical_record.reference_owner = doc.owner
|
||||||
|
medical_record.save(ignore_permissions=True)
|
@ -35,17 +35,17 @@ def delete_vital_signs_from_medical_record(doc):
|
|||||||
|
|
||||||
def set_subject_field(doc):
|
def set_subject_field(doc):
|
||||||
subject = ''
|
subject = ''
|
||||||
if(doc.temperature):
|
if doc.temperature:
|
||||||
subject += _('Temperature: ') + '\n'+ cstr(doc.temperature) + '. '
|
subject += frappe.bold(_('Temperature: ')) + cstr(doc.temperature) + '<br>'
|
||||||
if(doc.pulse):
|
if doc.pulse:
|
||||||
subject += _('Pulse: ') + '\n' + cstr(doc.pulse) + '. '
|
subject += frappe.bold(_('Pulse: ')) + cstr(doc.pulse) + '<br>'
|
||||||
if(doc.respiratory_rate):
|
if doc.respiratory_rate:
|
||||||
subject += _('Respiratory Rate: ') + '\n' + cstr(doc.respiratory_rate) + '. '
|
subject += frappe.bold(_('Respiratory Rate: ')) + cstr(doc.respiratory_rate) + '<br>'
|
||||||
if(doc.bp):
|
if doc.bp:
|
||||||
subject += _('BP: ') + '\n' + cstr(doc.bp) + '. '
|
subject += frappe.bold(_('BP: ')) + cstr(doc.bp) + '<br>'
|
||||||
if(doc.bmi):
|
if doc.bmi:
|
||||||
subject += _('BMI: ') + '\n' + cstr(doc.bmi) + '. '
|
subject += frappe.bold(_('BMI: ')) + cstr(doc.bmi) + '<br>'
|
||||||
if(doc.nutrition_note):
|
if doc.nutrition_note:
|
||||||
subject += _('Note: ') + '\n' + cstr(doc.nutrition_note) + '. '
|
subject += frappe.bold(_('Note: ')) + cstr(doc.nutrition_note) + '<br>'
|
||||||
|
|
||||||
return subject
|
return subject
|
||||||
|
@ -250,7 +250,8 @@ doc_events = {
|
|||||||
},
|
},
|
||||||
"Contact": {
|
"Contact": {
|
||||||
"on_trash": "erpnext.support.doctype.issue.issue.update_issue",
|
"on_trash": "erpnext.support.doctype.issue.issue.update_issue",
|
||||||
"after_insert": "erpnext.communication.doctype.call_log.call_log.set_caller_information"
|
"after_insert": "erpnext.communication.doctype.call_log.call_log.set_caller_information",
|
||||||
|
"validate": "erpnext.crm.utils.update_lead_phone_numbers"
|
||||||
},
|
},
|
||||||
"Lead": {
|
"Lead": {
|
||||||
"after_insert": "erpnext.communication.doctype.call_log.call_log.set_caller_information"
|
"after_insert": "erpnext.communication.doctype.call_log.call_log.set_caller_information"
|
||||||
@ -537,4 +538,4 @@ global_search_doctypes = {
|
|||||||
{'doctype': 'Hotel Room Package', 'index': 3},
|
{'doctype': 'Hotel Room Package', 'index': 3},
|
||||||
{'doctype': 'Hotel Room Type', 'index': 4}
|
{'doctype': 'Hotel Room Type', 'index': 4}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"label": "Payroll",
|
"label": "Payroll",
|
||||||
"links": "[\n {\n \"label\": \"Salary Structure\",\n \"name\": \"Salary Structure\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Salary Structure\",\n \"Employee\"\n ],\n \"label\": \"Salary Structure Assignment\",\n \"name\": \"Salary Structure Assignment\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Payroll Entry\",\n \"name\": \"Payroll Entry\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Salary Slip\",\n \"name\": \"Salary Slip\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Payroll Period\",\n \"name\": \"Payroll Period\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Salary Component\",\n \"name\": \"Salary Component\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Additional Salary\",\n \"name\": \"Additional Salary\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Retention Bonus\",\n \"name\": \"Retention Bonus\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Incentive\",\n \"name\": \"Employee Incentive\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Salary Slip\"\n ],\n \"doctype\": \"Salary Slip\",\n \"is_query_report\": true,\n \"label\": \"Salary Register\",\n \"name\": \"Salary Register\",\n \"type\": \"report\"\n }\n]"
|
"links": "[\n {\n \"label\": \"Salary Structure\",\n \"name\": \"Salary Structure\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Salary Structure\",\n \"Employee\"\n ],\n \"label\": \"Salary Structure Assignment\",\n \"name\": \"Salary Structure Assignment\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Payroll Entry\",\n \"name\": \"Payroll Entry\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Salary Slip\",\n \"name\": \"Salary Slip\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Payroll Period\",\n \"name\": \"Payroll Period\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Income Tax Slab\",\n \"name\": \"Income Tax Slab\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Salary Component\",\n \"name\": \"Salary Component\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Additional Salary\",\n \"name\": \"Additional Salary\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Retention Bonus\",\n \"name\": \"Retention Bonus\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Incentive\",\n \"name\": \"Employee Incentive\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Salary Slip\"\n ],\n \"doctype\": \"Salary Slip\",\n \"is_query_report\": true,\n \"label\": \"Salary Register\",\n \"name\": \"Salary Register\",\n \"type\": \"report\"\n }\n]"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -73,7 +73,7 @@
|
|||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"label": "Employee Tax and Benefits",
|
"label": "Employee Tax and Benefits",
|
||||||
"links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Declaration\",\n \"name\": \"Employee Tax Exemption Declaration\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Proof Submission\",\n \"name\": \"Employee Tax Exemption Proof Submission\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Benefit Application\",\n \"name\": \"Employee Benefit Application\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Benefit Claim\",\n \"name\": \"Employee Benefit Claim\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Category\",\n \"name\": \"Employee Tax Exemption Category\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Sub Category\",\n \"name\": \"Employee Tax Exemption Sub Category\",\n \"type\": \"doctype\"\n }\n]"
|
"links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Declaration\",\n \"name\": \"Employee Tax Exemption Declaration\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Proof Submission\",\n \"name\": \"Employee Tax Exemption Proof Submission\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\",\n \"Payroll Period\"\n ],\n \"label\": \"Employee Other Income\",\n \"name\": \"Employee Other Income\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Benefit Application\",\n \"name\": \"Employee Benefit Application\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Benefit Claim\",\n \"name\": \"Employee Benefit Claim\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Category\",\n \"name\": \"Employee Tax Exemption Category\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Sub Category\",\n \"name\": \"Employee Tax Exemption Sub Category\",\n \"type\": \"doctype\"\n }\n]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"category": "Modules",
|
"category": "Modules",
|
||||||
@ -88,7 +88,7 @@
|
|||||||
"idx": 0,
|
"idx": 0,
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"label": "HR",
|
"label": "HR",
|
||||||
"modified": "2020-04-01 11:28:50.860012",
|
"modified": "2020-04-29 20:29:22.114309",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "HR",
|
"name": "HR",
|
||||||
|
@ -6,6 +6,9 @@ def get_data():
|
|||||||
'heatmap': True,
|
'heatmap': True,
|
||||||
'heatmap_message': _('This is based on the attendance of this Employee'),
|
'heatmap_message': _('This is based on the attendance of this Employee'),
|
||||||
'fieldname': 'employee',
|
'fieldname': 'employee',
|
||||||
|
'non_standard_fieldnames': {
|
||||||
|
'Bank Account': 'party'
|
||||||
|
},
|
||||||
'transactions': [
|
'transactions': [
|
||||||
{
|
{
|
||||||
'label': _('Leave and Attendance'),
|
'label': _('Leave and Attendance'),
|
||||||
@ -33,7 +36,7 @@ def get_data():
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Payroll'),
|
'label': _('Payroll'),
|
||||||
'items': ['Salary Structure Assignment', 'Salary Slip', 'Additional Salary', 'Timesheet','Employee Incentive', 'Retention Bonus']
|
'items': ['Salary Structure Assignment', 'Salary Slip', 'Additional Salary', 'Timesheet','Employee Incentive', 'Retention Bonus', 'Bank Account']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Training'),
|
'label': _('Training'),
|
||||||
|
@ -76,6 +76,7 @@ class ExpenseClaim(AccountsController):
|
|||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.update_task_and_project()
|
self.update_task_and_project()
|
||||||
|
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
|
||||||
if self.payable_account:
|
if self.payable_account:
|
||||||
self.make_gl_entries(cancel=True)
|
self.make_gl_entries(cancel=True)
|
||||||
|
|
||||||
@ -260,10 +261,17 @@ class ExpenseClaim(AccountsController):
|
|||||||
if not expense.default_account or not validate:
|
if not expense.default_account or not validate:
|
||||||
expense.default_account = get_expense_claim_account(expense.expense_type, self.company)["account"]
|
expense.default_account = get_expense_claim_account(expense.expense_type, self.company)["account"]
|
||||||
|
|
||||||
def update_reimbursed_amount(doc):
|
def update_reimbursed_amount(doc, jv=None):
|
||||||
amt = frappe.db.sql("""select ifnull(sum(debit_in_account_currency), 0) as amt
|
|
||||||
|
condition = ""
|
||||||
|
|
||||||
|
if jv:
|
||||||
|
condition += "and voucher_no = '{0}'".format(jv)
|
||||||
|
|
||||||
|
amt = frappe.db.sql("""select ifnull(sum(debit_in_account_currency), 0) - ifnull(sum(credit_in_account_currency), 0)as amt
|
||||||
from `tabGL Entry` where against_voucher_type = 'Expense Claim' and against_voucher = %s
|
from `tabGL Entry` where against_voucher_type = 'Expense Claim' and against_voucher = %s
|
||||||
and party = %s """, (doc.name, doc.employee) ,as_dict=1)[0].amt
|
and party = %s {condition}""".format(condition=condition), #nosec
|
||||||
|
(doc.name, doc.employee) ,as_dict=1)[0].amt
|
||||||
|
|
||||||
doc.total_amount_reimbursed = amt
|
doc.total_amount_reimbursed = amt
|
||||||
frappe.db.set_value("Expense Claim", doc.name , "total_amount_reimbursed", amt)
|
frappe.db.set_value("Expense Claim", doc.name , "total_amount_reimbursed", amt)
|
||||||
|
@ -80,6 +80,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
|
"collapsible_depends_on": "other_taxes_and_charges",
|
||||||
"fieldname": "taxes_and_charges_on_income_tax_section",
|
"fieldname": "taxes_and_charges_on_income_tax_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Taxes and Charges on Income Tax"
|
"label": "Taxes and Charges on Income Tax"
|
||||||
@ -93,13 +94,15 @@
|
|||||||
],
|
],
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-24 12:28:36.805904",
|
"modified": "2020-04-29 15:08:21.436120",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Income Tax Slab",
|
"name": "Income Tax Slab",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
|
"amend": 1,
|
||||||
|
"cancel": 1,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
@ -109,9 +112,11 @@
|
|||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"share": 1,
|
"share": 1,
|
||||||
|
"submit": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"amend": 1,
|
||||||
"cancel": 1,
|
"cancel": 1,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
@ -126,6 +131,7 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"amend": 1,
|
||||||
"cancel": 1,
|
"cancel": 1,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
@ -138,20 +144,6 @@
|
|||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 1,
|
"submit": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
|
||||||
{
|
|
||||||
"cancel": 1,
|
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "Administrator",
|
|
||||||
"share": 1,
|
|
||||||
"submit": 1,
|
|
||||||
"write": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
|
@ -249,7 +249,7 @@ const submit_salary_slip = function (frm) {
|
|||||||
|
|
||||||
let make_bank_entry = function (frm) {
|
let make_bank_entry = function (frm) {
|
||||||
var doc = frm.doc;
|
var doc = frm.doc;
|
||||||
if (doc.company && doc.start_date && doc.end_date && doc.payment_account) {
|
if (doc.payment_account) {
|
||||||
return frappe.call({
|
return frappe.call({
|
||||||
doc: cur_frm.doc,
|
doc: cur_frm.doc,
|
||||||
method: "make_payment_entry",
|
method: "make_payment_entry",
|
||||||
@ -262,7 +262,8 @@ let make_bank_entry = function (frm) {
|
|||||||
freeze_message: __("Creating Payment Entries......")
|
freeze_message: __("Creating Payment Entries......")
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint(__("Company, Payment Account, From Date and To Date is mandatory"));
|
frappe.msgprint(__("Payment Account is mandatory"));
|
||||||
|
frm.scroll_to_field('payment_account');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@
|
|||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"depends_on": "eval:doc.type == \"Deduction\" && !doc.variable_based_on_taxable_salary",
|
"depends_on": "eval:doc.type == \"Deduction\" && !doc.variable_based_on_taxable_salary",
|
||||||
"description": "If checked, the full amount will be deducted from taxable income before calculating income tax. Otherwise, it can be exempted via Employee Tax Exemption Declaration.",
|
"description": "If checked, the full amount will be deducted from taxable income before calculating income tax without any declaration or proof submission.",
|
||||||
"fieldname": "exempted_from_income_tax",
|
"fieldname": "exempted_from_income_tax",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Exempted from Income Tax"
|
"label": "Exempted from Income Tax"
|
||||||
@ -235,7 +235,7 @@
|
|||||||
],
|
],
|
||||||
"icon": "fa fa-flag",
|
"icon": "fa fa-flag",
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-24 14:50:28.994054",
|
"modified": "2020-04-28 15:46:45.252945",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Salary Component",
|
"name": "Salary Component",
|
||||||
|
@ -549,15 +549,16 @@ class SalarySlip(TransactionBase):
|
|||||||
remaining_sub_periods = get_period_factor(self.employee,
|
remaining_sub_periods = get_period_factor(self.employee,
|
||||||
self.start_date, self.end_date, self.payroll_frequency, payroll_period)[1]
|
self.start_date, self.end_date, self.payroll_frequency, payroll_period)[1]
|
||||||
# get taxable_earnings, paid_taxes for previous period
|
# get taxable_earnings, paid_taxes for previous period
|
||||||
previous_taxable_earnings = self.get_taxable_earnings_for_prev_period(payroll_period.start_date, self.start_date)
|
previous_taxable_earnings = self.get_taxable_earnings_for_prev_period(payroll_period.start_date,
|
||||||
|
self.start_date, tax_slab.allow_tax_exemption)
|
||||||
previous_total_paid_taxes = self.get_tax_paid_in_period(payroll_period.start_date, self.start_date, tax_component)
|
previous_total_paid_taxes = self.get_tax_paid_in_period(payroll_period.start_date, self.start_date, tax_component)
|
||||||
|
|
||||||
# get taxable_earnings for current period (all days)
|
# get taxable_earnings for current period (all days)
|
||||||
current_taxable_earnings = self.get_taxable_earnings()
|
current_taxable_earnings = self.get_taxable_earnings(tax_slab.allow_tax_exemption)
|
||||||
future_structured_taxable_earnings = current_taxable_earnings.taxable_earnings * (math.ceil(remaining_sub_periods) - 1)
|
future_structured_taxable_earnings = current_taxable_earnings.taxable_earnings * (math.ceil(remaining_sub_periods) - 1)
|
||||||
|
|
||||||
# get taxable_earnings, addition_earnings for current actual payment days
|
# get taxable_earnings, addition_earnings for current actual payment days
|
||||||
current_taxable_earnings_for_payment_days = self.get_taxable_earnings(based_on_payment_days=1)
|
current_taxable_earnings_for_payment_days = self.get_taxable_earnings(tax_slab.allow_tax_exemption, based_on_payment_days=1)
|
||||||
current_structured_taxable_earnings = current_taxable_earnings_for_payment_days.taxable_earnings
|
current_structured_taxable_earnings = current_taxable_earnings_for_payment_days.taxable_earnings
|
||||||
current_additional_earnings = current_taxable_earnings_for_payment_days.additional_income
|
current_additional_earnings = current_taxable_earnings_for_payment_days.additional_income
|
||||||
current_additional_earnings_with_full_tax = current_taxable_earnings_for_payment_days.additional_income_with_full_tax
|
current_additional_earnings_with_full_tax = current_taxable_earnings_for_payment_days.additional_income_with_full_tax
|
||||||
@ -616,7 +617,7 @@ class SalarySlip(TransactionBase):
|
|||||||
return income_tax_slab_doc
|
return income_tax_slab_doc
|
||||||
|
|
||||||
|
|
||||||
def get_taxable_earnings_for_prev_period(self, start_date, end_date):
|
def get_taxable_earnings_for_prev_period(self, start_date, end_date, allow_tax_exemption=False):
|
||||||
taxable_earnings = frappe.db.sql("""
|
taxable_earnings = frappe.db.sql("""
|
||||||
select sum(sd.amount)
|
select sum(sd.amount)
|
||||||
from
|
from
|
||||||
@ -636,24 +637,26 @@ class SalarySlip(TransactionBase):
|
|||||||
})
|
})
|
||||||
taxable_earnings = flt(taxable_earnings[0][0]) if taxable_earnings else 0
|
taxable_earnings = flt(taxable_earnings[0][0]) if taxable_earnings else 0
|
||||||
|
|
||||||
exempted_amount = frappe.db.sql("""
|
exempted_amount = 0
|
||||||
select sum(sd.amount)
|
if allow_tax_exemption:
|
||||||
from
|
exempted_amount = frappe.db.sql("""
|
||||||
`tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name
|
select sum(sd.amount)
|
||||||
where
|
from
|
||||||
sd.parentfield='deductions'
|
`tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name
|
||||||
and sd.exempted_from_income_tax=1
|
where
|
||||||
and is_flexible_benefit=0
|
sd.parentfield='deductions'
|
||||||
and ss.docstatus=1
|
and sd.exempted_from_income_tax=1
|
||||||
and ss.employee=%(employee)s
|
and is_flexible_benefit=0
|
||||||
and ss.start_date between %(from_date)s and %(to_date)s
|
and ss.docstatus=1
|
||||||
and ss.end_date between %(from_date)s and %(to_date)s
|
and ss.employee=%(employee)s
|
||||||
""", {
|
and ss.start_date between %(from_date)s and %(to_date)s
|
||||||
"employee": self.employee,
|
and ss.end_date between %(from_date)s and %(to_date)s
|
||||||
"from_date": start_date,
|
""", {
|
||||||
"to_date": end_date
|
"employee": self.employee,
|
||||||
})
|
"from_date": start_date,
|
||||||
exempted_amount = flt(exempted_amount[0][0]) if exempted_amount else 0
|
"to_date": end_date
|
||||||
|
})
|
||||||
|
exempted_amount = flt(exempted_amount[0][0]) if exempted_amount else 0
|
||||||
|
|
||||||
return taxable_earnings - exempted_amount
|
return taxable_earnings - exempted_amount
|
||||||
|
|
||||||
@ -681,7 +684,7 @@ class SalarySlip(TransactionBase):
|
|||||||
|
|
||||||
return total_tax_paid
|
return total_tax_paid
|
||||||
|
|
||||||
def get_taxable_earnings(self, based_on_payment_days=0):
|
def get_taxable_earnings(self, allow_tax_exemption=False, based_on_payment_days=0):
|
||||||
joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
|
joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
|
||||||
["date_of_joining", "relieving_date"])
|
["date_of_joining", "relieving_date"])
|
||||||
|
|
||||||
@ -715,12 +718,13 @@ class SalarySlip(TransactionBase):
|
|||||||
else:
|
else:
|
||||||
taxable_earnings += amount
|
taxable_earnings += amount
|
||||||
|
|
||||||
for ded in self.deductions:
|
if allow_tax_exemption:
|
||||||
if ded.exempted_from_income_tax:
|
for ded in self.deductions:
|
||||||
amount = ded.amount
|
if ded.exempted_from_income_tax:
|
||||||
if based_on_payment_days:
|
amount = ded.amount
|
||||||
amount = self.get_amount_based_on_payment_days(ded, joining_date, relieving_date)[0]
|
if based_on_payment_days:
|
||||||
taxable_earnings -= flt(amount)
|
amount = self.get_amount_based_on_payment_days(ded, joining_date, relieving_date)[0]
|
||||||
|
taxable_earnings -= flt(amount)
|
||||||
|
|
||||||
return frappe._dict({
|
return frappe._dict({
|
||||||
"taxable_earnings": taxable_earnings,
|
"taxable_earnings": taxable_earnings,
|
||||||
@ -822,13 +826,13 @@ class SalarySlip(TransactionBase):
|
|||||||
for slab in tax_slab.slabs:
|
for slab in tax_slab.slabs:
|
||||||
if slab.condition and not self.eval_tax_slab_condition(slab.condition, data):
|
if slab.condition and not self.eval_tax_slab_condition(slab.condition, data):
|
||||||
continue
|
continue
|
||||||
if not slab.to_amount and annual_taxable_earning > slab.from_amount:
|
if not slab.to_amount and annual_taxable_earning >= slab.from_amount:
|
||||||
tax_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01
|
tax_amount += (annual_taxable_earning - slab.from_amount + 1) * slab.percent_deduction *.01
|
||||||
continue
|
continue
|
||||||
if annual_taxable_earning > slab.from_amount and annual_taxable_earning < slab.to_amount:
|
if annual_taxable_earning >= slab.from_amount and annual_taxable_earning < slab.to_amount:
|
||||||
tax_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01
|
tax_amount += (annual_taxable_earning - slab.from_amount + 1) * slab.percent_deduction *.01
|
||||||
elif annual_taxable_earning > slab.from_amount and annual_taxable_earning > slab.to_amount:
|
elif annual_taxable_earning >= slab.from_amount and annual_taxable_earning >= slab.to_amount:
|
||||||
tax_amount += (slab.to_amount - slab.from_amount) * slab.percent_deduction * .01
|
tax_amount += (slab.to_amount - slab.from_amount + 1) * slab.percent_deduction * .01
|
||||||
|
|
||||||
# other taxes and charges on income tax
|
# other taxes and charges on income tax
|
||||||
for d in tax_slab.other_taxes_and_charges:
|
for d in tax_slab.other_taxes_and_charges:
|
||||||
|
@ -149,7 +149,7 @@ def get_existing_assignments(employees, salary_structure, from_date):
|
|||||||
return salary_structures_assignments
|
return salary_structures_assignments
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_salary_slip(source_name, target_doc = None, employee = None, as_print = False, print_format = None, for_preview=0):
|
def make_salary_slip(source_name, target_doc = None, employee = None, as_print = False, print_format = None, for_preview=0, ignore_permissions=False):
|
||||||
def postprocess(source, target):
|
def postprocess(source, target):
|
||||||
if employee:
|
if employee:
|
||||||
employee_details = frappe.db.get_value("Employee", employee,
|
employee_details = frappe.db.get_value("Employee", employee,
|
||||||
@ -169,7 +169,7 @@ def make_salary_slip(source_name, target_doc = None, employee = None, as_print =
|
|||||||
"name": "salary_structure"
|
"name": "salary_structure"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, target_doc, postprocess, ignore_child_tables=True)
|
}, target_doc, postprocess, ignore_child_tables=True, ignore_permissions=ignore_permissions)
|
||||||
|
|
||||||
if cint(as_print):
|
if cint(as_print):
|
||||||
doc.name = 'Preview for {0}'.format(employee)
|
doc.name = 'Preview for {0}'.format(employee)
|
||||||
|
@ -12,7 +12,8 @@ def execute(filters=None):
|
|||||||
columns, data, chart = [], [], []
|
columns, data, chart = [], [], []
|
||||||
if filters.get('fiscal_year'):
|
if filters.get('fiscal_year'):
|
||||||
company = erpnext.get_default_company()
|
company = erpnext.get_default_company()
|
||||||
period_list = get_period_list(filters.get('fiscal_year'), filters.get('fiscal_year'),"Monthly", company)
|
period_list = get_period_list(filters.get('fiscal_year'), filters.get('fiscal_year'),
|
||||||
|
'', '', 'Fiscal Year', 'Monthly', company=company)
|
||||||
columns=get_columns()
|
columns=get_columns()
|
||||||
data=get_log_data(filters)
|
data=get_log_data(filters)
|
||||||
chart=get_chart_data(data,period_list)
|
chart=get_chart_data(data,period_list)
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
"idx": 0,
|
"idx": 0,
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"label": "Loan Management",
|
"label": "Loan Management",
|
||||||
"modified": "2020-04-01 11:28:51.380509",
|
"modified": "2020-04-02 11:28:51.380509",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Loan Management",
|
"module": "Loan Management",
|
||||||
"name": "Loan Management",
|
"name": "Loan Management",
|
||||||
|
@ -236,7 +236,7 @@ class TestLoan(unittest.TestCase):
|
|||||||
|
|
||||||
process_loan_interest_accrual_for_term_loans(posting_date=nowdate())
|
process_loan_interest_accrual_for_term_loans(posting_date=nowdate())
|
||||||
|
|
||||||
repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(get_last_day(nowdate()), 5),
|
repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(nowdate(), 5),
|
||||||
"Regular Payment", 89768.75)
|
"Regular Payment", 89768.75)
|
||||||
|
|
||||||
repayment_entry.submit()
|
repayment_entry.submit()
|
||||||
|
@ -7,17 +7,17 @@
|
|||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"against_loan",
|
"against_loan",
|
||||||
"disbursement_date",
|
|
||||||
"posting_date",
|
"posting_date",
|
||||||
|
"applicant_type",
|
||||||
"column_break_4",
|
"column_break_4",
|
||||||
"company",
|
"company",
|
||||||
"applicant_type",
|
|
||||||
"applicant",
|
"applicant",
|
||||||
"section_break_7",
|
"section_break_7",
|
||||||
|
"disbursement_date",
|
||||||
|
"column_break_8",
|
||||||
"disbursed_amount",
|
"disbursed_amount",
|
||||||
"accounting_dimensions_section",
|
"accounting_dimensions_section",
|
||||||
"cost_center",
|
"cost_center",
|
||||||
"section_break_13",
|
|
||||||
"customer_details_section",
|
"customer_details_section",
|
||||||
"bank_account",
|
"bank_account",
|
||||||
"amended_from"
|
"amended_from"
|
||||||
@ -66,6 +66,7 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"collapsible": 1,
|
||||||
"fieldname": "accounting_dimensions_section",
|
"fieldname": "accounting_dimensions_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Accounting Dimensions"
|
"label": "Accounting Dimensions"
|
||||||
@ -89,12 +90,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_7",
|
"fieldname": "section_break_7",
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break",
|
||||||
},
|
"label": "Disbursement Details"
|
||||||
{
|
|
||||||
"collapsible": 1,
|
|
||||||
"fieldname": "section_break_13",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "customer_details_section",
|
"fieldname": "customer_details_section",
|
||||||
@ -114,11 +111,15 @@
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Bank Account",
|
"label": "Bank Account",
|
||||||
"options": "Bank Account"
|
"options": "Bank Account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_8",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-09 14:44:28.527271",
|
"modified": "2020-04-29 05:20:41.629911",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Loan Management",
|
"module": "Loan Management",
|
||||||
"name": "Loan Disbursement",
|
"name": "Loan Disbursement",
|
||||||
|
@ -106,6 +106,7 @@ class LoanRepayment(AccountsController):
|
|||||||
def allocate_amounts(self, paid_entries):
|
def allocate_amounts(self, paid_entries):
|
||||||
self.set('repayment_details', [])
|
self.set('repayment_details', [])
|
||||||
self.principal_amount_paid = 0
|
self.principal_amount_paid = 0
|
||||||
|
interest_paid = 0
|
||||||
|
|
||||||
if self.amount_paid - self.penalty_amount > 0 and paid_entries:
|
if self.amount_paid - self.penalty_amount > 0 and paid_entries:
|
||||||
interest_paid = self.amount_paid - self.penalty_amount
|
interest_paid = self.amount_paid - self.penalty_amount
|
||||||
@ -286,7 +287,11 @@ def get_amounts(amounts, against_loan, posting_date, payment_type):
|
|||||||
pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable
|
pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable
|
||||||
|
|
||||||
if payment_type == "Loan Closure" and not payable_principal_amount:
|
if payment_type == "Loan Closure" and not payable_principal_amount:
|
||||||
pending_days = date_diff(posting_date, entry.posting_date) + 1
|
if final_due_date:
|
||||||
|
pending_days = date_diff(posting_date, final_due_date)
|
||||||
|
else:
|
||||||
|
pending_days = date_diff(posting_date, against_loan_doc.disbursement_date) + 1
|
||||||
|
|
||||||
payable_principal_amount = pending_principal_amount
|
payable_principal_amount = pending_principal_amount
|
||||||
per_day_interest = (payable_principal_amount * (loan_type_details.rate_of_interest / 100))/365
|
per_day_interest = (payable_principal_amount * (loan_type_details.rate_of_interest / 100))/365
|
||||||
total_pending_interest += (pending_days * per_day_interest)
|
total_pending_interest += (pending_days * per_day_interest)
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"actions": [],
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
"autoname": "field:loan_security_name",
|
|
||||||
"creation": "2019-09-02 15:07:08.885593",
|
"creation": "2019-09-02 15:07:08.885593",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"loan_security_name",
|
"loan_security_name",
|
||||||
"unit_of_measure",
|
"haircut",
|
||||||
"loan_security_code",
|
"loan_security_code",
|
||||||
"column_break_3",
|
"column_break_3",
|
||||||
"loan_security_type",
|
"loan_security_type",
|
||||||
"haircut",
|
"unit_of_measure",
|
||||||
"disabled"
|
"disabled"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
@ -66,7 +65,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-28 14:07:54.506896",
|
"modified": "2020-04-29 13:21:26.043492",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Loan Management",
|
"module": "Loan Management",
|
||||||
"name": "Loan Security",
|
"name": "Loan Security",
|
||||||
|
@ -7,4 +7,5 @@ from __future__ import unicode_literals
|
|||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class LoanSecurity(Document):
|
class LoanSecurity(Document):
|
||||||
pass
|
def autoname(self):
|
||||||
|
self.name = self.loan_security_name
|
||||||
|
@ -62,9 +62,9 @@ class TestProductionPlan(unittest.TestCase):
|
|||||||
|
|
||||||
def test_production_plan_for_existing_ordered_qty(self):
|
def test_production_plan_for_existing_ordered_qty(self):
|
||||||
sr1 = create_stock_reconciliation(item_code="Raw Material Item 1",
|
sr1 = create_stock_reconciliation(item_code="Raw Material Item 1",
|
||||||
target="_Test Warehouse - _TC", qty=1, rate=100)
|
target="_Test Warehouse - _TC", qty=1, rate=110)
|
||||||
sr2 = create_stock_reconciliation(item_code="Raw Material Item 2",
|
sr2 = create_stock_reconciliation(item_code="Raw Material Item 2",
|
||||||
target="_Test Warehouse - _TC", qty=1, rate=100)
|
target="_Test Warehouse - _TC", qty=1, rate=120)
|
||||||
|
|
||||||
pln = create_production_plan(item_code='Test Production Item 1', ignore_existing_ordered_qty=0)
|
pln = create_production_plan(item_code='Test Production Item 1', ignore_existing_ordered_qty=0)
|
||||||
self.assertTrue(len(pln.mr_items), 1)
|
self.assertTrue(len(pln.mr_items), 1)
|
||||||
@ -86,9 +86,9 @@ class TestProductionPlan(unittest.TestCase):
|
|||||||
|
|
||||||
def test_production_plan_without_multi_level_for_existing_ordered_qty(self):
|
def test_production_plan_without_multi_level_for_existing_ordered_qty(self):
|
||||||
sr1 = create_stock_reconciliation(item_code="Raw Material Item 1",
|
sr1 = create_stock_reconciliation(item_code="Raw Material Item 1",
|
||||||
target="_Test Warehouse - _TC", qty=1, rate=100)
|
target="_Test Warehouse - _TC", qty=1, rate=130)
|
||||||
sr2 = create_stock_reconciliation(item_code="Subassembly Item 1",
|
sr2 = create_stock_reconciliation(item_code="Subassembly Item 1",
|
||||||
target="_Test Warehouse - _TC", qty=1, rate=100)
|
target="_Test Warehouse - _TC", qty=1, rate=140)
|
||||||
|
|
||||||
pln = create_production_plan(item_code='Test Production Item 1',
|
pln = create_production_plan(item_code='Test Production Item 1',
|
||||||
use_multi_level_bom=0, ignore_existing_ordered_qty=0)
|
use_multi_level_bom=0, ignore_existing_ordered_qty=0)
|
||||||
|
@ -6,10 +6,17 @@ def get_data():
|
|||||||
'heatmap': True,
|
'heatmap': True,
|
||||||
'heatmap_message': _('Member Activity'),
|
'heatmap_message': _('Member Activity'),
|
||||||
'fieldname': 'member',
|
'fieldname': 'member',
|
||||||
|
'non_standard_fieldnames': {
|
||||||
|
'Bank Account': 'party'
|
||||||
|
},
|
||||||
'transactions': [
|
'transactions': [
|
||||||
{
|
{
|
||||||
'label': _('Membership Details'),
|
'label': _('Membership Details'),
|
||||||
'items': ['Membership']
|
'items': ['Membership']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Fee'),
|
||||||
|
'items': ['Bank Account']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -62,11 +62,9 @@ def get_member_based_on_subscription(subscription_id, email):
|
|||||||
'subscription_id': subscription_id,
|
'subscription_id': subscription_id,
|
||||||
'email_id': email
|
'email_id': email
|
||||||
}, order_by="creation desc")
|
}, order_by="creation desc")
|
||||||
|
|
||||||
return frappe.get_doc("Member", members[0]['name'])
|
return frappe.get_doc("Member", members[0]['name'])
|
||||||
|
|
||||||
|
@frappe.whitelist(allow_guest=True)
|
||||||
@frappe.whitelist()
|
|
||||||
def trigger_razorpay_subscription(data):
|
def trigger_razorpay_subscription(data):
|
||||||
if isinstance(data, six.string_types):
|
if isinstance(data, six.string_types):
|
||||||
data = json.loads(data)
|
data = json.loads(data)
|
||||||
@ -88,10 +86,6 @@ def trigger_razorpay_subscription(data):
|
|||||||
|
|
||||||
if data.event == "subscription.activated":
|
if data.event == "subscription.activated":
|
||||||
member.customer_id = payment.customer_id
|
member.customer_id = payment.customer_id
|
||||||
member.subscription_start = datetime.fromtimestamp(subscription.start_at)
|
|
||||||
member.subscription_end = datetime.fromtimestamp(subscription.end_at)
|
|
||||||
member.subscription_activated = 1
|
|
||||||
member.save(ignore_permissions=True)
|
|
||||||
elif data.event == "subscription.charged":
|
elif data.event == "subscription.charged":
|
||||||
membership = frappe.new_doc("Membership")
|
membership = frappe.new_doc("Membership")
|
||||||
membership.update({
|
membership.update({
|
||||||
@ -108,6 +102,12 @@ def trigger_razorpay_subscription(data):
|
|||||||
})
|
})
|
||||||
membership.insert(ignore_permissions=True)
|
membership.insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
# Update these values anyway
|
||||||
|
member.subscription_start = datetime.fromtimestamp(subscription.start_at)
|
||||||
|
member.subscription_end = datetime.fromtimestamp(subscription.end_at)
|
||||||
|
member.subscription_activated = 1
|
||||||
|
member.save(ignore_permissions=True)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
execute:import unidecode # new requirement
|
execute:import unidecode # new requirement
|
||||||
erpnext.patches.v8_0.move_perpetual_inventory_setting
|
erpnext.patches.v8_0.move_perpetual_inventory_setting
|
||||||
erpnext.patches.v8_9.set_print_zero_amount_taxes
|
erpnext.patches.v8_9.set_print_zero_amount_taxes
|
||||||
|
erpnext.patches.v12_0.update_is_cancelled_field
|
||||||
erpnext.patches.v11_0.rename_production_order_to_work_order
|
erpnext.patches.v11_0.rename_production_order_to_work_order
|
||||||
erpnext.patches.v11_0.refactor_naming_series
|
erpnext.patches.v11_0.refactor_naming_series
|
||||||
erpnext.patches.v11_0.refactor_autoname_naming
|
erpnext.patches.v11_0.refactor_autoname_naming
|
||||||
@ -261,7 +262,6 @@ erpnext.patches.v6_19.comment_feed_communication
|
|||||||
erpnext.patches.v6_21.fix_reorder_level
|
erpnext.patches.v6_21.fix_reorder_level
|
||||||
erpnext.patches.v6_21.rename_material_request_fields
|
erpnext.patches.v6_21.rename_material_request_fields
|
||||||
erpnext.patches.v6_23.update_stopped_status_to_closed
|
erpnext.patches.v6_23.update_stopped_status_to_closed
|
||||||
erpnext.patches.v6_24.repost_valuation_rate_for_serialized_items
|
|
||||||
erpnext.patches.v6_24.set_recurring_id
|
erpnext.patches.v6_24.set_recurring_id
|
||||||
erpnext.patches.v6_20x.set_compact_print
|
erpnext.patches.v6_20x.set_compact_print
|
||||||
execute:frappe.delete_doc_if_exists("Web Form", "contact") #2016-03-10
|
execute:frappe.delete_doc_if_exists("Web Form", "contact") #2016-03-10
|
||||||
@ -315,7 +315,6 @@ erpnext.patches.v7_0.set_material_request_type_in_item
|
|||||||
erpnext.patches.v7_0.rename_examination_to_assessment
|
erpnext.patches.v7_0.rename_examination_to_assessment
|
||||||
erpnext.patches.v7_0.set_portal_settings
|
erpnext.patches.v7_0.set_portal_settings
|
||||||
erpnext.patches.v7_0.update_change_amount_account
|
erpnext.patches.v7_0.update_change_amount_account
|
||||||
erpnext.patches.v7_0.repost_future_gle_for_purchase_invoice
|
|
||||||
erpnext.patches.v7_0.fix_duplicate_icons
|
erpnext.patches.v7_0.fix_duplicate_icons
|
||||||
erpnext.patches.v7_0.repost_gle_for_pos_sales_return
|
erpnext.patches.v7_0.repost_gle_for_pos_sales_return
|
||||||
erpnext.patches.v7_1.update_total_billing_hours
|
erpnext.patches.v7_1.update_total_billing_hours
|
||||||
@ -660,6 +659,7 @@ erpnext.patches.v12_0.set_published_in_hub_tracked_item
|
|||||||
erpnext.patches.v12_0.set_job_offer_applicant_email
|
erpnext.patches.v12_0.set_job_offer_applicant_email
|
||||||
erpnext.patches.v12_0.create_irs_1099_field_united_states
|
erpnext.patches.v12_0.create_irs_1099_field_united_states
|
||||||
erpnext.patches.v12_0.move_bank_account_swift_number_to_bank
|
erpnext.patches.v12_0.move_bank_account_swift_number_to_bank
|
||||||
|
erpnext.patches.v12_0.rename_bank_reconciliation
|
||||||
erpnext.patches.v12_0.rename_bank_reconciliation_fields # 2020-01-22
|
erpnext.patches.v12_0.rename_bank_reconciliation_fields # 2020-01-22
|
||||||
erpnext.patches.v12_0.add_permission_in_lower_deduction
|
erpnext.patches.v12_0.add_permission_in_lower_deduction
|
||||||
erpnext.patches.v12_0.set_received_qty_in_material_request_as_per_stock_uom
|
erpnext.patches.v12_0.set_received_qty_in_material_request_as_per_stock_uom
|
||||||
@ -674,4 +674,5 @@ erpnext.patches.v12_0.repost_stock_ledger_entries_for_target_warehouse
|
|||||||
erpnext.patches.v12_0.update_end_date_and_status_in_email_campaign
|
erpnext.patches.v12_0.update_end_date_and_status_in_email_campaign
|
||||||
erpnext.patches.v13_0.move_tax_slabs_from_payroll_period_to_income_tax_slab #123
|
erpnext.patches.v13_0.move_tax_slabs_from_payroll_period_to_income_tax_slab #123
|
||||||
erpnext.patches.v12_0.fix_quotation_expired_status
|
erpnext.patches.v12_0.fix_quotation_expired_status
|
||||||
erpnext.patches.v12_0.update_appointment_reminder_scheduler_entry
|
erpnext.patches.v12_0.update_appointment_reminder_scheduler_entry
|
||||||
|
erpnext.patches.v12_0.retain_permission_rules_for_video_doctype
|
||||||
|
@ -24,9 +24,9 @@ def execute():
|
|||||||
doc = frappe.get_doc("Purchase Receipt", d.name)
|
doc = frappe.get_doc("Purchase Receipt", d.name)
|
||||||
|
|
||||||
doc.docstatus = 2
|
doc.docstatus = 2
|
||||||
doc.make_gl_entries_on_cancel(repost_future_gle=False)
|
doc.make_gl_entries_on_cancel()
|
||||||
|
|
||||||
|
|
||||||
# update gl entries for submit state of PR
|
# update gl entries for submit state of PR
|
||||||
doc.docstatus = 1
|
doc.docstatus = 1
|
||||||
doc.make_gl_entries(repost_future_gle=False)
|
doc.make_gl_entries()
|
||||||
|
@ -19,7 +19,7 @@ def execute():
|
|||||||
doc.db_update()
|
doc.db_update()
|
||||||
|
|
||||||
delete_gle_for_voucher(doc.name)
|
delete_gle_for_voucher(doc.name)
|
||||||
doc.make_gl_entries(repost_future_gle=False)
|
doc.make_gl_entries()
|
||||||
|
|
||||||
def delete_gle_for_voucher(voucher_no):
|
def delete_gle_for_voucher(voucher_no):
|
||||||
frappe.db.sql("""delete from `tabGL Entry` where voucher_no = %(voucher_no)s""",
|
frappe.db.sql("""delete from `tabGL Entry` where voucher_no = %(voucher_no)s""",
|
||||||
|
@ -5,4 +5,5 @@ import frappe
|
|||||||
from erpnext.setup.setup_wizard.operations.install_fixtures import add_dashboards
|
from erpnext.setup.setup_wizard.operations.install_fixtures import add_dashboards
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
|
frappe.reload_doc("desk", "doctype", "number_card_link")
|
||||||
add_dashboards()
|
add_dashboards()
|
||||||
|
@ -3,8 +3,11 @@ import frappe
|
|||||||
from erpnext.regional.united_states.setup import make_custom_fields
|
from erpnext.regional.united_states.setup import make_custom_fields
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
company = frappe.get_all('Company', filters = {'country': 'United States'})
|
|
||||||
if not company:
|
|
||||||
return
|
|
||||||
|
|
||||||
make_custom_fields()
|
frappe.reload_doc('accounts', 'doctype', 'allowed_to_transact_with', force=True)
|
||||||
|
|
||||||
|
company = frappe.get_all('Company', filters = {'country': 'United States'})
|
||||||
|
if not company:
|
||||||
|
return
|
||||||
|
|
||||||
|
make_custom_fields()
|
16
erpnext/patches/v12_0/rename_bank_reconciliation.py
Normal file
16
erpnext/patches/v12_0/rename_bank_reconciliation.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Copyright (c) 2018, Frappe and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
if frappe.db.table_exists("Bank Reconciliation"):
|
||||||
|
frappe.rename_doc('DocType', 'Bank Reconciliation', 'Bank Clearance', force=True)
|
||||||
|
frappe.reload_doc('Accounts', 'doctype', 'Bank Clearance')
|
||||||
|
|
||||||
|
frappe.rename_doc('DocType', 'Bank Reconciliation Detail', 'Bank Clearance Detail', force=True)
|
||||||
|
frappe.reload_doc('Accounts', 'doctype', 'Bank Clearance Detail')
|
||||||
|
|
||||||
|
frappe.delete_doc("DocType", "Bank Reconciliation")
|
||||||
|
frappe.delete_doc("DocType", "Bank Reconciliation Detail")
|
@ -9,6 +9,6 @@ def _rename_single_field(**kwargs):
|
|||||||
frappe.db.sql("UPDATE tabSingles SET field='{new_name}' WHERE doctype='{doctype}' AND field='{old_name}';".format(**kwargs)) #nosec
|
frappe.db.sql("UPDATE tabSingles SET field='{new_name}' WHERE doctype='{doctype}' AND field='{old_name}';".format(**kwargs)) #nosec
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
_rename_single_field(doctype = "Bank Reconciliation", old_name = "bank_account" , new_name = "account")
|
_rename_single_field(doctype = "Bank Clearance", old_name = "bank_account" , new_name = "account")
|
||||||
_rename_single_field(doctype = "Bank Reconciliation", old_name = "bank_account_no", new_name = "bank_account")
|
_rename_single_field(doctype = "Bank Clearance", old_name = "bank_account_no", new_name = "bank_account")
|
||||||
frappe.reload_doc("Accounts", "doctype", "Bank Reconciliation")
|
frappe.reload_doc("Accounts", "doctype", "Bank Clearance")
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
# to retain the roles and permissions from Education Module
|
||||||
|
# after moving doctype to core
|
||||||
|
permissions = frappe.db.sql("""
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
`tabDocPerm`
|
||||||
|
WHERE
|
||||||
|
parent='Video'
|
||||||
|
""", as_dict=True)
|
||||||
|
|
||||||
|
frappe.reload_doc('core', 'doctype', 'video')
|
||||||
|
doc = frappe.get_doc('DocType', 'Video')
|
||||||
|
doc.permissions = []
|
||||||
|
for perm in permissions:
|
||||||
|
doc.append('permissions', perm)
|
||||||
|
doc.save()
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user