Merge branch 'develop' into email-campaign
This commit is contained in:
commit
a566b4e24a
@ -121,7 +121,7 @@ frappe.treeview_settings["Account"] = {
|
||||
},
|
||||
onrender: function(node) {
|
||||
if(frappe.boot.user.can_read.indexOf("GL Entry") !== -1){
|
||||
var dr_or_cr = node.data.balance < 0 ? "Cr" : "Dr";
|
||||
var dr_or_cr = in_list(["Liability", "Income", "Equity"], node.data.root_type) ? "Cr" : "Dr";
|
||||
if (node.data && node.data.balance!==undefined) {
|
||||
$('<span class="balance-area pull-right text-muted small">'
|
||||
+ (node.data.balance_in_account_currency ?
|
||||
|
@ -10,6 +10,14 @@ frappe.ui.form.on('Accounting Dimension', {
|
||||
});
|
||||
}
|
||||
|
||||
frm.set_query('document_type', () => {
|
||||
return {
|
||||
filters: {
|
||||
name: ['not in', ['Accounting Dimension', 'Project', 'Cost Center']]
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
let button = frm.doc.disabled ? "Enable" : "Disable";
|
||||
|
||||
frm.add_custom_button(__(button), function() {
|
||||
@ -33,10 +41,10 @@ frappe.ui.form.on('Accounting Dimension', {
|
||||
|
||||
document_type: function(frm) {
|
||||
frm.set_value('label', frm.doc.document_type);
|
||||
frm.set_value('fieldname', frappe.scrub(frm.doc.document_type));
|
||||
frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type));
|
||||
|
||||
frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => {
|
||||
if (r.document_type) {
|
||||
if (r && r.document_type) {
|
||||
frm.set_df_property('document_type', 'description', "Document type is already set as dimension");
|
||||
}
|
||||
});
|
||||
|
@ -38,6 +38,7 @@
|
||||
"default": "0",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Disable",
|
||||
"read_only": 1
|
||||
},
|
||||
@ -54,7 +55,7 @@
|
||||
"label": "Mandatory For Profit and Loss Account"
|
||||
}
|
||||
],
|
||||
"modified": "2019-07-07 18:56:19.517450",
|
||||
"modified": "2019-07-14 17:25:01.307948",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounting Dimension",
|
||||
|
@ -155,7 +155,7 @@ def get_doctypes_with_dimensions():
|
||||
return doclist
|
||||
|
||||
def get_accounting_dimensions(as_list=True):
|
||||
accounting_dimensions = frappe.get_all("Accounting Dimension", fields=["label", "fieldname", "mandatory_for_pl", "mandatory_for_bs", "disabled"])
|
||||
accounting_dimensions = frappe.get_all("Accounting Dimension", fields=["label", "fieldname", "mandatory_for_pl", "mandatory_for_bs", "disabled"], filters={"disabled": 0})
|
||||
|
||||
if as_list:
|
||||
return [d.fieldname for d in accounting_dimensions]
|
||||
|
@ -10,6 +10,7 @@
|
||||
"acc_frozen_upto",
|
||||
"frozen_accounts_modifier",
|
||||
"determine_address_tax_category_from",
|
||||
"over_billing_allowance",
|
||||
"column_break_4",
|
||||
"credit_controller",
|
||||
"check_supplier_invoice_uniqueness",
|
||||
@ -168,12 +169,18 @@
|
||||
"fieldname": "automatically_fetch_payment_terms",
|
||||
"fieldtype": "Check",
|
||||
"label": "Automatically Fetch Payment Terms"
|
||||
},
|
||||
{
|
||||
"description": "Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.",
|
||||
"fieldname": "over_billing_allowance",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Over Billing Allowance (%)"
|
||||
}
|
||||
],
|
||||
"icon": "icon-cog",
|
||||
"idx": 1,
|
||||
"issingle": 1,
|
||||
"modified": "2019-04-28 18:20:55.789946",
|
||||
"modified": "2019-07-04 18:20:55.789946",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
|
@ -48,7 +48,10 @@ class BankAccount(Document):
|
||||
# Encode characters as numbers
|
||||
encoded = [encode_char(c) if ord(c) >= 65 and ord(c) <= 90 else c for c in flipped]
|
||||
|
||||
try:
|
||||
to_check = int(''.join(encoded))
|
||||
except ValueError:
|
||||
frappe.throw(_('IBAN is not valid'))
|
||||
|
||||
if to_check % 97 != 1:
|
||||
frappe.throw(_('IBAN is not valid'))
|
||||
|
@ -78,7 +78,6 @@ var validate_csv_data = function(frm) {
|
||||
|
||||
var create_import_button = function(frm) {
|
||||
frm.page.set_primary_action(__("Start Import"), function () {
|
||||
setup_progress_bar(frm);
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
|
||||
args: {
|
||||
@ -86,11 +85,11 @@ var create_import_button = function(frm) {
|
||||
company: frm.doc.company
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: __("Creating Accounts..."),
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
clearInterval(frm.page["interval"]);
|
||||
frm.page.set_indicator(__('Import Successfull'), 'blue');
|
||||
frappe.hide_progress();
|
||||
create_reset_button(frm);
|
||||
}
|
||||
}
|
||||
@ -126,13 +125,3 @@ var generate_tree_preview = function(frm) {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var setup_progress_bar = function(frm) {
|
||||
frm.page["seconds_elapsed"] = 0;
|
||||
frm.page["execution_time"] = (frm.page["total_accounts"] > 100) ? 100 : frm.page["total_accounts"];
|
||||
|
||||
frm.page["interval"] = setInterval(function() {
|
||||
frm.page["seconds_elapsed"] += 1;
|
||||
frappe.show_progress(__('Creating Accounts'), frm.page["seconds_elapsed"], frm.page["execution_time"]);
|
||||
}, 250);
|
||||
};
|
@ -33,6 +33,9 @@ def import_coa(file_name, company):
|
||||
|
||||
def generate_data_from_csv(file_name, as_dict=False):
|
||||
''' read csv file and return the generated nested tree '''
|
||||
if not file_name.endswith('.csv'):
|
||||
frappe.throw("Only CSV files can be used to for importing data. Please check the file format you are trying to upload")
|
||||
|
||||
file_doc = frappe.get_doc('File', {"file_url": file_name})
|
||||
file_path = file_doc.get_full_path()
|
||||
|
||||
@ -96,15 +99,27 @@ def build_forest(data):
|
||||
return [child] + return_parent(data, parent_account)
|
||||
|
||||
charts_map, paths = {}, []
|
||||
|
||||
line_no = 3
|
||||
error_messages = []
|
||||
|
||||
for i in data:
|
||||
account_name, _, account_number, is_group, account_type, root_type = i
|
||||
|
||||
if not account_name:
|
||||
error_messages.append("Row {0}: Please enter Account Name".format(line_no))
|
||||
|
||||
charts_map[account_name] = {}
|
||||
if is_group: charts_map[account_name]["is_group"] = is_group
|
||||
if is_group == 1: charts_map[account_name]["is_group"] = is_group
|
||||
if account_type: charts_map[account_name]["account_type"] = account_type
|
||||
if root_type: charts_map[account_name]["root_type"] = root_type
|
||||
if account_number: charts_map[account_name]["account_number"] = account_number
|
||||
path = return_parent(data, account_name)[::-1]
|
||||
paths.append(path) # List of path is created
|
||||
line_no += 1
|
||||
|
||||
if error_messages:
|
||||
frappe.throw("<br>".join(error_messages))
|
||||
|
||||
out = {}
|
||||
for path in paths:
|
||||
@ -150,22 +165,27 @@ def validate_root(accounts):
|
||||
if len(roots) < 4:
|
||||
return _("Number of root accounts cannot be less than 4")
|
||||
|
||||
error_messages = []
|
||||
|
||||
for account in roots:
|
||||
if not account.get("root_type"):
|
||||
return _("Please enter Root Type for - {0}").format(account.get("account_name"))
|
||||
elif account.get("root_type") not in ("Asset", "Liability", "Expense", "Income", "Equity"):
|
||||
return _('Root Type for "{0}" must be one of the Asset, Liability, Income, Expense and Equity').format(account.get("account_name"))
|
||||
if not account.get("root_type") and account.get("account_name"):
|
||||
error_messages.append("Please enter Root Type for account- {0}".format(account.get("account_name")))
|
||||
elif account.get("root_type") not in ("Asset", "Liability", "Expense", "Income", "Equity") and account.get("account_name"):
|
||||
error_messages.append("Root Type for {0} must be one of the Asset, Liability, Income, Expense and Equity".format(account.get("account_name")))
|
||||
|
||||
if error_messages:
|
||||
return "<br>".join(error_messages)
|
||||
|
||||
def validate_account_types(accounts):
|
||||
account_types_for_ledger = ["Cost of Goods Sold", "Depreciation", "Fixed Asset", "Payable", "Receivable", "Stock Adjustment"]
|
||||
account_types = [accounts[d]["account_type"] for d in accounts if not accounts[d]['is_group']]
|
||||
account_types = [accounts[d]["account_type"] for d in accounts if not accounts[d]['is_group'] == 1]
|
||||
|
||||
missing = list(set(account_types_for_ledger) - set(account_types))
|
||||
if missing:
|
||||
return _("Please identify/create Account (Ledger) for type - {0}").format(' , '.join(missing))
|
||||
|
||||
account_types_for_group = ["Bank", "Cash", "Stock"]
|
||||
account_groups = [accounts[d]["account_type"] for d in accounts if accounts[d]['is_group']]
|
||||
account_groups = [accounts[d]["account_type"] for d in accounts if accounts[d]['is_group'] not in ('', 1)]
|
||||
|
||||
missing = list(set(account_types_for_group) - set(account_groups))
|
||||
if missing:
|
||||
|
@ -1,177 +1,64 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2019-03-07 12:07:09.416101",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"sales_invoice",
|
||||
"customer",
|
||||
"column_break_3",
|
||||
"posting_date",
|
||||
"outstanding_amount"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sales_invoice",
|
||||
"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": "Invoice",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Sales Invoice",
|
||||
"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
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "sales_invoice.customer",
|
||||
"fieldname": "customer",
|
||||
"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": "Customer",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Customer",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"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
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "sales_invoice.posting_date",
|
||||
"fieldname": "posting_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": "Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"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
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "sales_invoice.grand_total",
|
||||
"fieldname": "outstanding_amount",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Outstanding Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"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
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-03-07 16:38:03.622666",
|
||||
"modified": "2019-05-30 19:27:29.436153",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Discounted Invoice",
|
||||
"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,
|
||||
"track_views": 0
|
||||
"track_changes": 1
|
||||
}
|
@ -21,10 +21,30 @@ frappe.ui.form.on('Exchange Rate Revaluation', {
|
||||
|
||||
refresh: function(frm) {
|
||||
if(frm.doc.docstatus==1) {
|
||||
frappe.db.get_value("Journal Entry Account", {
|
||||
'reference_type': 'Exchange Rate Revaluation',
|
||||
'reference_name': frm.doc.name,
|
||||
'docstatus': 1
|
||||
}, "sum(debit) as sum", (r) =>{
|
||||
let total_amt = 0;
|
||||
frm.doc.accounts.forEach(d=> {
|
||||
total_amt = total_amt + d['new_balance_in_base_currency'];
|
||||
});
|
||||
if(total_amt === r.sum) {
|
||||
frm.add_custom_button(__("Journal Entry"), function(){
|
||||
frappe.route_options = {
|
||||
'reference_type': 'Exchange Rate Revaluation',
|
||||
'reference_name': frm.doc.name
|
||||
};
|
||||
frappe.set_route("List", "Journal Entry");
|
||||
}, __("View"));
|
||||
} else {
|
||||
frm.add_custom_button(__('Create Journal Entry'), function() {
|
||||
return frm.events.make_jv(frm);
|
||||
});
|
||||
}
|
||||
}, 'Journal Entry');
|
||||
}
|
||||
},
|
||||
|
||||
get_entries: function(frm) {
|
||||
|
@ -91,13 +91,13 @@ class GLEntry(Document):
|
||||
if account_type == "Profit and Loss" \
|
||||
and dimension.mandatory_for_pl and not dimension.disabled:
|
||||
if not self.get(dimension.fieldname):
|
||||
frappe.throw(_("{0} is required for 'Profit and Loss' account {1}.")
|
||||
frappe.throw(_("Accounting Dimension <b>{0}</b> is required for 'Profit and Loss' account {1}.")
|
||||
.format(dimension.label, self.account))
|
||||
|
||||
if account_type == "Balance Sheet" \
|
||||
and dimension.mandatory_for_bs and not dimension.disabled:
|
||||
if not self.get(dimension.fieldname):
|
||||
frappe.throw(_("{0} is required for 'Balance Sheet' account {1}.")
|
||||
frappe.throw(_("Accounting Dimension <b>{0}</b> is required for 'Balance Sheet' account {1}.")
|
||||
.format(dimension.label, self.account))
|
||||
|
||||
|
||||
|
@ -1,744 +1,177 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "ACC-INV-DISC-.YYYY.-.#####",
|
||||
"beta": 0,
|
||||
"creation": "2019-03-07 12:01:56.296952",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"posting_date",
|
||||
"loan_start_date",
|
||||
"loan_period",
|
||||
"loan_end_date",
|
||||
"column_break_3",
|
||||
"status",
|
||||
"company",
|
||||
"section_break_5",
|
||||
"invoices",
|
||||
"section_break_7",
|
||||
"total_amount",
|
||||
"column_break_9",
|
||||
"bank_charges",
|
||||
"section_break_6",
|
||||
"short_term_loan",
|
||||
"bank_account",
|
||||
"bank_charges_account",
|
||||
"column_break_15",
|
||||
"accounts_receivable_credit",
|
||||
"accounts_receivable_discounted",
|
||||
"accounts_receivable_unpaid",
|
||||
"amended_from"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Today",
|
||||
"fieldname": "posting_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": "Posting Date",
|
||||
"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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "loan_start_date",
|
||||
"fieldtype": "Date",
|
||||
"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": "Loan Start Date",
|
||||
"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
|
||||
"label": "Loan Start Date"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "loan_period",
|
||||
"fieldtype": "Int",
|
||||
"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": "Loan Period",
|
||||
"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
|
||||
"label": "Loan Period (Days)"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "loan_end_date",
|
||||
"fieldtype": "Date",
|
||||
"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": "Loan End Date",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"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
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"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,
|
||||
"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
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"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": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Draft\nSanctioned\nDisbursed\nSettled\nCancelled",
|
||||
"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
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"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
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_5",
|
||||
"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
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "invoices",
|
||||
"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": "Invoices",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Discounted Invoice",
|
||||
"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
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_7",
|
||||
"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
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 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": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"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
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_9",
|
||||
"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,
|
||||
"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
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "bank_charges",
|
||||
"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": "Bank Charges",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"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
|
||||
"options": "Company:company:default_currency"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_6",
|
||||
"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
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "short_term_loan",
|
||||
"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": "Short Term Loan Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 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": "Account",
|
||||
"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
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "bank_charges_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 Charges Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_15",
|
||||
"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,
|
||||
"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
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "accounts_receivable_credit",
|
||||
"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": "Accounts Receivable Credit Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "accounts_receivable_discounted",
|
||||
"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": "Accounts Receivable Discounted Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "accounts_receivable_unpaid",
|
||||
"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": "Accounts Receivable Unpaid Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "amended_from",
|
||||
"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": "Amended From",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Invoice Discounting",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"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
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-03-08 14:24:31.222027",
|
||||
"modified": "2019-05-30 19:08:21.199759",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Invoice Discounting",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
@ -748,26 +181,17 @@
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"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,
|
||||
"track_views": 0
|
||||
"track_changes": 1
|
||||
}
|
@ -28,19 +28,40 @@ class InvoiceDiscounting(AccountsController):
|
||||
self.total_amount = sum([flt(d.outstanding_amount) for d in self.invoices])
|
||||
|
||||
def on_submit(self):
|
||||
self.update_sales_invoice()
|
||||
self.make_gl_entries()
|
||||
|
||||
def on_cancel(self):
|
||||
self.set_status()
|
||||
self.update_sales_invoice()
|
||||
self.make_gl_entries()
|
||||
|
||||
def set_status(self):
|
||||
def set_status(self, status=None):
|
||||
if status:
|
||||
self.status = status
|
||||
self.db_set("status", status)
|
||||
for d in self.invoices:
|
||||
frappe.get_doc("Sales Invoice", d.sales_invoice).set_status(update=True, update_modified=False)
|
||||
else:
|
||||
self.status = "Draft"
|
||||
if self.docstatus == 1:
|
||||
self.status = "Sanctioned"
|
||||
elif self.docstatus == 2:
|
||||
self.status = "Cancelled"
|
||||
|
||||
def update_sales_invoice(self):
|
||||
for d in self.invoices:
|
||||
if self.docstatus == 1:
|
||||
is_discounted = 1
|
||||
else:
|
||||
discounted_invoice = frappe.db.exists({
|
||||
"doctype": "Discounted Invoice",
|
||||
"sales_invoice": d.sales_invoice,
|
||||
"docstatus": 1
|
||||
})
|
||||
is_discounted = 1 if discounted_invoice else 0
|
||||
frappe.db.set_value("Sales Invoice", d.sales_invoice, "is_discounted", is_discounted)
|
||||
|
||||
def make_gl_entries(self):
|
||||
company_currency = frappe.get_cached_value('Company', self.company, "default_currency")
|
||||
|
||||
|
@ -105,24 +105,28 @@ class JournalEntry(AccountsController):
|
||||
|
||||
invoice_discounting_list = list(set([d.reference_name for d in self.accounts if d.reference_type=="Invoice Discounting"]))
|
||||
for inv_disc in invoice_discounting_list:
|
||||
short_term_loan_account, id_status = frappe.db.get_value("Invoice Discounting", inv_disc, ["short_term_loan", "status"])
|
||||
inv_disc_doc = frappe.get_doc("Invoice Discounting", inv_disc)
|
||||
status = None
|
||||
for d in self.accounts:
|
||||
if d.account == short_term_loan_account and d.reference_name == inv_disc:
|
||||
if d.account == inv_disc_doc.short_term_loan and d.reference_name == inv_disc:
|
||||
if self.docstatus == 1:
|
||||
if d.credit > 0:
|
||||
_validate_invoice_discounting_status(inv_disc, id_status, "Sanctioned", d.idx)
|
||||
_validate_invoice_discounting_status(inv_disc, inv_disc_doc.status, "Sanctioned", d.idx)
|
||||
status = "Disbursed"
|
||||
elif d.debit > 0:
|
||||
_validate_invoice_discounting_status(inv_disc, id_status, "Disbursed", d.idx)
|
||||
_validate_invoice_discounting_status(inv_disc, inv_disc_doc.status, "Disbursed", d.idx)
|
||||
status = "Settled"
|
||||
else:
|
||||
if d.credit > 0:
|
||||
_validate_invoice_discounting_status(inv_disc, id_status, "Disbursed", d.idx)
|
||||
_validate_invoice_discounting_status(inv_disc, inv_disc_doc.status, "Disbursed", d.idx)
|
||||
status = "Sanctioned"
|
||||
elif d.debit > 0:
|
||||
_validate_invoice_discounting_status(inv_disc, id_status, "Settled", d.idx)
|
||||
_validate_invoice_discounting_status(inv_disc, inv_disc_doc.status, "Settled", d.idx)
|
||||
status = "Disbursed"
|
||||
frappe.db.set_value("Invoice Discounting", inv_disc, "status", status)
|
||||
break
|
||||
if status:
|
||||
inv_disc_doc.set_status(status=status)
|
||||
|
||||
|
||||
def unlink_advance_entry_reference(self):
|
||||
for d in self.get("accounts"):
|
||||
|
@ -601,7 +601,7 @@ def get_outstanding_reference_documents(args):
|
||||
condition += " and company = {0}".format(frappe.db.escape(args.get("company")))
|
||||
|
||||
outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"),
|
||||
args.get("party_account"), filters=args, condition=condition, limit=100)
|
||||
args.get("party_account"), filters=args, condition=condition)
|
||||
|
||||
for d in outstanding_invoices:
|
||||
d["exchange_rate"] = 1
|
||||
|
@ -451,6 +451,10 @@ def make_customer_and_address(customers):
|
||||
|
||||
|
||||
def add_customer(data):
|
||||
customer = data.get('full_name') or data.get('customer')
|
||||
if frappe.db.exists("Customer", customer.strip()):
|
||||
return customer.strip()
|
||||
|
||||
customer_doc = frappe.new_doc('Customer')
|
||||
customer_doc.customer_name = data.get('full_name') or data.get('customer')
|
||||
customer_doc.customer_pos_id = data.get('customer_pos_id')
|
||||
|
@ -83,10 +83,14 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
}
|
||||
}
|
||||
|
||||
if (doc.outstanding_amount>0 && !cint(doc.is_return)) {
|
||||
if (doc.outstanding_amount>0) {
|
||||
cur_frm.add_custom_button(__('Payment Request'), function() {
|
||||
me.make_payment_request();
|
||||
}, __('Create'));
|
||||
|
||||
cur_frm.add_custom_button(__('Invoice Discounting'), function() {
|
||||
cur_frm.events.create_invoice_discounting(cur_frm);
|
||||
}, __('Create'));
|
||||
}
|
||||
|
||||
if (doc.docstatus === 1) {
|
||||
@ -187,9 +191,13 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
method: "erpnext.selling.doctype.quotation.quotation.make_sales_invoice",
|
||||
source_doctype: "Quotation",
|
||||
target: me.frm,
|
||||
setters: {
|
||||
customer: me.frm.doc.customer || undefined,
|
||||
},
|
||||
setters: [{
|
||||
fieldtype: 'Link',
|
||||
label: __('Customer'),
|
||||
options: 'Customer',
|
||||
fieldname: 'party_name',
|
||||
default: me.frm.doc.customer,
|
||||
}],
|
||||
get_query_filters: {
|
||||
docstatus: 1,
|
||||
status: ["!=", "Lost"],
|
||||
@ -804,6 +812,13 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
frm.set_df_property("patient_name", "hidden", 1);
|
||||
frm.set_df_property("ref_practitioner", "hidden", 1);
|
||||
}
|
||||
},
|
||||
|
||||
create_invoice_discounting: function(frm) {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.create_invoice_discounting",
|
||||
frm: frm
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -155,6 +155,7 @@
|
||||
"inter_company_invoice_reference",
|
||||
"customer_group",
|
||||
"campaign",
|
||||
"is_discounted",
|
||||
"col_break23",
|
||||
"status",
|
||||
"source",
|
||||
@ -1324,6 +1325,13 @@
|
||||
"options": "Campaign",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "is_discounted",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Discounted",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break23",
|
||||
"fieldtype": "Column Break",
|
||||
@ -1336,7 +1344,7 @@
|
||||
"in_standard_filter": 1,
|
||||
"label": "Status",
|
||||
"no_copy": 1,
|
||||
"options": "\nDraft\nReturn\nCredit Note Issued\nSubmitted\nPaid\nUnpaid\nOverdue\nCancelled",
|
||||
"options": "\nDraft\nReturn\nCredit Note Issued\nSubmitted\nPaid\nUnpaid\nUnpaid and Discounted\nOverdue and Discounted\nOverdue\nOverdue\nCancelled",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
@ -1558,7 +1566,7 @@
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 181,
|
||||
"is_submittable": 1,
|
||||
"modified": "2019-05-25 22:05:03.474745",
|
||||
"modified": "2019-07-04 22:05:03.474745",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
@ -395,14 +395,18 @@ class SalesInvoice(SellingController):
|
||||
if pos.get('account_for_change_amount'):
|
||||
self.account_for_change_amount = pos.get('account_for_change_amount')
|
||||
|
||||
for fieldname in ('territory', 'naming_series', 'currency', 'taxes_and_charges', 'letter_head', 'tc_name',
|
||||
'company', 'select_print_heading', 'cash_bank_account', 'company_address',
|
||||
'write_off_account', 'write_off_cost_center', 'apply_discount_on', 'cost_center'):
|
||||
for fieldname in ('territory', 'naming_series', 'currency', 'letter_head', 'tc_name',
|
||||
'company', 'select_print_heading', 'cash_bank_account', 'write_off_account',
|
||||
'write_off_cost_center', 'apply_discount_on', 'cost_center'):
|
||||
if (not for_validate) or (for_validate and not self.get(fieldname)):
|
||||
self.set(fieldname, pos.get(fieldname))
|
||||
|
||||
customer_price_list = frappe.get_value("Customer", self.customer, 'default_price_list')
|
||||
|
||||
for field in ['taxes_and_charges', 'company_address']:
|
||||
if pos.get(field):
|
||||
self.set(field, pos.get(fieldname))
|
||||
|
||||
if not customer_price_list:
|
||||
self.set('selling_price_list', pos.get('selling_price_list'))
|
||||
|
||||
@ -1177,6 +1181,56 @@ class SalesInvoice(SellingController):
|
||||
|
||||
self.set_missing_values(for_validate = True)
|
||||
|
||||
def get_discounting_status(self):
|
||||
status = None
|
||||
if self.is_discounted:
|
||||
invoice_discounting_list = frappe.db.sql("""
|
||||
select status
|
||||
from `tabInvoice Discounting` id, `tabDiscounted Invoice` d
|
||||
where
|
||||
id.name = d.parent
|
||||
and d.sales_invoice=%s
|
||||
and id.docstatus=1
|
||||
and status in ('Disbursed', 'Settled')
|
||||
""", self.name)
|
||||
for d in invoice_discounting_list:
|
||||
status = d[0]
|
||||
if status == "Disbursed":
|
||||
break
|
||||
return status
|
||||
|
||||
def set_status(self, update=False, status=None, update_modified=True):
|
||||
if self.is_new():
|
||||
if self.get('amended_from'):
|
||||
self.status = 'Draft'
|
||||
return
|
||||
|
||||
if not status:
|
||||
if self.docstatus == 2:
|
||||
status = "Cancelled"
|
||||
elif self.docstatus == 1:
|
||||
if flt(self.outstanding_amount) > 0 and getdate(self.due_date) < getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
|
||||
self.status = "Overdue and Discounted"
|
||||
elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) < getdate(nowdate()):
|
||||
self.status = "Overdue"
|
||||
elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
|
||||
self.status = "Unpaid and Discounted"
|
||||
elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) >= getdate(nowdate()):
|
||||
self.status = "Unpaid"
|
||||
elif flt(self.outstanding_amount) < 0 and self.is_return==0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}):
|
||||
self.status = "Credit Note Issued"
|
||||
elif self.is_return == 1:
|
||||
self.status = "Return"
|
||||
elif flt(self.outstanding_amount)<=0:
|
||||
self.status = "Paid"
|
||||
else:
|
||||
self.status = "Submitted"
|
||||
else:
|
||||
self.status = "Draft"
|
||||
|
||||
if update:
|
||||
self.db_set('status', self.status, update_modified = update_modified)
|
||||
|
||||
def validate_inter_company_party(doctype, party, company, inter_company_reference):
|
||||
if not party:
|
||||
return
|
||||
@ -1432,3 +1486,17 @@ def get_loyalty_programs(customer):
|
||||
return []
|
||||
else:
|
||||
return lp_details
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_invoice_discounting(source_name, target_doc=None):
|
||||
invoice = frappe.get_doc("Sales Invoice", source_name)
|
||||
invoice_discounting = frappe.new_doc("Invoice Discounting")
|
||||
invoice_discounting.company = invoice.company
|
||||
invoice_discounting.append("invoices", {
|
||||
"sales_invoice": source_name,
|
||||
"customer": invoice.customer,
|
||||
"posting_date": invoice.posting_date,
|
||||
"outstanding_amount": invoice.outstanding_amount
|
||||
})
|
||||
|
||||
return invoice_discounting
|
@ -6,17 +6,18 @@ frappe.listview_settings['Sales Invoice'] = {
|
||||
add_fields: ["customer", "customer_name", "base_grand_total", "outstanding_amount", "due_date", "company",
|
||||
"currency", "is_return"],
|
||||
get_indicator: function(doc) {
|
||||
if(flt(doc.outstanding_amount) < 0) {
|
||||
return [__("Credit Note Issued"), "darkgrey", "outstanding_amount,<,0"]
|
||||
} else if (flt(doc.outstanding_amount) > 0 && doc.due_date >= frappe.datetime.get_today()) {
|
||||
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due_date,>,Today"]
|
||||
} else if (flt(doc.outstanding_amount) > 0 && doc.due_date < frappe.datetime.get_today()) {
|
||||
return [__("Overdue"), "red", "outstanding_amount,>,0|due_date,<=,Today"]
|
||||
} else if(cint(doc.is_return)) {
|
||||
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
||||
} else if(flt(doc.outstanding_amount)==0) {
|
||||
return [__("Paid"), "green", "outstanding_amount,=,0"]
|
||||
}
|
||||
var status_color = {
|
||||
"Draft": "grey",
|
||||
"Unpaid": "orange",
|
||||
"Paid": "green",
|
||||
"Return": "darkgrey",
|
||||
"Credit Note Issued": "darkgrey",
|
||||
"Unpaid and Discounted": "orange",
|
||||
"Overdue and Discounted": "red",
|
||||
"Overdue": "red"
|
||||
|
||||
};
|
||||
return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
|
||||
},
|
||||
right_column: "grand_total"
|
||||
};
|
||||
|
@ -88,6 +88,12 @@ frappe.query_reports["Accounts Payable"] = {
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"fieldname":"payment_terms_template",
|
||||
"label": __("Payment Terms Template"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Payment Terms Template"
|
||||
},
|
||||
{
|
||||
"fieldname":"supplier_group",
|
||||
"label": __("Supplier Group"),
|
||||
|
@ -77,6 +77,12 @@ frappe.query_reports["Accounts Payable Summary"] = {
|
||||
"fieldtype": "Link",
|
||||
"options": "Supplier"
|
||||
},
|
||||
{
|
||||
"fieldname":"payment_terms_template",
|
||||
"label": __("Payment Terms Template"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Payment Terms Template"
|
||||
},
|
||||
{
|
||||
"fieldname":"supplier_group",
|
||||
"label": __("Supplier Group"),
|
||||
|
@ -541,6 +541,10 @@ class ReceivablePayableReport(object):
|
||||
where supplier_group=%s)""")
|
||||
values.append(self.filters.get("supplier_group"))
|
||||
|
||||
if self.filters.get("payment_terms_template"):
|
||||
conditions.append("party in (select name from tabSupplier where payment_terms=%s)")
|
||||
values.append(self.filters.get("payment_terms_template"))
|
||||
|
||||
if self.filters.get("cost_center"):
|
||||
lft, rgt = frappe.get_cached_value("Cost Center",
|
||||
self.filters.get("cost_center"), ['lft', 'rgt'])
|
||||
|
@ -8,17 +8,19 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
||||
// The last item in the array is the definition for Presentation Currency
|
||||
// filter. It won't be used in cash flow for now so we pop it. Please take
|
||||
// of this if you are working here.
|
||||
frappe.query_reports["Cash Flow"]["filters"].pop();
|
||||
|
||||
frappe.query_reports["Cash Flow"]["filters"].push({
|
||||
frappe.query_reports["Cash Flow"]["filters"].splice(5, 1);
|
||||
|
||||
frappe.query_reports["Cash Flow"]["filters"].push(
|
||||
{
|
||||
"fieldname": "accumulated_values",
|
||||
"label": __("Accumulated Values"),
|
||||
"fieldtype": "Check"
|
||||
});
|
||||
|
||||
frappe.query_reports["Cash Flow"]["filters"].push({
|
||||
},
|
||||
{
|
||||
"fieldname": "include_default_book_entries",
|
||||
"label": __("Include Default Book Entries"),
|
||||
"fieldtype": "Check"
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
@ -69,7 +69,9 @@ def execute(filters=None):
|
||||
add_total_row_account(data, data, _("Net Change in Cash"), period_list, company_currency)
|
||||
columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company)
|
||||
|
||||
return columns, data
|
||||
chart = get_chart_data(columns, data)
|
||||
|
||||
return columns, data, None, chart
|
||||
|
||||
def get_cash_flow_accounts():
|
||||
operation_accounts = {
|
||||
@ -172,3 +174,20 @@ def add_total_row_account(out, data, label, period_list, currency, consolidated
|
||||
|
||||
out.append(total_row)
|
||||
out.append({})
|
||||
|
||||
def get_chart_data(columns, data):
|
||||
labels = [d.get("label") for d in columns[2:]]
|
||||
datasets = [{'name':account.get('account').replace("'", ""), 'values': [account.get('total')]} for account in data if account.get('parent_account') == None and account.get('currency')]
|
||||
datasets = datasets[:-1]
|
||||
|
||||
chart = {
|
||||
"data": {
|
||||
'labels': labels,
|
||||
'datasets': datasets
|
||||
},
|
||||
"type": "bar"
|
||||
}
|
||||
|
||||
chart["fieldtype"] = "Currency"
|
||||
|
||||
return chart
|
||||
|
@ -11,6 +11,7 @@ from erpnext.accounts.utils import get_account_currency
|
||||
from erpnext.accounts.report.financial_statements import get_cost_centers_with_children
|
||||
from six import iteritems
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
|
||||
from collections import OrderedDict
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters:
|
||||
@ -274,7 +275,7 @@ def group_by_field(group_by):
|
||||
return 'voucher_no'
|
||||
|
||||
def initialize_gle_map(gl_entries, filters):
|
||||
gle_map = frappe._dict()
|
||||
gle_map = OrderedDict()
|
||||
group_by = group_by_field(filters.get('group_by'))
|
||||
|
||||
for gle in gl_entries:
|
||||
|
@ -93,4 +93,6 @@ def get_chart_data(filters, columns, income, expense, net_profit_loss):
|
||||
else:
|
||||
chart["type"] = "line"
|
||||
|
||||
chart["fieldtype"] = "Currency"
|
||||
|
||||
return chart
|
@ -104,6 +104,9 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
|
||||
# get balance of all entries that exist
|
||||
date = nowdate()
|
||||
|
||||
if account:
|
||||
acc = frappe.get_doc("Account", account)
|
||||
|
||||
try:
|
||||
year_start_date = get_fiscal_year(date, verbose=0)[1]
|
||||
except FiscalYearError:
|
||||
@ -118,7 +121,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
|
||||
|
||||
allow_cost_center_in_entry_of_bs_account = get_allow_cost_center_in_entry_of_bs_account()
|
||||
|
||||
if cost_center and allow_cost_center_in_entry_of_bs_account:
|
||||
if cost_center and (allow_cost_center_in_entry_of_bs_account or acc.report_type =='Profit and Loss'):
|
||||
cc = frappe.get_doc("Cost Center", cost_center)
|
||||
if cc.is_group:
|
||||
cond.append(""" exists (
|
||||
@ -132,20 +135,13 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
|
||||
|
||||
if account:
|
||||
|
||||
acc = frappe.get_doc("Account", account)
|
||||
|
||||
if not frappe.flags.ignore_account_permission:
|
||||
acc.check_permission("read")
|
||||
|
||||
|
||||
if not allow_cost_center_in_entry_of_bs_account and acc.report_type == 'Profit and Loss':
|
||||
if acc.report_type == 'Profit and Loss':
|
||||
# for pl accounts, get balance within a fiscal year
|
||||
cond.append("posting_date >= '%s' and voucher_type != 'Period Closing Voucher'" \
|
||||
% year_start_date)
|
||||
elif allow_cost_center_in_entry_of_bs_account:
|
||||
# for all accounts, get balance within a fiscal year if maintain cost center in balance account is checked
|
||||
cond.append("posting_date >= '%s' and voucher_type != 'Period Closing Voucher'" \
|
||||
% year_start_date)
|
||||
# different filter for group and ledger - improved performance
|
||||
if acc.is_group:
|
||||
cond.append("""exists (
|
||||
@ -745,7 +741,7 @@ def get_children(doctype, parent, company, is_root=False):
|
||||
filters.append(['company', '=', company])
|
||||
|
||||
else:
|
||||
fields += ['account_currency'] if doctype == 'Account' else []
|
||||
fields += ['root_type', 'account_currency'] if doctype == 'Account' else []
|
||||
fields += [parent_fieldname + ' as parent']
|
||||
|
||||
acc = frappe.get_list(doctype, fields=fields, filters=filters)
|
||||
|
@ -66,10 +66,11 @@
|
||||
"net_total",
|
||||
"total_net_weight",
|
||||
"taxes_section",
|
||||
"taxes_and_charges",
|
||||
"tax_category",
|
||||
"column_break_50",
|
||||
"shipping_rule",
|
||||
"section_break_52",
|
||||
"taxes_and_charges",
|
||||
"taxes",
|
||||
"sec_tax_breakup",
|
||||
"other_charges_calculation",
|
||||
@ -569,7 +570,7 @@
|
||||
{
|
||||
"fieldname": "taxes_and_charges",
|
||||
"fieldtype": "Link",
|
||||
"label": "Taxes and Charges",
|
||||
"label": "Purchase Taxes and Charges Template",
|
||||
"oldfieldname": "purchase_other_charges",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Purchase Taxes and Charges Template",
|
||||
@ -1032,12 +1033,18 @@
|
||||
"fieldname": "update_auto_repeat_reference",
|
||||
"fieldtype": "Button",
|
||||
"label": "Update Auto Repeat Reference"
|
||||
},
|
||||
{
|
||||
"fieldname": "tax_category",
|
||||
"fieldtype": "Link",
|
||||
"label": "Tax Category",
|
||||
"options": "Tax Category"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 105,
|
||||
"is_submittable": 1,
|
||||
"modified": "2019-06-24 21:22:05.483429",
|
||||
"modified": "2019-07-11 18:25:49.509343",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
@ -4,6 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import unittest
|
||||
import frappe
|
||||
import json
|
||||
import frappe.defaults
|
||||
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
|
||||
from frappe.utils import flt, add_days, nowdate, getdate
|
||||
@ -15,7 +16,7 @@ from erpnext.stock.doctype.material_request.test_material_request import make_ma
|
||||
from erpnext.stock.doctype.material_request.material_request import make_purchase_order
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||
from erpnext.controllers.accounts_controller import update_child_qty_rate
|
||||
import json
|
||||
from erpnext.controllers.status_updater import OverAllowanceError
|
||||
|
||||
class TestPurchaseOrder(unittest.TestCase):
|
||||
def test_make_purchase_receipt(self):
|
||||
@ -41,7 +42,7 @@ class TestPurchaseOrder(unittest.TestCase):
|
||||
po.load_from_db()
|
||||
self.assertEqual(po.get("items")[0].received_qty, 4)
|
||||
|
||||
frappe.db.set_value('Item', '_Test Item', 'tolerance', 50)
|
||||
frappe.db.set_value('Item', '_Test Item', 'over_delivery_receipt_allowance', 50)
|
||||
|
||||
pr = create_pr_against_po(po.name, received_qty=8)
|
||||
self.assertEqual(get_ordered_qty(), existing_ordered_qty)
|
||||
@ -57,12 +58,12 @@ class TestPurchaseOrder(unittest.TestCase):
|
||||
|
||||
def test_ordered_qty_against_pi_with_update_stock(self):
|
||||
existing_ordered_qty = get_ordered_qty()
|
||||
|
||||
po = create_purchase_order()
|
||||
|
||||
self.assertEqual(get_ordered_qty(), existing_ordered_qty + 10)
|
||||
|
||||
frappe.db.set_value('Item', '_Test Item', 'tolerance', 50)
|
||||
frappe.db.set_value('Item', '_Test Item', 'over_delivery_receipt_allowance', 50)
|
||||
frappe.db.set_value('Item', '_Test Item', 'over_billing_allowance', 20)
|
||||
|
||||
pi = make_pi_from_po(po.name)
|
||||
pi.update_stock = 1
|
||||
@ -81,6 +82,11 @@ class TestPurchaseOrder(unittest.TestCase):
|
||||
po.load_from_db()
|
||||
self.assertEqual(po.get("items")[0].received_qty, 0)
|
||||
|
||||
frappe.db.set_value('Item', '_Test Item', 'over_delivery_receipt_allowance', 0)
|
||||
frappe.db.set_value('Item', '_Test Item', 'over_billing_allowance', 0)
|
||||
frappe.db.set_value("Accounts Settings", None, "over_billing_allowance", 0)
|
||||
|
||||
|
||||
def test_update_child_qty_rate(self):
|
||||
mr = make_material_request(qty=10)
|
||||
po = make_purchase_order(mr.name)
|
||||
|
@ -6,11 +6,12 @@ import frappe
|
||||
def get_data():
|
||||
config = [
|
||||
{
|
||||
"label": _("Masters and Accounts"),
|
||||
"label": _("Accounts Receivable"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Item",
|
||||
"name": "Sales Invoice",
|
||||
"description": _("Bills raised to Customers."),
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
@ -19,12 +20,115 @@ def get_data():
|
||||
"description": _("Customer database."),
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Payment Entry",
|
||||
"description": _("Bank/Cash transactions against party or for internal transfer")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Payment Request",
|
||||
"description": _("Payment Request"),
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Accounts Receivable",
|
||||
"doctype": "Sales Invoice",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Accounts Receivable Summary",
|
||||
"doctype": "Sales Invoice",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Sales Register",
|
||||
"doctype": "Sales Invoice",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Item-wise Sales Register",
|
||||
"is_query_report": True,
|
||||
"doctype": "Sales Invoice"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Ordered Items To Be Billed",
|
||||
"is_query_report": True,
|
||||
"doctype": "Sales Invoice"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Delivered Items To Be Billed",
|
||||
"is_query_report": True,
|
||||
"doctype": "Sales Invoice"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Accounts Payable"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Purchase Invoice",
|
||||
"description": _("Bills raised by Suppliers."),
|
||||
"onboard": 1
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Supplier",
|
||||
"description": _("Supplier database."),
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Payment Entry",
|
||||
"description": _("Bank/Cash transactions against party or for internal transfer")
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Accounts Payable",
|
||||
"doctype": "Purchase Invoice",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Accounts Payable Summary",
|
||||
"doctype": "Purchase Invoice",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Purchase Register",
|
||||
"doctype": "Purchase Invoice",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Item-wise Purchase Register",
|
||||
"is_query_report": True,
|
||||
"doctype": "Purchase Invoice"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Purchase Order Items To Be Billed",
|
||||
"is_query_report": True,
|
||||
"doctype": "Purchase Invoice"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Received Items To Be Billed",
|
||||
"is_query_report": True,
|
||||
"doctype": "Purchase Invoice"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Accounting Masters"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Company",
|
||||
@ -40,201 +144,31 @@ def get_data():
|
||||
"description": _("Tree of financial accounts."),
|
||||
"onboard": 1,
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Billing"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Sales Invoice",
|
||||
"description": _("Bills raised to Customers."),
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Purchase Invoice",
|
||||
"description": _("Bills raised by Suppliers."),
|
||||
"onboard": 1
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Payment Request",
|
||||
"description": _("Payment Request"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Payment Term",
|
||||
"description": _("Payment Terms based on conditions")
|
||||
},
|
||||
|
||||
# Reports
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Ordered Items To Be Billed",
|
||||
"is_query_report": True,
|
||||
"reference_doctype": "Sales Invoice"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Delivered Items To Be Billed",
|
||||
"is_query_report": True,
|
||||
"reference_doctype": "Sales Invoice"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Purchase Order Items To Be Billed",
|
||||
"is_query_report": True,
|
||||
"reference_doctype": "Purchase Invoice"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Received Items To Be Billed",
|
||||
"is_query_report": True,
|
||||
"reference_doctype": "Purchase Invoice"
|
||||
},
|
||||
]
|
||||
|
||||
},
|
||||
{
|
||||
"label": _("Settings"),
|
||||
"icon": "fa fa-cog",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Accounts Settings",
|
||||
"description": _("Default settings for accounting transactions.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Fiscal Year",
|
||||
"description": _("Financial / accounting year.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Currency",
|
||||
"description": _("Enable / disable currencies.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Currency Exchange",
|
||||
"description": _("Currency exchange rate master.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Exchange Rate Revaluation",
|
||||
"description": _("Exchange Rate Revaluation master.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Payment Gateway Account",
|
||||
"description": _("Setup Gateway accounts.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Terms and Conditions",
|
||||
"label": _("Terms and Conditions Template"),
|
||||
"description": _("Template of terms or contract.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Mode of Payment",
|
||||
"description": _("e.g. Bank, Cash, Credit Card")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Auto Repeat",
|
||||
"label": _("Auto Repeat"),
|
||||
"description": _("To make recurring documents")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "C-Form",
|
||||
"description": _("C-Form records"),
|
||||
"country": "India"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Cheque Print Template",
|
||||
"description": _("Setup cheque dimensions for printing")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Accounting Dimension",
|
||||
"description": _("Setup custom dimensions for accounting")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Opening Invoice Creation Tool",
|
||||
"description": _("Create Opening Sales and Purchase Invoices")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Accounting Entries"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Payment Entry",
|
||||
"description": _("Bank/Cash transactions against party or for internal transfer")
|
||||
"name": "Finance Book",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Journal Entry",
|
||||
"description": _("Accounting journal entries.")
|
||||
}
|
||||
]
|
||||
"name": "Accounting Period",
|
||||
},
|
||||
{
|
||||
"label": _("Financial Statements"),
|
||||
"items": [
|
||||
{
|
||||
"type": "report",
|
||||
"name": "General Ledger",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True,
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Accounts Receivable",
|
||||
"doctype": "Sales Invoice",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Accounts Payable",
|
||||
"doctype": "Purchase Invoice",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Trial Balance",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True,
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Balance Sheet",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Cash Flow",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Profit and Loss Statement",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Consolidated Financial Statement",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True
|
||||
"type": "doctype",
|
||||
"name": "Payment Term",
|
||||
"description": _("Payment Terms based on conditions")
|
||||
},
|
||||
]
|
||||
},
|
||||
@ -243,43 +177,10 @@ def get_data():
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"label": _("Bank"),
|
||||
"name": "Bank",
|
||||
"label": _("Match Payments with Invoices"),
|
||||
"name": "Payment Reconciliation",
|
||||
"description": _("Match non-linked Invoices and Payments.")
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"label": _("Reconcile payments and bank transactions"),
|
||||
"name": "bank-reconciliation",
|
||||
"description": _("Link bank transactions with payments.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"label": _("Bank Account"),
|
||||
"name": "Bank Account",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"label": _("Invoice Discounting"),
|
||||
"name": "Invoice Discounting",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"label": _("Bank Statement Transaction Entry List"),
|
||||
"name": "Bank Statement Transaction Entry",
|
||||
"route": "#List/Bank Statement Transaction Entry",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"label": _("Bank Statement Transaction Entry Report"),
|
||||
"name": "Bank Statement Transaction Entry",
|
||||
"route": "#Report/Bank Statement Transaction Entry",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"label": _("Bank Statement Settings"),
|
||||
"name": "Bank Statement Settings",
|
||||
},
|
||||
|
||||
{
|
||||
"type": "doctype",
|
||||
"label": _("Update Bank Transaction Dates"),
|
||||
@ -288,9 +189,8 @@ def get_data():
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"label": _("Match Payments with Invoices"),
|
||||
"name": "Payment Reconciliation",
|
||||
"description": _("Match non-linked Invoices and Payments.")
|
||||
"label": _("Invoice Discounting"),
|
||||
"name": "Invoice Discounting",
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
@ -306,8 +206,75 @@ def get_data():
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Bank Guarantee",
|
||||
"doctype": "Bank Guarantee"
|
||||
"name": "Bank Guarantee"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Cheque Print Template",
|
||||
"description": _("Setup cheque dimensions for printing")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("General Ledger"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Journal Entry",
|
||||
"description": _("Accounting journal entries.")
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "General Ledger",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True,
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Customer Ledger Summary",
|
||||
"doctype": "Sales Invoice",
|
||||
"is_query_report": True,
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Supplier Ledger Summary",
|
||||
"doctype": "Sales Invoice",
|
||||
"is_query_report": True,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Taxes"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Sales Taxes and Charges Template",
|
||||
"description": _("Tax template for selling transactions.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Purchase Taxes and Charges Template",
|
||||
"description": _("Tax template for buying transactions.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Item Tax Template",
|
||||
"description": _("Tax template for item tax rates.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Tax Category",
|
||||
"description": _("Tax Category for overriding tax rates.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Tax Rule",
|
||||
"description": _("Tax Rule for transactions.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Tax Withholding Category",
|
||||
"description": _("Tax Withholding rates to be applied on transactions.")
|
||||
},
|
||||
]
|
||||
},
|
||||
@ -327,6 +294,10 @@ def get_data():
|
||||
"name": "Budget",
|
||||
"description": _("Define budget for a financial year.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Accounting Dimension",
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Budget Variance Report",
|
||||
@ -338,51 +309,106 @@ def get_data():
|
||||
"name": "Monthly Distribution",
|
||||
"description": _("Seasonality for setting budgets, targets etc.")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Financial Statements"),
|
||||
"items": [
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Trial Balance",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True,
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Profit and Loss Statement",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Balance Sheet",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Cash Flow",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Consolidated Financial Statement",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Opening and Closing"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Opening Invoice Creation Tool",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Chart of Accounts Importer",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Period Closing Voucher",
|
||||
"description": _("Close Balance Sheet and book Profit or Loss.")
|
||||
},
|
||||
]
|
||||
|
||||
},
|
||||
{
|
||||
"label": _("Taxes"),
|
||||
"label": _("Multi Currency"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Tax Category",
|
||||
"description": _("Tax Category for overriding tax rates.")
|
||||
"name": "Currency",
|
||||
"description": _("Enable / disable currencies.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Sales Taxes and Charges Template",
|
||||
"description": _("Tax template for selling transactions.")
|
||||
"name": "Currency Exchange",
|
||||
"description": _("Currency exchange rate master.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Purchase Taxes and Charges Template",
|
||||
"description": _("Tax template for buying transactions.")
|
||||
"name": "Exchange Rate Revaluation",
|
||||
"description": _("Exchange Rate Revaluation master.")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Settings"),
|
||||
"icon": "fa fa-cog",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Payment Gateway Account",
|
||||
"description": _("Setup Gateway accounts.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Item Tax Template",
|
||||
"description": _("Tax template for item tax rates.")
|
||||
"name": "Terms and Conditions",
|
||||
"label": _("Terms and Conditions Template"),
|
||||
"description": _("Template of terms or contract.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Tax Rule",
|
||||
"description": _("Tax Rule for transactions.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Tax Withholding Category",
|
||||
"description": _("Tax Withholding rates to be applied on transactions.")
|
||||
"name": "Mode of Payment",
|
||||
"description": _("e.g. Bank, Cash, Credit Card")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Subscription Management"),
|
||||
"icon": "fa fa-microchip ",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
@ -403,7 +429,31 @@ def get_data():
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Key Reports"),
|
||||
"label": _("Bank Statement"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"label": _("Bank"),
|
||||
"name": "Bank",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"label": _("Bank Account"),
|
||||
"name": "Bank Account",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Bank Statement Transaction Entry",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"label": _("Bank Statement Settings"),
|
||||
"name": "Bank Statement Settings",
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Profitability"),
|
||||
"items": [
|
||||
{
|
||||
"type": "report",
|
||||
@ -413,21 +463,9 @@ def get_data():
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Sales Register",
|
||||
"doctype": "Sales Invoice",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Purchase Register",
|
||||
"doctype": "Purchase Invoice",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Purchase Invoice Trends",
|
||||
"name": "Profitability Analysis",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True,
|
||||
"doctype": "Purchase Invoice"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
@ -437,38 +475,14 @@ def get_data():
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Item-wise Sales Register",
|
||||
"is_query_report": True,
|
||||
"doctype": "Sales Invoice"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Item-wise Purchase Register",
|
||||
"name": "Purchase Invoice Trends",
|
||||
"is_query_report": True,
|
||||
"doctype": "Purchase Invoice"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Profitability Analysis",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True,
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Customer Ledger Summary",
|
||||
"doctype": "Sales Invoice",
|
||||
"is_query_report": True,
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Supplier Ledger Summary",
|
||||
"doctype": "Sales Invoice",
|
||||
"is_query_report": True,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Other Reports"),
|
||||
"label": _("Reports"),
|
||||
"icon": "fa fa-table",
|
||||
"items": [
|
||||
{
|
||||
@ -489,18 +503,6 @@ def get_data():
|
||||
"is_query_report": True,
|
||||
"doctype": "Sales Invoice"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Accounts Receivable Summary",
|
||||
"doctype": "Sales Invoice",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Accounts Payable Summary",
|
||||
"doctype": "Purchase Invoice",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
@ -549,27 +551,7 @@ def get_data():
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Help"),
|
||||
"icon": "fa fa-facetime-video",
|
||||
"items": [
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Chart of Accounts"),
|
||||
"youtube_id": "DyR-DST-PyA"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Opening Accounting Balance"),
|
||||
"youtube_id": "kdgM20Q-q68"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Setting up Taxes"),
|
||||
"youtube_id": "nQ1zZdPgdaQ"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
gst = {
|
||||
@ -617,6 +599,12 @@ def get_data():
|
||||
"name": "GST Itemised Purchase Register",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "C-Form",
|
||||
"description": _("C-Form records"),
|
||||
"country": "India"
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@ -624,6 +612,6 @@ def get_data():
|
||||
countries = frappe.get_all("Company", fields="country")
|
||||
countries = [country["country"] for country in countries]
|
||||
if "India" in countries:
|
||||
config.insert(7, gst)
|
||||
config.insert(9, gst)
|
||||
domains = frappe.get_active_domains()
|
||||
return config
|
||||
|
@ -228,29 +228,5 @@ def get_data():
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Help"),
|
||||
"items": [
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Customer and Supplier"),
|
||||
"youtube_id": "anoGi_RpQ20"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Material Request to Purchase Order"),
|
||||
"youtube_id": "4TN9kPyfIqM"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Purchase Order to Payment"),
|
||||
"youtube_id": "EK65tLdVUDk"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Managing Subcontracting"),
|
||||
"youtube_id": "ThiMCC2DtKo"
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
]
|
||||
|
@ -26,8 +26,8 @@ def get_data():
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"name": "medical_record",
|
||||
"label": _("Patient Medical Record"),
|
||||
"name": "patient_history",
|
||||
"label": _("Patient History"),
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
|
@ -4,127 +4,13 @@ from frappe import _
|
||||
def get_data():
|
||||
return [
|
||||
{
|
||||
"label": _("Employee and Attendance"),
|
||||
"label": _("Employee"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee",
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Attendance Tool",
|
||||
"hide_count": True,
|
||||
"onboard": 1,
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Group",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Attendance",
|
||||
"onboard": 1,
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Attendance Request",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Upload Attendance",
|
||||
"hide_count": True,
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Checkin",
|
||||
"hide_count": True,
|
||||
"onboard": 1,
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Payroll"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Salary Structure",
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Salary Structure Assignment",
|
||||
"onboard": 1,
|
||||
"dependencies": ["Salary Structure", "Employee"],
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Salary Slip",
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Payroll Entry",
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Benefit Application",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Benefit Claim",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Additional Salary",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Tax Exemption Declaration",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Tax Exemption Proof Submission",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Incentive",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Retention Bonus",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Payroll Period",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Salary Component",
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Settings"),
|
||||
"icon": "fa fa-cog",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "HR Settings",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employment Type",
|
||||
@ -147,19 +33,56 @@ def get_data():
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Daily Work Summary Group"
|
||||
"name": "Employee Group",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Health Insurance"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Staffing Plan",
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"label": _("Attendance"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Attendance Tool",
|
||||
"hide_count": True,
|
||||
"onboard": 1,
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Attendance",
|
||||
"onboard": 1,
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Attendance Request",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Upload Attendance",
|
||||
"hide_count": True,
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Checkin",
|
||||
"hide_count": True,
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Monthly Attendance Sheet",
|
||||
"doctype": "Attendance"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Leaves"),
|
||||
"items": [
|
||||
@ -175,13 +98,8 @@ def get_data():
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Compensatory Leave Request",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Leave Encashment",
|
||||
"dependencies": ["Employee"]
|
||||
"name": "Leave Policy",
|
||||
"dependencies": ["Leave Type"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
@ -194,37 +112,172 @@ def get_data():
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Leave Policy",
|
||||
"dependencies": ["Leave Type"]
|
||||
"name": "Holiday List",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Holiday List",
|
||||
"name": "Compensatory Leave Request",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Leave Encashment",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Leave Block List",
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Employee Leave Balance",
|
||||
"doctype": "Leave Application"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Recruitment and Training"),
|
||||
"label": _("Payroll"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Job Applicant",
|
||||
"name": "Salary Structure",
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Salary Structure Assignment",
|
||||
"onboard": 1,
|
||||
"dependencies": ["Salary Structure", "Employee"],
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Payroll Entry",
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Salary Slip",
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Salary Component",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Additional Salary",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Retention Bonus",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Incentive",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Salary Register",
|
||||
"doctype": "Salary Slip"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Employee Tax and Benefits"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Tax Exemption Declaration",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Tax Exemption Proof Submission",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Benefit Application",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Benefit Claim",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Employee Lifecycle"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Onboarding",
|
||||
"dependencies": ["Job Applicant"],
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Skill Map",
|
||||
"dependencies": ["Employee"],
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Promotion",
|
||||
"dependencies": ["Employee"],
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Transfer",
|
||||
"dependencies": ["Employee"],
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Separation",
|
||||
"dependencies": ["Employee"],
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Onboarding Template",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Separation Template",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Recruitment"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Job Opening",
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Job Applicant",
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Job Offer",
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Staffing Plan",
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Training"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Training Program"
|
||||
@ -244,42 +297,7 @@ def get_data():
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Employee Lifecycle"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Transfer",
|
||||
"dependencies": ["Employee"],
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Promotion",
|
||||
"dependencies": ["Employee"],
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Separation",
|
||||
"dependencies": ["Employee"],
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Onboarding",
|
||||
"dependencies": ["Job Applicant"],
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Separation Template",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Onboarding Template",
|
||||
"dependencies": ["Employee"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Appraisals, Expense Claims and Loans"),
|
||||
"label": _("Performance"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
@ -290,15 +308,24 @@ def get_data():
|
||||
"name": "Appraisal Template",
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"name": "team-updates",
|
||||
"label": _("Team Updates")
|
||||
"type": "doctype",
|
||||
"name": "Energy Point Rule",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Advance",
|
||||
"dependencies": ["Employee"]
|
||||
"name": "Energy Point Log",
|
||||
},
|
||||
{
|
||||
"type": "link",
|
||||
"doctype": "Energy Point Log",
|
||||
"label": _("Energy Point Leaderboard"),
|
||||
"route": "#social/users"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Expense Claims"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Expense Claim",
|
||||
@ -306,8 +333,14 @@ def get_data():
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Loan Type",
|
||||
"name": "Employee Advance",
|
||||
"dependencies": ["Employee"]
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Loans"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Loan Application",
|
||||
@ -316,19 +349,72 @@ def get_data():
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Loan"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Loan Type",
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Shift Management"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Shift Type",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Shift Request",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Shift Assignment",
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Fleet Management"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Vehicle"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Vehicle Log"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Vehicle Expenses",
|
||||
"doctype": "Vehicle"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Settings"),
|
||||
"icon": "fa fa-cog",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "HR Settings",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Daily Work Summary Group"
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"name": "team-updates",
|
||||
"label": _("Team Updates")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Reports"),
|
||||
"icon": "fa fa-list",
|
||||
"items": [
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Employee Leave Balance",
|
||||
"doctype": "Leave Application"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
@ -341,29 +427,6 @@ def get_data():
|
||||
"name": "Employees working on a holiday",
|
||||
"doctype": "Employee"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Employee Information",
|
||||
"doctype": "Employee"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Salary Register",
|
||||
"doctype": "Salary Slip"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Monthly Attendance Sheet",
|
||||
"doctype": "Attendance"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Vehicle Expenses",
|
||||
"doctype": "Vehicle"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
@ -372,50 +435,4 @@ def get_data():
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Shifts and Fleet Management"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Shift Type",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Shift Request",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Shift Assignment",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Vehicle"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Vehicle Log"
|
||||
},
|
||||
]
|
||||
},
|
||||
# {
|
||||
# "label": _("Help"),
|
||||
# "icon": "fa fa-facetime-video",
|
||||
# "items": [
|
||||
# {
|
||||
# "type": "help",
|
||||
# "label": _("Setting up Employees"),
|
||||
# "youtube_id": "USfIUdZlUhw"
|
||||
# },
|
||||
# {
|
||||
# "type": "help",
|
||||
# "label": _("Leave Management"),
|
||||
# "youtube_id": "fc0p_AXebc8"
|
||||
# },
|
||||
# {
|
||||
# "type": "help",
|
||||
# "label": _("Expense Claims"),
|
||||
# "youtube_id": "5SZHJF--ZFY"
|
||||
# }
|
||||
# ]
|
||||
# },
|
||||
]
|
||||
|
@ -88,17 +88,14 @@ def get_data():
|
||||
"doctype": "Project",
|
||||
"dependencies": ["Project"],
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Help"),
|
||||
"icon": "fa fa-facetime-video",
|
||||
"items": [
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Managing Projects"),
|
||||
"youtube_id": "egxIGwtoKI4"
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Project Billing Summary",
|
||||
"doctype": "Project",
|
||||
"dependencies": ["Project"],
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
]
|
||||
|
@ -318,41 +318,5 @@ def get_data():
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("SMS"),
|
||||
"icon": "fa fa-wrench",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "SMS Center",
|
||||
"description":_("Send mass SMS to your contacts"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "SMS Log",
|
||||
"description":_("Logs for maintaining sms delivery status"),
|
||||
},
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Help"),
|
||||
"items": [
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Customer and Supplier"),
|
||||
"youtube_id": "anoGi_RpQ20"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Sales Order to Payment"),
|
||||
"youtube_id": "1eP90MWoDQM"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Point-of-Sale"),
|
||||
"youtube_id": "4WkelWkbP_c"
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
|
@ -281,9 +281,9 @@ def get_data():
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Item Shortage Report",
|
||||
"route": "#Report/Bin/Item Shortage Report",
|
||||
"doctype": "Purchase Receipt"
|
||||
"doctype": "Bin"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
@ -329,45 +329,5 @@ def get_data():
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Help"),
|
||||
"icon": "fa fa-facetime-video",
|
||||
"items": [
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Items and Pricing"),
|
||||
"youtube_id": "qXaEwld4_Ps"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Item Variants"),
|
||||
"youtube_id": "OGBETlCzU5o"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Opening Stock Balance"),
|
||||
"youtube_id": "0yPgrtfeCTs"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Making Stock Entries"),
|
||||
"youtube_id": "Njt107hlY3I"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Serialized Inventory"),
|
||||
"youtube_id": "gvOVlEwFDAk"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Batch Inventory"),
|
||||
"youtube_id": "J0QKl7ABPKM"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Managing Subcontracting"),
|
||||
"youtube_id": "ThiMCC2DtKo"
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
|
@ -21,13 +21,7 @@ def get_data():
|
||||
"type": "doctype",
|
||||
"name": "Issue Priority",
|
||||
"description": _("Issue Priority."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Communication",
|
||||
"description": _("Communication log."),
|
||||
"onboard": 1,
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -97,4 +91,15 @@ def get_data():
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Settings"),
|
||||
"icon": "fa fa-list",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Support Settings",
|
||||
"label": _("Support Settings"),
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
@ -488,8 +488,7 @@ class AccountsController(TransactionBase):
|
||||
return res
|
||||
|
||||
def is_inclusive_tax(self):
|
||||
is_inclusive = cint(frappe.db.get_single_value("Accounts Settings",
|
||||
"show_inclusive_tax_in_print"))
|
||||
is_inclusive = cint(frappe.db.get_single_value("Accounts Settings", "show_inclusive_tax_in_print"))
|
||||
|
||||
if is_inclusive:
|
||||
is_inclusive = 0
|
||||
@ -576,9 +575,9 @@ class AccountsController(TransactionBase):
|
||||
unlink_ref_doc_from_payment_entries(self)
|
||||
|
||||
def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield):
|
||||
from erpnext.controllers.status_updater import get_tolerance_for
|
||||
item_tolerance = {}
|
||||
global_tolerance = None
|
||||
from erpnext.controllers.status_updater import get_allowance_for
|
||||
item_allowance = {}
|
||||
global_qty_allowance, global_amount_allowance = None, None
|
||||
|
||||
for item in self.get("items"):
|
||||
if item.get(item_ref_dn):
|
||||
@ -586,26 +585,27 @@ class AccountsController(TransactionBase):
|
||||
item.get(item_ref_dn), based_on), self.precision(based_on, item))
|
||||
if not ref_amt:
|
||||
frappe.msgprint(
|
||||
_("Warning: System will not check overbilling since amount for Item {0} in {1} is zero").format(
|
||||
item.item_code, ref_dt))
|
||||
_("Warning: System will not check overbilling since amount for Item {0} in {1} is zero")
|
||||
.format(item.item_code, ref_dt))
|
||||
else:
|
||||
already_billed = frappe.db.sql("""select sum(%s) from `tab%s`
|
||||
where %s=%s and docstatus=1 and parent != %s""" %
|
||||
(based_on, self.doctype + " Item", item_ref_dn, '%s', '%s'),
|
||||
already_billed = frappe.db.sql("""
|
||||
select sum(%s)
|
||||
from `tab%s`
|
||||
where %s=%s and docstatus=1 and parent != %s
|
||||
""" % (based_on, self.doctype + " Item", item_ref_dn, '%s', '%s'),
|
||||
(item.get(item_ref_dn), self.name))[0][0]
|
||||
|
||||
total_billed_amt = flt(flt(already_billed) + flt(item.get(based_on)),
|
||||
self.precision(based_on, item))
|
||||
|
||||
tolerance, item_tolerance, global_tolerance = get_tolerance_for(item.item_code,
|
||||
item_tolerance, global_tolerance)
|
||||
allowance, item_allowance, global_qty_allowance, global_amount_allowance = \
|
||||
get_allowance_for(item.item_code, item_allowance, global_qty_allowance, global_amount_allowance, "amount")
|
||||
|
||||
max_allowed_amt = flt(ref_amt * (100 + tolerance) / 100)
|
||||
max_allowed_amt = flt(ref_amt * (100 + allowance) / 100)
|
||||
|
||||
if total_billed_amt - max_allowed_amt > 0.01:
|
||||
frappe.throw(_(
|
||||
"Cannot overbill for Item {0} in row {1} more than {2}. To allow over-billing, please set in Stock Settings").format(
|
||||
item.item_code, item.idx, max_allowed_amt))
|
||||
frappe.throw(_("Cannot overbill for Item {0} in row {1} more than {2}. To allow over-billing, please set in Stock Settings")
|
||||
.format(item.item_code, item.idx, max_allowed_amt))
|
||||
|
||||
def get_company_default(self, fieldname):
|
||||
from erpnext.accounts.utils import get_company_default
|
||||
@ -615,9 +615,10 @@ class AccountsController(TransactionBase):
|
||||
stock_items = []
|
||||
item_codes = list(set(item.item_code for item in self.get("items")))
|
||||
if item_codes:
|
||||
stock_items = [r[0] for r in frappe.db.sql("""select name
|
||||
from `tabItem` where name in (%s) and is_stock_item=1""" % \
|
||||
(", ".join((["%s"] * len(item_codes))),), item_codes)]
|
||||
stock_items = [r[0] for r in frappe.db.sql("""
|
||||
select name from `tabItem`
|
||||
where name in (%s) and is_stock_item=1
|
||||
""" % (", ".join((["%s"] * len(item_codes))),), item_codes)]
|
||||
|
||||
return stock_items
|
||||
|
||||
|
@ -7,6 +7,8 @@ from frappe.utils import flt, comma_or, nowdate, getdate
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
|
||||
class OverAllowanceError(frappe.ValidationError): pass
|
||||
|
||||
def validate_status(status, options):
|
||||
if status not in options:
|
||||
frappe.throw(_("Status must be one of {0}").format(comma_or(options)))
|
||||
@ -43,16 +45,6 @@ status_map = {
|
||||
["Closed", "eval:self.status=='Closed'"],
|
||||
["On Hold", "eval:self.status=='On Hold'"],
|
||||
],
|
||||
"Sales Invoice": [
|
||||
["Draft", None],
|
||||
["Submitted", "eval:self.docstatus==1"],
|
||||
["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"],
|
||||
["Return", "eval:self.is_return==1 and self.docstatus==1"],
|
||||
["Credit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1"],
|
||||
["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"],
|
||||
["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"],
|
||||
["Cancelled", "eval:self.docstatus==2"],
|
||||
],
|
||||
"Purchase Invoice": [
|
||||
["Draft", None],
|
||||
["Submitted", "eval:self.docstatus==1"],
|
||||
@ -154,8 +146,9 @@ class StatusUpdater(Document):
|
||||
|
||||
def validate_qty(self):
|
||||
"""Validates qty at row level"""
|
||||
self.tolerance = {}
|
||||
self.global_tolerance = None
|
||||
self.item_allowance = {}
|
||||
self.global_qty_allowance = None
|
||||
self.global_amount_allowance = None
|
||||
|
||||
for args in self.status_updater:
|
||||
if "target_ref_field" not in args:
|
||||
@ -186,32 +179,41 @@ class StatusUpdater(Document):
|
||||
|
||||
# if not item[args['target_ref_field']]:
|
||||
# msgprint(_("Note: System will not check over-delivery and over-booking for Item {0} as quantity or amount is 0").format(item.item_code))
|
||||
if args.get('no_tolerance'):
|
||||
if args.get('no_allowance'):
|
||||
item['reduce_by'] = item[args['target_field']] - item[args['target_ref_field']]
|
||||
if item['reduce_by'] > .01:
|
||||
self.limits_crossed_error(args, item)
|
||||
|
||||
elif item[args['target_ref_field']]:
|
||||
self.check_overflow_with_tolerance(item, args)
|
||||
self.check_overflow_with_allowance(item, args)
|
||||
|
||||
def check_overflow_with_tolerance(self, item, args):
|
||||
def check_overflow_with_allowance(self, item, args):
|
||||
"""
|
||||
Checks if there is overflow condering a relaxation tolerance
|
||||
Checks if there is overflow condering a relaxation allowance
|
||||
"""
|
||||
# check if overflow is within tolerance
|
||||
tolerance, self.tolerance, self.global_tolerance = get_tolerance_for(item['item_code'],
|
||||
self.tolerance, self.global_tolerance)
|
||||
qty_or_amount = "qty" if "qty" in args['target_ref_field'] else "amount"
|
||||
|
||||
# check if overflow is within allowance
|
||||
allowance, self.item_allowance, self.global_qty_allowance, self.global_amount_allowance = \
|
||||
get_allowance_for(item['item_code'], self.item_allowance,
|
||||
self.global_qty_allowance, self.global_amount_allowance, qty_or_amount)
|
||||
|
||||
overflow_percent = ((item[args['target_field']] - item[args['target_ref_field']]) /
|
||||
item[args['target_ref_field']]) * 100
|
||||
|
||||
if overflow_percent - tolerance > 0.01:
|
||||
item['max_allowed'] = flt(item[args['target_ref_field']] * (100+tolerance)/100)
|
||||
if overflow_percent - allowance > 0.01:
|
||||
item['max_allowed'] = flt(item[args['target_ref_field']] * (100+allowance)/100)
|
||||
item['reduce_by'] = item[args['target_field']] - item['max_allowed']
|
||||
|
||||
self.limits_crossed_error(args, item)
|
||||
self.limits_crossed_error(args, item, qty_or_amount)
|
||||
|
||||
def limits_crossed_error(self, args, item):
|
||||
def limits_crossed_error(self, args, item, qty_or_amount):
|
||||
'''Raise exception for limits crossed'''
|
||||
if qty_or_amount == "qty":
|
||||
action_msg = _('To allow over receipt / delivery, update "Over Receipt/Delivery Allowance" in Stock Settings or the Item.')
|
||||
else:
|
||||
action_msg = _('To allow over billing, update "Over Billing Allowance" in Accounts Settings or the Item.')
|
||||
|
||||
frappe.throw(_('This document is over limit by {0} {1} for item {4}. Are you making another {3} against the same {2}?')
|
||||
.format(
|
||||
frappe.bold(_(item["target_ref_field"].title())),
|
||||
@ -219,9 +221,7 @@ class StatusUpdater(Document):
|
||||
frappe.bold(_(args.get('target_dt'))),
|
||||
frappe.bold(_(self.doctype)),
|
||||
frappe.bold(item.get('item_code'))
|
||||
) + '<br><br>' +
|
||||
_('To allow over-billing or over-ordering, update "Allowance" in Stock Settings or the Item.'),
|
||||
title = _('Limit Crossed'))
|
||||
) + '<br><br>' + action_msg, OverAllowanceError, title = _('Limit Crossed'))
|
||||
|
||||
def update_qty(self, update_modified=True):
|
||||
"""Updates qty or amount at row level
|
||||
@ -358,19 +358,34 @@ class StatusUpdater(Document):
|
||||
ref_doc.db_set("per_billed", per_billed)
|
||||
ref_doc.set_status(update=True)
|
||||
|
||||
def get_tolerance_for(item_code, item_tolerance={}, global_tolerance=None):
|
||||
def get_allowance_for(item_code, item_allowance={}, global_qty_allowance=None, global_amount_allowance=None, qty_or_amount="qty"):
|
||||
"""
|
||||
Returns the tolerance for the item, if not set, returns global tolerance
|
||||
Returns the allowance for the item, if not set, returns global allowance
|
||||
"""
|
||||
if item_tolerance.get(item_code):
|
||||
return item_tolerance[item_code], item_tolerance, global_tolerance
|
||||
if qty_or_amount == "qty":
|
||||
if item_allowance.get(item_code, frappe._dict()).get("qty"):
|
||||
return item_allowance[item_code].qty, item_allowance, global_qty_allowance, global_amount_allowance
|
||||
else:
|
||||
if item_allowance.get(item_code, frappe._dict()).get("amount"):
|
||||
return item_allowance[item_code].amount, item_allowance, global_qty_allowance, global_amount_allowance
|
||||
|
||||
tolerance = flt(frappe.db.get_value('Item',item_code,'tolerance') or 0)
|
||||
qty_allowance, over_billing_allowance = \
|
||||
frappe.db.get_value('Item', item_code, ['over_delivery_receipt_allowance', 'over_billing_allowance'])
|
||||
|
||||
if not tolerance:
|
||||
if global_tolerance == None:
|
||||
global_tolerance = flt(frappe.db.get_value('Stock Settings', None, 'tolerance'))
|
||||
tolerance = global_tolerance
|
||||
if qty_or_amount == "qty" and not qty_allowance:
|
||||
if global_qty_allowance == None:
|
||||
global_qty_allowance = flt(frappe.db.get_single_value('Stock Settings', 'over_delivery_receipt_allowance'))
|
||||
qty_allowance = global_qty_allowance
|
||||
elif qty_or_amount == "amount" and not over_billing_allowance:
|
||||
if global_amount_allowance == None:
|
||||
global_amount_allowance = flt(frappe.db.get_single_value('Accounts Settings', 'over_billing_allowance'))
|
||||
over_billing_allowance = global_amount_allowance
|
||||
|
||||
item_tolerance[item_code] = tolerance
|
||||
return tolerance, item_tolerance, global_tolerance
|
||||
if qty_or_amount == "qty":
|
||||
allowance = qty_allowance
|
||||
item_allowance.setdefault(item_code, frappe._dict()).setdefault("qty", qty_allowance)
|
||||
else:
|
||||
allowance = over_billing_allowance
|
||||
item_allowance.setdefault(item_code, frappe._dict()).setdefault("amount", over_billing_allowance)
|
||||
|
||||
return allowance, item_allowance, global_qty_allowance, global_amount_allowance
|
||||
|
@ -15,6 +15,9 @@ class calculate_taxes_and_totals(object):
|
||||
self.calculate()
|
||||
|
||||
def calculate(self):
|
||||
if not len(self.doc.get("items")):
|
||||
return
|
||||
|
||||
self.discount_amount_applied = False
|
||||
self._calculate()
|
||||
|
||||
@ -320,7 +323,7 @@ class calculate_taxes_and_totals(object):
|
||||
self._set_in_company_currency(self.doc, ["total_taxes_and_charges", "rounding_adjustment"])
|
||||
|
||||
if self.doc.doctype in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]:
|
||||
self.doc.base_grand_total = flt(self.doc.grand_total * self.doc.conversion_rate) \
|
||||
self.doc.base_grand_total = flt(self.doc.grand_total * self.doc.conversion_rate, self.doc.precision("base_grand_total")) \
|
||||
if self.doc.total_taxes_and_charges else self.doc.base_net_total
|
||||
else:
|
||||
self.doc.taxes_and_charges_added = self.doc.taxes_and_charges_deducted = 0.0
|
||||
|
@ -19,6 +19,10 @@ frappe.ui.form.on("Opportunity", {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (frm.doc.opportunity_from && frm.doc.party_name){
|
||||
frm.trigger('set_contact_link');
|
||||
}
|
||||
},
|
||||
|
||||
onload_post_render: function(frm) {
|
||||
|
@ -7,7 +7,9 @@ import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from requests_oauthlib import OAuth2Session
|
||||
import json, requests
|
||||
import json
|
||||
import requests
|
||||
import traceback
|
||||
from erpnext import encode_company_abbr
|
||||
|
||||
# QuickBooks requires a redirect URL, User will be redirect to this URL
|
||||
@ -32,7 +34,6 @@ def callback(*args, **kwargs):
|
||||
class QuickBooksMigrator(Document):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(QuickBooksMigrator, self).__init__(*args, **kwargs)
|
||||
from pprint import pprint
|
||||
self.oauth = OAuth2Session(
|
||||
client_id=self.client_id,
|
||||
redirect_uri=self.redirect_url,
|
||||
@ -46,7 +47,9 @@ class QuickBooksMigrator(Document):
|
||||
if self.company:
|
||||
# We need a Cost Center corresponding to the selected erpnext Company
|
||||
self.default_cost_center = frappe.db.get_value('Company', self.company, 'cost_center')
|
||||
self.default_warehouse = frappe.get_all('Warehouse', filters={"company": self.company, "is_group": 0})[0]["name"]
|
||||
company_warehouses = frappe.get_all('Warehouse', filters={"company": self.company, "is_group": 0})
|
||||
if company_warehouses:
|
||||
self.default_warehouse = company_warehouses[0].name
|
||||
if self.authorization_endpoint:
|
||||
self.authorization_url = self.oauth.authorization_url(self.authorization_endpoint)[0]
|
||||
|
||||
@ -218,7 +221,7 @@ class QuickBooksMigrator(Document):
|
||||
|
||||
def _fetch_general_ledger(self):
|
||||
try:
|
||||
query_uri = "{}/company/{}/reports/GeneralLedger".format(self.api_endpoint ,self.quickbooks_company_id)
|
||||
query_uri = "{}/company/{}/reports/GeneralLedger".format(self.api_endpoint, self.quickbooks_company_id)
|
||||
response = self._get(query_uri,
|
||||
params={
|
||||
"columns": ",".join(["tx_date", "txn_type", "credit_amt", "debt_amt"]),
|
||||
@ -493,17 +496,17 @@ class QuickBooksMigrator(Document):
|
||||
"account_currency": customer["CurrencyRef"]["value"],
|
||||
"company": self.company,
|
||||
})[0]["name"]
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
receivable_account = None
|
||||
erpcustomer = frappe.get_doc({
|
||||
"doctype": "Customer",
|
||||
"quickbooks_id": customer["Id"],
|
||||
"customer_name" : encode_company_abbr(customer["DisplayName"], self.company),
|
||||
"customer_type" : "Individual",
|
||||
"customer_group" : "Commercial",
|
||||
"customer_name": encode_company_abbr(customer["DisplayName"], self.company),
|
||||
"customer_type": "Individual",
|
||||
"customer_group": "Commercial",
|
||||
"default_currency": customer["CurrencyRef"]["value"],
|
||||
"accounts": [{"company": self.company, "account": receivable_account}],
|
||||
"territory" : "All Territories",
|
||||
"territory": "All Territories",
|
||||
"company": self.company,
|
||||
}).insert()
|
||||
if "BillAddr" in customer:
|
||||
@ -521,7 +524,7 @@ class QuickBooksMigrator(Document):
|
||||
item_dict = {
|
||||
"doctype": "Item",
|
||||
"quickbooks_id": item["Id"],
|
||||
"item_code" : encode_company_abbr(item["Name"], self.company),
|
||||
"item_code": encode_company_abbr(item["Name"], self.company),
|
||||
"stock_uom": "Unit",
|
||||
"is_stock_item": 0,
|
||||
"item_group": "All Item Groups",
|
||||
@ -549,14 +552,14 @@ class QuickBooksMigrator(Document):
|
||||
erpsupplier = frappe.get_doc({
|
||||
"doctype": "Supplier",
|
||||
"quickbooks_id": vendor["Id"],
|
||||
"supplier_name" : encode_company_abbr(vendor["DisplayName"], self.company),
|
||||
"supplier_group" : "All Supplier Groups",
|
||||
"supplier_name": encode_company_abbr(vendor["DisplayName"], self.company),
|
||||
"supplier_group": "All Supplier Groups",
|
||||
"company": self.company,
|
||||
}).insert()
|
||||
if "BillAddr" in vendor:
|
||||
self._create_address(erpsupplier, "Supplier", vendor["BillAddr"], "Billing")
|
||||
if "ShipAddr" in vendor:
|
||||
self._create_address(erpsupplier, "Supplier",vendor["ShipAddr"], "Shipping")
|
||||
self._create_address(erpsupplier, "Supplier", vendor["ShipAddr"], "Shipping")
|
||||
except Exception as e:
|
||||
self._log_error(e)
|
||||
|
||||
@ -1200,7 +1203,7 @@ class QuickBooksMigrator(Document):
|
||||
|
||||
|
||||
def _create_address(self, entity, doctype, address, address_type):
|
||||
try :
|
||||
try:
|
||||
if not frappe.db.exists({"doctype": "Address", "quickbooks_id": address["Id"]}):
|
||||
frappe.get_doc({
|
||||
"doctype": "Address",
|
||||
@ -1252,8 +1255,6 @@ class QuickBooksMigrator(Document):
|
||||
|
||||
|
||||
def _log_error(self, execption, data=""):
|
||||
import json, traceback
|
||||
traceback.print_exc()
|
||||
frappe.log_error(title="QuickBooks Migration Error",
|
||||
message="\n".join([
|
||||
"Data",
|
||||
|
@ -21,9 +21,9 @@ frappe.ui.form.on('Patient', {
|
||||
});
|
||||
}
|
||||
if (frm.doc.patient_name && frappe.user.has_role("Physician")) {
|
||||
frm.add_custom_button(__('Medical Record'), function () {
|
||||
frm.add_custom_button(__('Patient History'), function () {
|
||||
frappe.route_options = { "patient": frm.doc.name };
|
||||
frappe.set_route("medical_record");
|
||||
frappe.set_route("patient_history");
|
||||
},"View");
|
||||
}
|
||||
if (!frm.doc.__islocal && (frappe.user.has_role("Nursing User") || frappe.user.has_role("Physician"))) {
|
||||
|
@ -30,9 +30,9 @@ frappe.ui.form.on('Patient Appointment', {
|
||||
};
|
||||
});
|
||||
if(frm.doc.patient){
|
||||
frm.add_custom_button(__('Medical Record'), function() {
|
||||
frm.add_custom_button(__('Patient History'), function() {
|
||||
frappe.route_options = {"patient": frm.doc.patient};
|
||||
frappe.set_route("medical_record");
|
||||
frappe.set_route("patient_history");
|
||||
},__("View"));
|
||||
}
|
||||
if(frm.doc.status == "Open"){
|
||||
|
@ -41,10 +41,10 @@ frappe.ui.form.on('Patient Encounter', {
|
||||
}
|
||||
});
|
||||
}
|
||||
frm.add_custom_button(__('Medical Record'), function() {
|
||||
frm.add_custom_button(__('Patient History'), function() {
|
||||
if (frm.doc.patient) {
|
||||
frappe.route_options = {"patient": frm.doc.patient};
|
||||
frappe.set_route("medical_record");
|
||||
frappe.set_route("patient_history");
|
||||
} else {
|
||||
frappe.msgprint(__("Please select Patient"));
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
from __future__ import unicode_literals
|
@ -1,182 +0,0 @@
|
||||
frappe.provide("frappe.medical_record");
|
||||
frappe.pages['medical_record'].on_page_load = function(wrapper) {
|
||||
var me = this;
|
||||
var page = frappe.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: 'Medical Record',
|
||||
});
|
||||
|
||||
frappe.breadcrumbs.add("Medical");
|
||||
|
||||
page.main.html(frappe.render_template("patient_select", {}));
|
||||
var patient = frappe.ui.form.make_control({
|
||||
parent: page.main.find(".patient"),
|
||||
df: {
|
||||
fieldtype: "Link",
|
||||
options: "Patient",
|
||||
fieldname: "patient",
|
||||
change: function(){
|
||||
page.main.find(".frappe-list").html("");
|
||||
draw_page(patient.get_value(), me);
|
||||
}
|
||||
},
|
||||
only_input: true,
|
||||
});
|
||||
patient.refresh();
|
||||
|
||||
|
||||
this.page.main.on("click", ".medical_record-message", function() {
|
||||
var doctype = $(this).attr("data-doctype"),
|
||||
docname = $(this).attr("data-docname");
|
||||
|
||||
if (doctype && docname) {
|
||||
frappe.route_options = {
|
||||
scroll_to: { "doctype": doctype, "name": docname }
|
||||
};
|
||||
frappe.set_route(["Form", doctype, docname]);
|
||||
}
|
||||
});
|
||||
|
||||
this.page.sidebar.on("click", ".edit-details", function() {
|
||||
patient = patient.get_value();
|
||||
if (patient) {
|
||||
frappe.set_route(["Form", "Patient", patient]);
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
frappe.pages['medical_record'].refresh = function() {
|
||||
var me = this;
|
||||
|
||||
if(frappe.route_options) {
|
||||
if(frappe.route_options.patient){
|
||||
me.page.main.find(".frappe-list").html("");
|
||||
var patient = frappe.route_options.patient;
|
||||
draw_page(patient,me);
|
||||
me.page.main.find("[data-fieldname='patient']").val(patient);
|
||||
frappe.route_options = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
var show_patient_info = function(patient, me){
|
||||
frappe.call({
|
||||
"method": "erpnext.healthcare.doctype.patient.patient.get_patient_detail",
|
||||
args: {
|
||||
patient: patient
|
||||
},
|
||||
callback: function (r) {
|
||||
var data = r.message;
|
||||
var details = "";
|
||||
if(data.email) details += "<br><b>Email :</b> " + data.email;
|
||||
if(data.mobile) details += "<br><b>Mobile :</b> " + data.mobile;
|
||||
if(data.occupation) details += "<br><b>Occupation :</b> " + data.occupation;
|
||||
if(data.blood_group) details += "<br><b>Blood group : </b> " + data.blood_group;
|
||||
if(data.allergies) details += "<br><br><b>Allergies : </b> "+ data.allergies;
|
||||
if(data.medication) details += "<br><b>Medication : </b> "+ data.medication;
|
||||
if(data.alcohol_current_use) details += "<br><br><b>Alcohol use : </b> "+ data.alcohol_current_use;
|
||||
if(data.alcohol_past_use) details += "<br><b>Alcohol past use : </b> "+ data.alcohol_past_use;
|
||||
if(data.tobacco_current_use) details += "<br><b>Tobacco use : </b> "+ data.tobacco_current_use;
|
||||
if(data.tobacco_past_use) details += "<br><b>Tobacco past use : </b> "+ data.tobacco_past_use;
|
||||
if(data.medical_history) details += "<br><br><b>Medical history : </b> "+ data.medical_history;
|
||||
if(data.surgical_history) details += "<br><b>Surgical history : </b> "+ data.surgical_history;
|
||||
if(data.surrounding_factors) details += "<br><br><b>Occupational hazards : </b> "+ data.surrounding_factors;
|
||||
if(data.other_risk_factors) details += "<br><b>Other risk factors : </b> " + data.other_risk_factors;
|
||||
if(data.patient_details) details += "<br><br><b>More info : </b> " + data.patient_details;
|
||||
|
||||
if(details){
|
||||
details = "<div style='padding-left:10px; font-size:13px;' align='center'></br><b class='text-muted'>Patient Details</b>" + details + "</div>";
|
||||
}
|
||||
|
||||
var vitals = "";
|
||||
if(data.temperature) vitals += "<br><b>Temperature :</b> " + data.temperature;
|
||||
if(data.pulse) vitals += "<br><b>Pulse :</b> " + data.pulse;
|
||||
if(data.respiratory_rate) vitals += "<br><b>Respiratory Rate :</b> " + data.respiratory_rate;
|
||||
if(data.bp) vitals += "<br><b>BP :</b> " + data.bp;
|
||||
if(data.bmi) vitals += "<br><b>BMI :</b> " + data.bmi;
|
||||
if(data.height) vitals += "<br><b>Height :</b> " + data.height;
|
||||
if(data.weight) vitals += "<br><b>Weight :</b> " + data.weight;
|
||||
if(data.signs_date) vitals += "<br><b>Date :</b> " + data.signs_date;
|
||||
|
||||
if(vitals){
|
||||
vitals = "<div style='padding-left:10px; font-size:13px;' align='center'></br><b class='text-muted'>Vital Signs</b>" + vitals + "<br></div>";
|
||||
details = vitals + details;
|
||||
}
|
||||
if(details) details += "<div align='center'><br><a class='btn btn-default btn-sm edit-details'>Edit Details</a></b> </div>";
|
||||
|
||||
me.page.sidebar.addClass("col-sm-3");
|
||||
me.page.sidebar.html(details);
|
||||
me.page.wrapper.find(".layout-main-section-wrapper").addClass("col-sm-9");
|
||||
}
|
||||
});
|
||||
};
|
||||
var draw_page = function(patient, me){
|
||||
frappe.model.with_doctype("Patient Medical Record", function() {
|
||||
me.page.list = new frappe.ui.BaseList({
|
||||
hide_refresh: true,
|
||||
page: me.page,
|
||||
method: 'erpnext.healthcare.page.medical_record.medical_record.get_feed',
|
||||
args: {name: patient},
|
||||
parent: $("<div></div>").appendTo(me.page.main),
|
||||
render_view: function(values) {
|
||||
var me = this;
|
||||
var wrapper = me.page.main.find(".result-list").get(0);
|
||||
values.map(function (value) {
|
||||
var row = $('<div class="list-row">').data("data", value).appendTo($(wrapper)).get(0);
|
||||
new frappe.medical_record.Feed(row, value);
|
||||
});
|
||||
},
|
||||
show_filters: true,
|
||||
doctype: "Patient Medical Record",
|
||||
});
|
||||
show_patient_info(patient, me);
|
||||
me.page.list.run();
|
||||
});
|
||||
};
|
||||
|
||||
frappe.medical_record.last_feed_date = false;
|
||||
frappe.medical_record.Feed = Class.extend({
|
||||
init: function(row, data) {
|
||||
this.scrub_data(data);
|
||||
this.add_date_separator(row, data);
|
||||
if(!data.add_class)
|
||||
data.add_class = "label-default";
|
||||
|
||||
data.link = "";
|
||||
if (data.reference_doctype && data.reference_name) {
|
||||
data.link = frappe.format(data.reference_name, {fieldtype: "Link", options: data.reference_doctype},
|
||||
{label: __(data.reference_doctype)});
|
||||
}
|
||||
|
||||
$(row)
|
||||
.append(frappe.render_template("medical_record_row", data))
|
||||
.find("a").addClass("grey");
|
||||
},
|
||||
scrub_data: function(data) {
|
||||
data.by = frappe.user.full_name(data.owner);
|
||||
data.imgsrc = frappe.utils.get_file_link(frappe.user_info(data.owner).image);
|
||||
|
||||
data.icon = "icon-flag";
|
||||
},
|
||||
add_date_separator: function(row, data) {
|
||||
var date = frappe.datetime.str_to_obj(data.creation);
|
||||
var last = frappe.medical_record.last_feed_date;
|
||||
|
||||
if((last && frappe.datetime.obj_to_str(last) != frappe.datetime.obj_to_str(date)) || (!last)) {
|
||||
var diff = frappe.datetime.get_day_diff(frappe.datetime.get_today(), frappe.datetime.obj_to_str(date));
|
||||
if(diff < 1) {
|
||||
var pdate = 'Today';
|
||||
} else if(diff < 2) {
|
||||
pdate = 'Yesterday';
|
||||
} else {
|
||||
pdate = frappe.datetime.global_date_format(date);
|
||||
}
|
||||
data.date_sep = pdate;
|
||||
data.date_class = pdate=='Today' ? "date-indicator blue" : "date-indicator";
|
||||
} else {
|
||||
data.date_sep = null;
|
||||
data.date_class = "";
|
||||
}
|
||||
frappe.medical_record.last_feed_date = date;
|
||||
}
|
||||
});
|
@ -1,24 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, ESS LLP and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import cint
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_feed(start, page_length, name):
|
||||
"""get feed"""
|
||||
result = frappe.db.sql("""select name, owner, modified, creation,
|
||||
reference_doctype, reference_name, subject
|
||||
from `tabPatient Medical Record`
|
||||
where patient=%(patient)s
|
||||
order by creation desc
|
||||
limit %(start)s, %(page_length)s""",
|
||||
{
|
||||
"start": cint(start),
|
||||
"page_length": cint(page_length),
|
||||
"patient": name
|
||||
}, as_dict=True)
|
||||
|
||||
return result
|
@ -1,21 +0,0 @@
|
||||
<div class="row medical_record-row" data-creation="{%= creation.split(" ")[0] + " 00:00:00" %}">
|
||||
<div class="col-xs-3 text-right medical_record-date"><span class="{%= date_class %}">
|
||||
{%= date_sep || "" %}</span>
|
||||
</div>
|
||||
<div class="col-xs-9 medical_record-message"
|
||||
data-doctype="{%= reference_doctype %}"
|
||||
data-docname="{%= reference_name %}"
|
||||
title="{%= by %} / {%= frappe.datetime.str_to_user(creation) %}">
|
||||
<span class="avatar avatar-small">
|
||||
<div class="avatar-frame" style="background-image: url({{ imgsrc }});"></div>
|
||||
<!-- <img src="{%= imgsrc %}"> -->
|
||||
</span>
|
||||
<span class="small">
|
||||
{% if (reference_doctype && reference_name) { %}
|
||||
{%= __("{0}: {1}", [link, "<strong>" + subject + "</strong>"]) %}
|
||||
{% } else { %}
|
||||
{%= subject %}
|
||||
{% } %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
@ -1,5 +0,0 @@
|
||||
<div class="text-center col-sm-9" style="padding: 40px;">
|
||||
|
||||
<p>{%= __("Select Patient") %}</p>
|
||||
<p class="patient" style="margin: auto; max-width: 300px; margin-bottom: 20px;"></p>
|
||||
</div>
|
0
erpnext/healthcare/page/patient_history/__init__.py
Normal file
0
erpnext/healthcare/page/patient_history/__init__.py
Normal file
@ -14,6 +14,10 @@
|
||||
margin-bottom: -4px;
|
||||
}
|
||||
|
||||
.medical_record-row > * {
|
||||
z-index: -999;
|
||||
}
|
||||
|
||||
.date-indicator {
|
||||
background:none;
|
||||
font-size:12px;
|
||||
@ -35,6 +39,61 @@
|
||||
color: #5e64ff;
|
||||
}
|
||||
|
||||
.div-bg-color {
|
||||
background: #fafbfc;
|
||||
}
|
||||
|
||||
.bg-color-white {
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
.d-flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.width-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.p-3 {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.mt-2 {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.mr-3 {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.Box {
|
||||
background-color: #fff;
|
||||
border: 1px solid #d1d5da;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.flex-column {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
line-height: 1;
|
||||
vertical-align: middle;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.py-3 {
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.border-bottom {
|
||||
border-bottom: 1px #e1e4e8 solid;
|
||||
}
|
||||
|
||||
.date-indicator.blue::after {
|
||||
background: #5e64ff;
|
||||
}
|
||||
@ -65,8 +124,3 @@
|
||||
#page-medical_record .list-filters {
|
||||
display: none ;
|
||||
}
|
||||
|
||||
#page-medical_record .octicon-heart {
|
||||
color: #ff5858;
|
||||
margin: 0px 5px;
|
||||
}
|
20
erpnext/healthcare/page/patient_history/patient_history.html
Normal file
20
erpnext/healthcare/page/patient_history/patient_history.html
Normal file
@ -0,0 +1,20 @@
|
||||
<div class="col-sm-12">
|
||||
<div class="col-sm-3">
|
||||
<p class="text-center">{%= __("Select Patient") %}</p>
|
||||
<p class="patient" style="margin: auto; max-width: 300px; margin-bottom: 20px;"></p>
|
||||
<div class="patient_details" style="z-index=0"></div>
|
||||
</div>
|
||||
<div class="col-sm-9 patient_documents">
|
||||
<div class="col-sm-12">
|
||||
<div class="col-sm-12 show_chart_btns" align="center">
|
||||
</div>
|
||||
<div id="chart" class="col-sm-12 patient_vital_charts">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 patient_documents_list">
|
||||
</div>
|
||||
<div class="col-sm-12 text-center py-3">
|
||||
<a class="btn btn-sm btn-default btn-get-records" style="display:none">More..</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
300
erpnext/healthcare/page/patient_history/patient_history.js
Normal file
300
erpnext/healthcare/page/patient_history/patient_history.js
Normal file
@ -0,0 +1,300 @@
|
||||
frappe.provide("frappe.patient_history");
|
||||
frappe.pages['patient_history'].on_page_load = function(wrapper) {
|
||||
var me = this;
|
||||
var page = frappe.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: 'Patient History',
|
||||
single_column: true
|
||||
});
|
||||
|
||||
frappe.breadcrumbs.add("Healthcare");
|
||||
let pid = '';
|
||||
page.main.html(frappe.render_template("patient_history", {}));
|
||||
var patient = frappe.ui.form.make_control({
|
||||
parent: page.main.find(".patient"),
|
||||
df: {
|
||||
fieldtype: "Link",
|
||||
options: "Patient",
|
||||
fieldname: "patient",
|
||||
change: function(){
|
||||
if(pid != patient.get_value() && patient.get_value()){
|
||||
me.start = 0;
|
||||
me.page.main.find(".patient_documents_list").html("");
|
||||
get_documents(patient.get_value(), me);
|
||||
show_patient_info(patient.get_value(), me);
|
||||
show_patient_vital_charts(patient.get_value(), me, "bp", "mmHg", "Blood Pressure");
|
||||
}
|
||||
pid = patient.get_value();
|
||||
}
|
||||
},
|
||||
only_input: true,
|
||||
});
|
||||
patient.refresh();
|
||||
|
||||
if (frappe.route_options){
|
||||
patient.set_value(frappe.route_options.patient);
|
||||
}
|
||||
|
||||
this.page.main.on("click", ".btn-show-chart", function() {
|
||||
var btn_show_id = $(this).attr("data-show-chart-id"), pts = $(this).attr("data-pts");
|
||||
var title = $(this).attr("data-title");
|
||||
show_patient_vital_charts(patient.get_value(), me, btn_show_id, pts, title);
|
||||
});
|
||||
|
||||
this.page.main.on("click", ".btn-more", function() {
|
||||
var doctype = $(this).attr("data-doctype"), docname = $(this).attr("data-docname");
|
||||
if(me.page.main.find("."+docname).parent().find('.document-html').attr('data-fetched') == "1"){
|
||||
me.page.main.find("."+docname).hide();
|
||||
me.page.main.find("."+docname).parent().find('.document-html').show();
|
||||
}else{
|
||||
if(doctype && docname){
|
||||
let exclude = ["patient", "patient_name", 'patient_sex', "encounter_date"];
|
||||
frappe.call({
|
||||
method: "erpnext.healthcare.utils.render_doc_as_html",
|
||||
args:{
|
||||
doctype: doctype,
|
||||
docname: docname,
|
||||
exclude_fields: exclude
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message){
|
||||
me.page.main.find("."+docname).hide();
|
||||
me.page.main.find("."+docname).parent().find('.document-html').html(r.message.html+"\
|
||||
<div align='center'><a class='btn octicon octicon-chevron-up btn-default btn-xs\
|
||||
btn-less' data-doctype='"+doctype+"' data-docname='"+docname+"'></a></div>");
|
||||
me.page.main.find("."+docname).parent().find('.document-html').show();
|
||||
me.page.main.find("."+docname).parent().find('.document-html').attr('data-fetched', "1");
|
||||
}
|
||||
},
|
||||
freeze: true
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.page.main.on("click", ".btn-less", function() {
|
||||
var docname = $(this).attr("data-docname");
|
||||
me.page.main.find("."+docname).parent().find('.document-id').show();
|
||||
me.page.main.find("."+docname).parent().find('.document-html').hide();
|
||||
});
|
||||
me.start = 0;
|
||||
me.page.main.on("click", ".btn-get-records", function(){
|
||||
get_documents(patient.get_value(), me);
|
||||
});
|
||||
};
|
||||
|
||||
var get_documents = function(patient, me){
|
||||
frappe.call({
|
||||
"method": "erpnext.healthcare.page.patient_history.patient_history.get_feed",
|
||||
args: {
|
||||
name: patient,
|
||||
start: me.start,
|
||||
page_length: 20
|
||||
},
|
||||
callback: function (r) {
|
||||
var data = r.message;
|
||||
if(data.length){
|
||||
add_to_records(me, data);
|
||||
}else{
|
||||
me.page.main.find(".patient_documents_list").append("<div class='text-muted' align='center'><br><br>No more records..<br><br></div>");
|
||||
me.page.main.find(".btn-get-records").hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var add_to_records = function(me, data){
|
||||
var details = "<ul class='nav nav-pills nav-stacked'>";
|
||||
var i;
|
||||
for(i=0; i<data.length; i++){
|
||||
if(data[i].reference_doctype){
|
||||
let label = '';
|
||||
if(data[i].subject){
|
||||
label += "<br/>"+data[i].subject;
|
||||
}
|
||||
data[i] = add_date_separator(data[i]);
|
||||
if(frappe.user_info(data[i].owner).image){
|
||||
data[i].imgsrc = frappe.utils.get_file_link(frappe.user_info(data[i].owner).image);
|
||||
}
|
||||
else{
|
||||
data[i].imgsrc = false;
|
||||
}
|
||||
var time_line_heading = data[i].practitioner ? `${data[i].practitioner} ` : ``;
|
||||
time_line_heading += data[i].reference_doctype + " - "+ data[i].reference_name;
|
||||
details += `<li data-toggle='pill' class='patient_doc_menu'
|
||||
data-doctype='${data[i].reference_doctype}' data-docname='${data[i].reference_name}'>
|
||||
<div class='col-sm-12 d-flex border-bottom py-3'>`;
|
||||
if (data[i].imgsrc){
|
||||
details += `<span class='mr-3'>
|
||||
<img class='avtar' src='${data[i].imgsrc}' width='32' height='32'>
|
||||
</img>
|
||||
</span>`;
|
||||
}else{
|
||||
details += `<span class='mr-3 avatar avatar-small' style='width:32px; height:32px;'><div align='center' class='standard-image'
|
||||
style='background-color: #fafbfc;'>${data[i].practitioner ? data[i].practitioner.charAt(0) : "U"}</div></span>`;
|
||||
}
|
||||
details += `<div class='d-flex flex-column width-full'>
|
||||
<div>
|
||||
`+time_line_heading+` on
|
||||
<span>
|
||||
${data[i].date_sep}
|
||||
</span>
|
||||
</div>
|
||||
<div class='Box p-3 mt-2'>
|
||||
<span class='${data[i].reference_name} document-id'>${label}
|
||||
<div align='center'>
|
||||
<a class='btn octicon octicon-chevron-down btn-default btn-xs btn-more'
|
||||
data-doctype='${data[i].reference_doctype}' data-docname='${data[i].reference_name}'>
|
||||
</a>
|
||||
</div>
|
||||
</span>
|
||||
<span class='document-html' hidden data-fetched="0">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>`;
|
||||
}
|
||||
}
|
||||
details += "</ul>";
|
||||
me.page.main.find(".patient_documents_list").append(details);
|
||||
me.start += data.length;
|
||||
if(data.length===20){
|
||||
me.page.main.find(".btn-get-records").show();
|
||||
}else{
|
||||
me.page.main.find(".btn-get-records").hide();
|
||||
me.page.main.find(".patient_documents_list").append("<div class='text-muted' align='center'><br><br>No more records..<br><br></div>");
|
||||
}
|
||||
};
|
||||
|
||||
var add_date_separator = function(data) {
|
||||
var date = frappe.datetime.str_to_obj(data.creation);
|
||||
|
||||
var diff = frappe.datetime.get_day_diff(frappe.datetime.get_today(), frappe.datetime.obj_to_str(date));
|
||||
if(diff < 1) {
|
||||
var pdate = 'Today';
|
||||
} else if(diff < 2) {
|
||||
pdate = 'Yesterday';
|
||||
} else {
|
||||
pdate = frappe.datetime.global_date_format(date);
|
||||
}
|
||||
data.date_sep = pdate;
|
||||
return data;
|
||||
};
|
||||
|
||||
var show_patient_info = function(patient, me){
|
||||
frappe.call({
|
||||
"method": "erpnext.healthcare.doctype.patient.patient.get_patient_detail",
|
||||
args: {
|
||||
patient: patient
|
||||
},
|
||||
callback: function (r) {
|
||||
var data = r.message;
|
||||
var details = "";
|
||||
if(data.image){
|
||||
details += "<div><img class='thumbnail' width=75% src='"+data.image+"'></div>";
|
||||
}
|
||||
details += "<b>" + data.patient_name +"</b><br>" + data.sex;
|
||||
if(data.email) details += "<br>" + data.email;
|
||||
if(data.mobile) details += "<br>" + data.mobile;
|
||||
if(data.occupation) details += "<br><br><b>Occupation :</b> " + data.occupation;
|
||||
if(data.blood_group) details += "<br><b>Blood group : </b> " + data.blood_group;
|
||||
if(data.allergies) details += "<br><br><b>Allergies : </b> "+ data.allergies.replace("\n", "<br>");
|
||||
if(data.medication) details += "<br><b>Medication : </b> "+ data.medication.replace("\n", "<br>");
|
||||
if(data.alcohol_current_use) details += "<br><br><b>Alcohol use : </b> "+ data.alcohol_current_use;
|
||||
if(data.alcohol_past_use) details += "<br><b>Alcohol past use : </b> "+ data.alcohol_past_use;
|
||||
if(data.tobacco_current_use) details += "<br><b>Tobacco use : </b> "+ data.tobacco_current_use;
|
||||
if(data.tobacco_past_use) details += "<br><b>Tobacco past use : </b> "+ data.tobacco_past_use;
|
||||
if(data.medical_history) details += "<br><br><b>Medical history : </b> "+ data.medical_history.replace("\n", "<br>");
|
||||
if(data.surgical_history) details += "<br><b>Surgical history : </b> "+ data.surgical_history.replace("\n", "<br>");
|
||||
if(data.surrounding_factors) details += "<br><br><b>Occupational hazards : </b> "+ data.surrounding_factors.replace("\n", "<br>");
|
||||
if(data.other_risk_factors) details += "<br><b>Other risk factors : </b> " + data.other_risk_factors.replace("\n", "<br>");
|
||||
if(data.patient_details) details += "<br><br><b>More info : </b> " + data.patient_details.replace("\n", "<br>");
|
||||
|
||||
if(details){
|
||||
details = "<div style='padding-left:10px; font-size:13px;' align='center'>" + details + "</div>";
|
||||
}
|
||||
me.page.main.find(".patient_details").html(details);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var show_patient_vital_charts = function(patient, me, btn_show_id, pts, title) {
|
||||
frappe.call({
|
||||
method: "erpnext.healthcare.utils.get_patient_vitals",
|
||||
args:{
|
||||
patient: patient
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message){
|
||||
var show_chart_btns_html = "<div style='padding-top:5px;'><a class='btn btn-default btn-xs btn-show-chart' \
|
||||
data-show-chart-id='bp' data-pts='mmHg' data-title='Blood Pressure'>Blood Pressure</a>\
|
||||
<a class='btn btn-default btn-xs btn-show-chart' data-show-chart-id='pulse_rate' \
|
||||
data-pts='per Minutes' data-title='Respiratory/Pulse Rate'>Respiratory/Pulse Rate</a>\
|
||||
<a class='btn btn-default btn-xs btn-show-chart' data-show-chart-id='temperature' \
|
||||
data-pts='°C or °F' data-title='Temperature'>Temperature</a>\
|
||||
<a class='btn btn-default btn-xs btn-show-chart' data-show-chart-id='bmi' \
|
||||
data-pts='bmi' data-title='BMI'>BMI</a></div>";
|
||||
me.page.main.find(".show_chart_btns").html(show_chart_btns_html);
|
||||
var data = r.message;
|
||||
let labels = [], datasets = [];
|
||||
let bp_systolic = [], bp_diastolic = [], temperature = [];
|
||||
let pulse = [], respiratory_rate = [], bmi = [], height = [], weight = [];
|
||||
for(var i=0; i<data.length; i++){
|
||||
labels.push(data[i].signs_date+"||"+data[i].signs_time);
|
||||
if(btn_show_id=="bp"){
|
||||
bp_systolic.push(data[i].bp_systolic);
|
||||
bp_diastolic.push(data[i].bp_diastolic);
|
||||
}
|
||||
if(btn_show_id=="temperature"){
|
||||
temperature.push(data[i].temperature);
|
||||
}
|
||||
if(btn_show_id=="pulse_rate"){
|
||||
pulse.push(data[i].pulse);
|
||||
respiratory_rate.push(data[i].respiratory_rate);
|
||||
}
|
||||
if(btn_show_id=="bmi"){
|
||||
bmi.push(data[i].bmi);
|
||||
height.push(data[i].height);
|
||||
weight.push(data[i].weight);
|
||||
}
|
||||
}
|
||||
if(btn_show_id=="temperature"){
|
||||
datasets.push({name: "Temperature", values: temperature, chartType:'line'});
|
||||
}
|
||||
if(btn_show_id=="bmi"){
|
||||
datasets.push({name: "BMI", values: bmi, chartType:'line'});
|
||||
datasets.push({name: "Height", values: height, chartType:'line'});
|
||||
datasets.push({name: "Weight", values: weight, chartType:'line'});
|
||||
}
|
||||
if(btn_show_id=="bp"){
|
||||
datasets.push({name: "BP Systolic", values: bp_systolic, chartType:'line'});
|
||||
datasets.push({name: "BP Diastolic", values: bp_diastolic, chartType:'line'});
|
||||
}
|
||||
if(btn_show_id=="pulse_rate"){
|
||||
datasets.push({name: "Heart Rate / Pulse", values: pulse, chartType:'line'});
|
||||
datasets.push({name: "Respiratory Rate", values: respiratory_rate, chartType:'line'});
|
||||
}
|
||||
new Chart( ".patient_vital_charts", {
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: datasets
|
||||
},
|
||||
|
||||
title: title,
|
||||
type: 'axis-mixed', // 'axis-mixed', 'bar', 'line', 'pie', 'percentage'
|
||||
height: 150,
|
||||
colors: ['purple', '#ffa3ef', 'light-blue'],
|
||||
|
||||
tooltipOptions: {
|
||||
formatTooltipX: d => (d + '').toUpperCase(),
|
||||
formatTooltipY: d => d + ' ' + pts,
|
||||
}
|
||||
});
|
||||
}else{
|
||||
me.page.main.find(".patient_vital_charts").html("");
|
||||
me.page.main.find(".show_chart_btns").html("");
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
@ -1,18 +1,21 @@
|
||||
{
|
||||
"content": null,
|
||||
"creation": "2016-06-09 11:33:14.025787",
|
||||
"creation": "2018-08-08 17:09:13.816199",
|
||||
"docstatus": 0,
|
||||
"doctype": "Page",
|
||||
"icon": "icon-play",
|
||||
"icon": "",
|
||||
"idx": 0,
|
||||
"modified": "2018-08-06 11:40:39.705660",
|
||||
"modified": "2018-08-08 17:09:55.969424",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "medical_record",
|
||||
"name": "patient_history",
|
||||
"owner": "Administrator",
|
||||
"page_name": "medical_record",
|
||||
"page_name": "patient_history",
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Healthcare Administrator"
|
||||
},
|
||||
{
|
||||
"role": "Physician"
|
||||
}
|
||||
@ -21,5 +24,5 @@
|
||||
"standard": "Yes",
|
||||
"style": null,
|
||||
"system_page": 0,
|
||||
"title": "Medical Record"
|
||||
"title": "Patient History"
|
||||
}
|
39
erpnext/healthcare/page/patient_history/patient_history.py
Normal file
39
erpnext/healthcare/page/patient_history/patient_history.py
Normal file
@ -0,0 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, ESS LLP and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import cint
|
||||
from erpnext.healthcare.utils import render_docs_as_html
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_feed(name, start=0, page_length=20):
|
||||
"""get feed"""
|
||||
result = frappe.db.sql("""select name, owner, creation,
|
||||
reference_doctype, reference_name, subject
|
||||
from `tabPatient Medical Record`
|
||||
where patient=%(patient)s
|
||||
order by creation desc
|
||||
limit %(start)s, %(page_length)s""",
|
||||
{
|
||||
"patient": name,
|
||||
"start": cint(start),
|
||||
"page_length": cint(page_length)
|
||||
}, as_dict=True)
|
||||
return result
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_feed_for_dt(doctype, docname):
|
||||
"""get feed"""
|
||||
result = frappe.db.sql("""select name, owner, modified, creation,
|
||||
reference_doctype, reference_name, subject
|
||||
from `tabPatient Medical Record`
|
||||
where reference_name=%(docname)s and reference_doctype=%(doctype)s
|
||||
order by creation desc""",
|
||||
{
|
||||
"docname": docname,
|
||||
"doctype": doctype
|
||||
}, as_dict=True)
|
||||
|
||||
return result
|
@ -429,3 +429,116 @@ def get_children(doctype, parent, company, is_root=False):
|
||||
occupancy_msg = str(occupied) + " Occupied out of " + str(occupancy_total)
|
||||
each["occupied_out_of_vacant"] = occupancy_msg
|
||||
return hc_service_units
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_patient_vitals(patient, from_date=None, to_date=None):
|
||||
if not patient: return
|
||||
vitals = frappe.db.sql("""select * from `tabVital Signs` where \
|
||||
docstatus=1 and patient=%s order by signs_date, signs_time""", \
|
||||
(patient), as_dict=1)
|
||||
if vitals and vitals[0]:
|
||||
return vitals
|
||||
else:
|
||||
return False
|
||||
|
||||
@frappe.whitelist()
|
||||
def render_docs_as_html(docs):
|
||||
# docs key value pair {doctype: docname}
|
||||
docs_html = "<div class='col-md-12 col-sm-12 text-muted'>"
|
||||
for doc in docs:
|
||||
docs_html += render_doc_as_html(doc['doctype'], doc['docname'])['html'] + "<br/>"
|
||||
return {'html': docs_html}
|
||||
|
||||
@frappe.whitelist()
|
||||
def render_doc_as_html(doctype, docname, exclude_fields = []):
|
||||
#render document as html, three column layout will break
|
||||
doc = frappe.get_doc(doctype, docname)
|
||||
meta = frappe.get_meta(doctype)
|
||||
doc_html = "<div class='col-md-12 col-sm-12'>"
|
||||
section_html = ""
|
||||
section_label = ""
|
||||
html = ""
|
||||
sec_on = False
|
||||
col_on = 0
|
||||
has_data = False
|
||||
for df in meta.fields:
|
||||
#on section break append append previous section and html to doc html
|
||||
if df.fieldtype == "Section Break":
|
||||
if has_data and col_on and sec_on:
|
||||
doc_html += section_html + html + "</div>"
|
||||
elif has_data and not col_on and sec_on:
|
||||
doc_html += "<div class='col-md-12 col-sm-12'\
|
||||
><div class='col-md-12 col-sm-12'>" \
|
||||
+ section_html + html +"</div></div>"
|
||||
while col_on:
|
||||
doc_html += "</div>"
|
||||
col_on -= 1
|
||||
sec_on = True
|
||||
has_data= False
|
||||
col_on = 0
|
||||
section_html = ""
|
||||
html = ""
|
||||
if df.label:
|
||||
section_label = df.label
|
||||
continue
|
||||
#on column break append html to section html or doc html
|
||||
if df.fieldtype == "Column Break":
|
||||
if sec_on and has_data:
|
||||
section_html += "<div class='col-md-12 col-sm-12'\
|
||||
><div class='col-md-6 col\
|
||||
-sm-6'><b>" + section_label + "</b>" + html + "</div><div \
|
||||
class='col-md-6 col-sm-6'>"
|
||||
elif has_data:
|
||||
doc_html += "<div class='col-md-12 col-sm-12'><div class='col-m\
|
||||
d-6 col-sm-6'>" + html + "</div><div class='col-md-6 col-sm-6'>"
|
||||
elif sec_on and not col_on:
|
||||
section_html += "<div class='col-md-6 col-sm-6'>"
|
||||
html = ""
|
||||
col_on += 1
|
||||
if df.label:
|
||||
html += '<br>' + df.label
|
||||
continue
|
||||
#on table iterate in items and create table based on in_list_view, append to section html or doc html
|
||||
if df.fieldtype == "Table":
|
||||
items = doc.get(df.fieldname)
|
||||
if not items: continue
|
||||
child_meta = frappe.get_meta(df.options)
|
||||
if not has_data : has_data = True
|
||||
table_head = ""
|
||||
table_row = ""
|
||||
create_head = True
|
||||
for item in items:
|
||||
table_row += '<tr>'
|
||||
for cdf in child_meta.fields:
|
||||
if cdf.in_list_view:
|
||||
if create_head:
|
||||
table_head += '<th>' + cdf.label + '</th>'
|
||||
if item.get(cdf.fieldname):
|
||||
table_row += '<td>' + str(item.get(cdf.fieldname)) \
|
||||
+ '</td>'
|
||||
else:
|
||||
table_row += '<td></td>'
|
||||
create_head = False
|
||||
table_row += '</tr>'
|
||||
if sec_on:
|
||||
section_html += '<table class="table table-condensed \
|
||||
bordered">' + table_head + table_row + '</table>'
|
||||
else:
|
||||
html += '<table class="table table-condensed table-bordered">' \
|
||||
+ table_head + table_row + '</table>'
|
||||
continue
|
||||
#on other field types add label and value to html
|
||||
if not df.hidden and not df.print_hide and doc.get(df.fieldname) and df.fieldname not in exclude_fields:
|
||||
html += "<br>{0} : {1}".format(df.label or df.fieldname, \
|
||||
doc.get(df.fieldname))
|
||||
if not has_data : has_data = True
|
||||
if sec_on and col_on and has_data:
|
||||
doc_html += section_html + html + "</div></div>"
|
||||
elif sec_on and not col_on and has_data:
|
||||
doc_html += "<div class='col-md-12 col-sm-12'\
|
||||
><div class='col-md-12 col-sm-12'>" \
|
||||
+ section_html + html +"</div></div>"
|
||||
if doc_html:
|
||||
doc_html = "<div class='small'><div class='col-md-12 text-right'><a class='btn btn-default btn-xs' href='#Form/%s/%s'></a></div>" %(doctype, docname) + doc_html + "</div>"
|
||||
|
||||
return {'html': doc_html}
|
||||
|
@ -1,516 +1,124 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "naming_series:",
|
||||
"beta": 0,
|
||||
"creation": "2017-10-17 08:21:50.489773",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"naming_series",
|
||||
"full_name",
|
||||
"status",
|
||||
"transporter",
|
||||
"column_break_2",
|
||||
"employee",
|
||||
"cell_number",
|
||||
"address",
|
||||
"license_details",
|
||||
"license_number",
|
||||
"column_break_8",
|
||||
"issuing_date",
|
||||
"column_break_10",
|
||||
"expiry_date",
|
||||
"driving_license_categories",
|
||||
"driving_license_category"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"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": "Series",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "HR-DRI-.YYYY.-",
|
||||
"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
|
||||
"options": "HR-DRI-.YYYY.-"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "full_name",
|
||||
"fieldtype": "Data",
|
||||
"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": "Full Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"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
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"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": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Active\nSuspended\nLeft",
|
||||
"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
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 1,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Applicable for external driver",
|
||||
"fieldname": "transporter",
|
||||
"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": "Transporter",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Supplier",
|
||||
"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
|
||||
"options": "Supplier"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_2",
|
||||
"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,
|
||||
"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
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "employee",
|
||||
"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": "Employee",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Employee",
|
||||
"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
|
||||
"options": "Employee"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "cell_number",
|
||||
"fieldtype": "Data",
|
||||
"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": "Cellphone Number",
|
||||
"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
|
||||
"label": "Cellphone Number"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "license_details",
|
||||
"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,
|
||||
"label": "License Details",
|
||||
"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
|
||||
"label": "License Details"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "license_number",
|
||||
"fieldtype": "Data",
|
||||
"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": "License Number",
|
||||
"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
|
||||
"label": "License Number"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_8",
|
||||
"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,
|
||||
"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
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "issuing_date",
|
||||
"fieldtype": "Date",
|
||||
"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": "Issuing Date",
|
||||
"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
|
||||
"label": "Issuing Date"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_10",
|
||||
"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,
|
||||
"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
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "expiry_date",
|
||||
"fieldtype": "Date",
|
||||
"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": "Expiry Date",
|
||||
"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
|
||||
"label": "Expiry Date"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "driving_license_categories",
|
||||
"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,
|
||||
"label": "Driving License Categories",
|
||||
"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
|
||||
"label": "Driving License Categories"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "driving_license_category",
|
||||
"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": "Driving License Category",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Driving License Category",
|
||||
"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
|
||||
"options": "Driving License Category"
|
||||
},
|
||||
{
|
||||
"fieldname": "address",
|
||||
"fieldtype": "Link",
|
||||
"label": "Address",
|
||||
"options": "Address"
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-user",
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-10-03 19:53:50.924391",
|
||||
"modified": "2019-07-18 16:29:14.151380",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Driver",
|
||||
@ -518,72 +126,44 @@
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Fleet Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
"share": 1
|
||||
},
|
||||
{
|
||||
"amend": 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": "HR User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 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": "HR Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"search_fields": "full_name",
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "full_name",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
"track_changes": 1
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, math
|
||||
from frappe import _
|
||||
from frappe.utils import flt, rounded
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from frappe.model.document import Document
|
||||
|
||||
from erpnext.hr.doctype.employee_loan.employee_loan import get_monthly_repayment_amount, check_repayment_method
|
||||
|
||||
class EmployeeLoanApplication(Document):
|
||||
def validate(self):
|
||||
check_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, self.repayment_periods)
|
||||
self.validate_loan_amount()
|
||||
self.get_repayment_details()
|
||||
|
||||
def validate_loan_amount(self):
|
||||
maximum_loan_limit = frappe.db.get_value('Loan Type', self.loan_type, 'maximum_loan_amount')
|
||||
if maximum_loan_limit and self.loan_amount > maximum_loan_limit:
|
||||
frappe.throw(_("Loan Amount cannot exceed Maximum Loan Amount of {0}").format(maximum_loan_limit))
|
||||
|
||||
def get_repayment_details(self):
|
||||
if self.repayment_method == "Repay Over Number of Periods":
|
||||
self.repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
|
||||
|
||||
if self.repayment_method == "Repay Fixed Amount per Period":
|
||||
monthly_interest_rate = flt(self.rate_of_interest) / (12 *100)
|
||||
if monthly_interest_rate:
|
||||
monthly_interest_amount = self.loan_amount * monthly_interest_rate
|
||||
if monthly_interest_amount >= self.repayment_amount:
|
||||
frappe.throw(_("Repayment amount {} should be greater than monthly interest amount {}").
|
||||
format(self.repayment_amount, monthly_interest_amount))
|
||||
|
||||
self.repayment_periods = math.ceil((math.log(self.repayment_amount) -
|
||||
math.log(self.repayment_amount - (monthly_interest_amount))) /
|
||||
(math.log(1 + monthly_interest_rate)))
|
||||
else:
|
||||
self.repayment_periods = self.loan_amount / self.repayment_amount
|
||||
|
||||
self.calculate_payable_amount()
|
||||
|
||||
def calculate_payable_amount(self):
|
||||
balance_amount = self.loan_amount
|
||||
self.total_payable_amount = 0
|
||||
self.total_payable_interest = 0
|
||||
|
||||
while(balance_amount > 0):
|
||||
interest_amount = rounded(balance_amount * flt(self.rate_of_interest) / (12*100))
|
||||
balance_amount = rounded(balance_amount + interest_amount - self.repayment_amount)
|
||||
|
||||
self.total_payable_interest += interest_amount
|
||||
|
||||
self.total_payable_amount = self.loan_amount + self.total_payable_interest
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_employee_loan(source_name, target_doc = None):
|
||||
doclist = get_mapped_doc("Employee Loan Application", source_name, {
|
||||
"Employee Loan Application": {
|
||||
"doctype": "Employee Loan",
|
||||
"validation": {
|
||||
"docstatus": ["=", 1]
|
||||
}
|
||||
}
|
||||
}, target_doc)
|
||||
|
||||
return doclist
|
@ -15,7 +15,7 @@ frappe.ui.form.on('HR Settings', {
|
||||
let policy = frm.doc.password_policy;
|
||||
if (policy) {
|
||||
if (policy.includes(' ') || policy.includes('--')) {
|
||||
frappe.msgprint(_("Password policy cannot contain spaces or simultaneous hyphens. The format will be restructured automatically"));
|
||||
frappe.msgprint(__("Password policy cannot contain spaces or simultaneous hyphens. The format will be restructured automatically"));
|
||||
}
|
||||
frm.set_value('password_policy', policy.split(new RegExp(" |-", 'g')).filter((token) => token).join('-'));
|
||||
}
|
||||
|
@ -39,31 +39,19 @@ frappe.ui.form.on('Loan', {
|
||||
},
|
||||
|
||||
refresh: function (frm) {
|
||||
if (frm.doc.docstatus == 1 && frm.doc.status == "Sanctioned") {
|
||||
if (frm.doc.docstatus == 1) {
|
||||
if (frm.doc.status == "Sanctioned") {
|
||||
frm.add_custom_button(__('Create Disbursement Entry'), function() {
|
||||
frm.trigger("make_jv");
|
||||
})
|
||||
}
|
||||
if (frm.doc.repayment_schedule) {
|
||||
let total_amount_paid = 0;
|
||||
$.each(frm.doc.repayment_schedule || [], function(i, row) {
|
||||
if (row.paid) {
|
||||
total_amount_paid += row.total_payment;
|
||||
}
|
||||
});
|
||||
frm.set_value("total_amount_paid", total_amount_paid);
|
||||
; }
|
||||
if (frm.doc.docstatus == 1 && frm.doc.repayment_start_date && (frm.doc.applicant_type == 'Member' || frm.doc.repay_from_salary == 0)) {
|
||||
}).addClass("btn-primary");
|
||||
} else if (frm.doc.status == "Disbursed" && frm.doc.repayment_start_date && (frm.doc.applicant_type == 'Member' || frm.doc.repay_from_salary == 0)) {
|
||||
frm.add_custom_button(__('Create Repayment Entry'), function() {
|
||||
frm.trigger("make_repayment_entry");
|
||||
})
|
||||
}).addClass("btn-primary");
|
||||
}
|
||||
}
|
||||
frm.trigger("toggle_fields");
|
||||
},
|
||||
status: function (frm) {
|
||||
frm.toggle_reqd("disbursement_date", frm.doc.status == 'Disbursed')
|
||||
frm.toggle_reqd("repayment_start_date", frm.doc.status == 'Disbursed')
|
||||
},
|
||||
|
||||
make_jv: function (frm) {
|
||||
frappe.call({
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
@ -20,6 +21,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "applicant_type",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
@ -53,6 +55,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "applicant",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"hidden": 0,
|
||||
@ -86,6 +89,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "applicant_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@ -118,6 +122,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "loan_application",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -151,6 +156,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "loan_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -184,6 +190,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@ -215,7 +222,8 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"default": "Today",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "posting_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
@ -248,6 +256,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -282,6 +291,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Sanctioned",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
@ -299,7 +309,7 @@
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -316,6 +326,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.applicant_type==\"Employee\"",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "repay_from_salary",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@ -348,6 +359,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_8",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -380,6 +392,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "loan_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@ -415,6 +428,7 @@
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fetch_from": "loan_type.rate_of_interest",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "rate_of_interest",
|
||||
"fieldtype": "Percent",
|
||||
"hidden": 0,
|
||||
@ -448,6 +462,8 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.status==\"Disbursed\"",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "disbursement_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
@ -480,6 +496,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "repayment_start_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
@ -499,7 +516,7 @@
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
@ -512,6 +529,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_11",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@ -544,6 +562,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Repay Over Number of Periods",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "repayment_method",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
@ -579,6 +598,7 @@
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"depends_on": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "repayment_periods",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
@ -613,6 +633,7 @@
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"depends_on": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "monthly_repayment_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@ -646,6 +667,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "account_info",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -678,6 +700,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "mode_of_payment",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -711,6 +734,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "payment_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -744,6 +768,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_9",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@ -775,6 +800,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "loan_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -808,6 +834,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "interest_income_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -841,6 +868,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_15",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -873,6 +901,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "repayment_schedule",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
@ -906,6 +935,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_17",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -939,6 +969,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "total_payment",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@ -972,6 +1003,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_19",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@ -1004,6 +1036,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "total_interest_payable",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@ -1037,6 +1070,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "total_amount_paid",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@ -1070,6 +1104,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -1106,7 +1141,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-08-21 16:15:53.267145",
|
||||
"modified": "2019-07-10 13:04:20.953694",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Loan",
|
||||
@ -1149,7 +1184,6 @@
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"user_permission_doctypes": "[\"Employee\"]",
|
||||
"write": 0
|
||||
}
|
||||
],
|
||||
|
@ -6,30 +6,34 @@ from __future__ import unicode_literals
|
||||
import frappe, math, json
|
||||
import erpnext
|
||||
from frappe import _
|
||||
from frappe.utils import flt, rounded, add_months, nowdate
|
||||
from frappe.utils import flt, rounded, add_months, nowdate, getdate
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
|
||||
class Loan(AccountsController):
|
||||
def validate(self):
|
||||
check_repayment_method(self.repayment_method, self.loan_amount, self.monthly_repayment_amount, self.repayment_periods)
|
||||
if not self.company:
|
||||
self.company = erpnext.get_default_company()
|
||||
if not self.posting_date:
|
||||
self.posting_date = nowdate()
|
||||
if self.loan_type and not self.rate_of_interest:
|
||||
self.rate_of_interest = frappe.db.get_value("Loan Type", self.loan_type, "rate_of_interest")
|
||||
if self.repayment_method == "Repay Over Number of Periods":
|
||||
self.monthly_repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
|
||||
if self.status == "Repaid/Closed":
|
||||
self.total_amount_paid = self.total_payment
|
||||
if self.status == 'Disbursed' and self.repayment_start_date < self.disbursement_date:
|
||||
frappe.throw(_("Repayment Start Date cannot be before Disbursement Date."))
|
||||
|
||||
if self.status == "Disbursed":
|
||||
validate_repayment_method(self.repayment_method, self.loan_amount, self.monthly_repayment_amount, self.repayment_periods)
|
||||
self.set_missing_fields()
|
||||
self.make_repayment_schedule()
|
||||
self.set_repayment_period()
|
||||
self.calculate_totals()
|
||||
|
||||
def set_missing_fields(self):
|
||||
if not self.company:
|
||||
self.company = erpnext.get_default_company()
|
||||
|
||||
if not self.posting_date:
|
||||
self.posting_date = nowdate()
|
||||
|
||||
if self.loan_type and not self.rate_of_interest:
|
||||
self.rate_of_interest = frappe.db.get_value("Loan Type", self.loan_type, "rate_of_interest")
|
||||
|
||||
if self.repayment_method == "Repay Over Number of Periods":
|
||||
self.monthly_repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
|
||||
|
||||
if self.status == "Repaid/Closed":
|
||||
self.total_amount_paid = self.total_payment
|
||||
|
||||
|
||||
def make_jv_entry(self):
|
||||
self.check_permission('write')
|
||||
journal_entry = frappe.new_doc('Journal Entry')
|
||||
@ -105,20 +109,31 @@ def update_total_amount_paid(doc):
|
||||
frappe.db.set_value("Loan", doc.name, "total_amount_paid", total_amount_paid)
|
||||
|
||||
def update_disbursement_status(doc):
|
||||
disbursement = frappe.db.sql("""select posting_date, ifnull(sum(credit_in_account_currency), 0) as disbursed_amount
|
||||
from `tabGL Entry` where account = %s and against_voucher_type = 'Loan' and against_voucher = %s""",
|
||||
(doc.payment_account, doc.name), as_dict=1)[0]
|
||||
if disbursement.disbursed_amount == doc.loan_amount:
|
||||
frappe.db.set_value("Loan", doc.name , "status", "Disbursed")
|
||||
if disbursement.disbursed_amount == 0:
|
||||
frappe.db.set_value("Loan", doc.name , "status", "Sanctioned")
|
||||
if disbursement.disbursed_amount > doc.loan_amount:
|
||||
frappe.throw(_("Disbursed Amount cannot be greater than Loan Amount {0}").format(doc.loan_amount))
|
||||
if disbursement.disbursed_amount > 0:
|
||||
frappe.db.set_value("Loan", doc.name , "disbursement_date", disbursement.posting_date)
|
||||
frappe.db.set_value("Loan", doc.name , "repayment_start_date", disbursement.posting_date)
|
||||
disbursement = frappe.db.sql("""
|
||||
select posting_date, ifnull(sum(credit_in_account_currency), 0) as disbursed_amount
|
||||
from `tabGL Entry`
|
||||
where account = %s and against_voucher_type = 'Loan' and against_voucher = %s
|
||||
""", (doc.payment_account, doc.name), as_dict=1)[0]
|
||||
|
||||
def check_repayment_method(repayment_method, loan_amount, monthly_repayment_amount, repayment_periods):
|
||||
disbursement_date = None
|
||||
if not disbursement or disbursement.disbursed_amount == 0:
|
||||
status = "Sanctioned"
|
||||
elif disbursement.disbursed_amount == doc.loan_amount:
|
||||
disbursement_date = disbursement.posting_date
|
||||
status = "Disbursed"
|
||||
elif disbursement.disbursed_amount > doc.loan_amount:
|
||||
frappe.throw(_("Disbursed Amount cannot be greater than Loan Amount {0}").format(doc.loan_amount))
|
||||
|
||||
if status == 'Disbursed' and getdate(disbursement_date) > getdate(frappe.db.get_value("Loan", doc.name, "repayment_start_date")):
|
||||
frappe.throw(_("Disbursement Date cannot be after Loan Repayment Start Date"))
|
||||
|
||||
frappe.db.sql("""
|
||||
update `tabLoan`
|
||||
set status = %s, disbursement_date = %s
|
||||
where name = %s
|
||||
""", (status, disbursement_date, doc.name))
|
||||
|
||||
def validate_repayment_method(repayment_method, loan_amount, monthly_repayment_amount, repayment_periods):
|
||||
if repayment_method == "Repay Over Number of Periods" and not repayment_periods:
|
||||
frappe.throw(_("Please enter Repayment Periods"))
|
||||
|
||||
|
@ -23,9 +23,8 @@ frappe.ui.form.on('Loan Application', {
|
||||
},
|
||||
add_toolbar_buttons: function(frm) {
|
||||
if (frm.doc.status == "Approved") {
|
||||
frm.add_custom_button(__('Loan'), function() {
|
||||
frm.add_custom_button(__('Create Loan'), function() {
|
||||
frappe.call({
|
||||
type: "GET",
|
||||
method: "erpnext.hr.doctype.loan_application.loan_application.make_loan",
|
||||
args: {
|
||||
"source_name": frm.doc.name
|
||||
@ -37,7 +36,7 @@ frappe.ui.form.on('Loan Application', {
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}).addClass("btn-primary");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -9,11 +9,11 @@ from frappe.utils import flt, rounded
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from frappe.model.document import Document
|
||||
|
||||
from erpnext.hr.doctype.loan.loan import get_monthly_repayment_amount, check_repayment_method
|
||||
from erpnext.hr.doctype.loan.loan import get_monthly_repayment_amount, validate_repayment_method
|
||||
|
||||
class LoanApplication(Document):
|
||||
def validate(self):
|
||||
check_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, self.repayment_periods)
|
||||
validate_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, self.repayment_periods)
|
||||
self.validate_loan_amount()
|
||||
self.get_repayment_details()
|
||||
|
||||
@ -29,9 +29,12 @@ class LoanApplication(Document):
|
||||
if self.repayment_method == "Repay Fixed Amount per Period":
|
||||
monthly_interest_rate = flt(self.rate_of_interest) / (12 *100)
|
||||
if monthly_interest_rate:
|
||||
self.repayment_periods = math.ceil((math.log(self.repayment_amount) -
|
||||
math.log(self.repayment_amount - (self.loan_amount*monthly_interest_rate))) /
|
||||
(math.log(1 + monthly_interest_rate)))
|
||||
min_repayment_amount = self.loan_amount*monthly_interest_rate
|
||||
if self.repayment_amount - min_repayment_amount < 0:
|
||||
frappe.throw(_("Repayment Amount must be greater than " \
|
||||
+ str(flt(min_repayment_amount, 2))))
|
||||
self.repayment_periods = math.ceil(math.log(self.repayment_amount) -
|
||||
math.log(self.repayment_amount - min_repayment_amount) /(math.log(1 + monthly_interest_rate)))
|
||||
else:
|
||||
self.repayment_periods = self.loan_amount / self.repayment_amount
|
||||
|
||||
|
@ -31,21 +31,22 @@ class TestLoanApplication(unittest.TestCase):
|
||||
"rate_of_interest": 9.2,
|
||||
"loan_amount": 250000,
|
||||
"repayment_method": "Repay Over Number of Periods",
|
||||
"repayment_periods": 24
|
||||
"repayment_periods": 18
|
||||
})
|
||||
loan_application.insert()
|
||||
|
||||
|
||||
def test_loan_totals(self):
|
||||
loan_application = frappe.get_doc("Loan Application", {"applicant":self.applicant})
|
||||
self.assertEquals(loan_application.repayment_amount, 11445)
|
||||
self.assertEquals(loan_application.total_payable_interest, 24657)
|
||||
self.assertEquals(loan_application.total_payable_amount, 274657)
|
||||
|
||||
loan_application.repayment_method = "Repay Fixed Amount per Period"
|
||||
loan_application.repayment_amount = 15000
|
||||
self.assertEqual(loan_application.total_payable_interest, 18599)
|
||||
self.assertEqual(loan_application.total_payable_amount, 268599)
|
||||
self.assertEqual(loan_application.repayment_amount, 14923)
|
||||
|
||||
loan_application.repayment_periods = 24
|
||||
loan_application.save()
|
||||
loan_application.reload()
|
||||
|
||||
self.assertEqual(loan_application.repayment_periods, 18)
|
||||
self.assertEqual(loan_application.total_payable_interest, 18506)
|
||||
self.assertEqual(loan_application.total_payable_amount, 268506)
|
||||
self.assertEqual(loan_application.total_payable_interest, 24657)
|
||||
self.assertEqual(loan_application.total_payable_amount, 274657)
|
||||
self.assertEqual(loan_application.repayment_amount, 11445)
|
||||
|
@ -119,6 +119,8 @@ class PayrollEntry(Document):
|
||||
frappe.enqueue(create_salary_slips_for_employees, timeout=600, employees=emp_list, args=args)
|
||||
else:
|
||||
create_salary_slips_for_employees(emp_list, args, publish_progress=False)
|
||||
# since this method is called via frm.call this doc needs to be updated manually
|
||||
self.reload()
|
||||
|
||||
def get_sal_slip_list(self, ss_status, as_dict=False):
|
||||
"""
|
||||
|
@ -22,7 +22,7 @@ class ShiftType(Document):
|
||||
'skip_auto_attendance':'0',
|
||||
'attendance':('is', 'not set'),
|
||||
'time':('>=', self.process_attendance_after),
|
||||
'shift_actual_start': ('<', self.last_sync_of_checkin),
|
||||
'shift_actual_end': ('<', self.last_sync_of_checkin),
|
||||
'shift': self.name
|
||||
}
|
||||
logs = frappe.db.get_list('Employee Checkin', fields="*", filters=filters, order_by="employee,time")
|
||||
|
@ -592,8 +592,8 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
|
||||
bom_item.idx,
|
||||
item.item_name,
|
||||
sum(bom_item.{qty_field}/ifnull(bom.quantity, 1)) * %(qty)s as qty,
|
||||
item.description,
|
||||
item.image,
|
||||
bom.project,
|
||||
item.stock_uom,
|
||||
item.allow_alternative_item,
|
||||
item_default.default_warehouse,
|
||||
@ -620,17 +620,22 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
|
||||
where_conditions="",
|
||||
is_stock_item=is_stock_item,
|
||||
qty_field="stock_qty",
|
||||
select_columns = """, bom_item.source_warehouse, bom_item.operation, bom_item.include_item_in_manufacturing,
|
||||
select_columns = """, bom_item.source_warehouse, bom_item.operation,
|
||||
bom_item.include_item_in_manufacturing, bom_item.description,
|
||||
(Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s limit 1) as idx""")
|
||||
|
||||
items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True)
|
||||
elif fetch_scrap_items:
|
||||
query = query.format(table="BOM Scrap Item", where_conditions="", select_columns=", bom_item.idx", is_stock_item=is_stock_item, qty_field="stock_qty")
|
||||
query = query.format(table="BOM Scrap Item", where_conditions="",
|
||||
select_columns=", bom_item.idx, item.description", is_stock_item=is_stock_item, qty_field="stock_qty")
|
||||
|
||||
items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True)
|
||||
else:
|
||||
query = query.format(table="BOM Item", where_conditions="", is_stock_item=is_stock_item,
|
||||
qty_field="stock_qty" if fetch_qty_in_stock_uom else "qty",
|
||||
select_columns = ", bom_item.uom, bom_item.conversion_factor, bom_item.source_warehouse, bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing")
|
||||
select_columns = """, bom_item.uom, bom_item.conversion_factor, bom_item.source_warehouse,
|
||||
bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing,
|
||||
bom_item.description """)
|
||||
items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True)
|
||||
|
||||
for item in items:
|
||||
|
@ -505,7 +505,7 @@ def get_material_request_items(row, sales_order,
|
||||
total_qty = row['qty']
|
||||
|
||||
required_qty = 0
|
||||
if ignore_existing_ordered_qty or bin_dict.get("projected_qty") < 0:
|
||||
if ignore_existing_ordered_qty or bin_dict.get("projected_qty", 0) < 0:
|
||||
required_qty = total_qty
|
||||
elif total_qty > bin_dict.get("projected_qty"):
|
||||
required_qty = total_qty - bin_dict.get("projected_qty")
|
||||
|
@ -505,6 +505,7 @@ erpnext.patches.v10_0.update_hub_connector_domain
|
||||
erpnext.patches.v10_0.set_student_party_type
|
||||
erpnext.patches.v10_0.update_project_in_sle
|
||||
erpnext.patches.v10_0.fix_reserved_qty_for_sub_contract
|
||||
erpnext.patches.v10_0.repost_requested_qty_for_non_stock_uom_items
|
||||
erpnext.patches.v11_0.merge_land_unit_with_location
|
||||
erpnext.patches.v11_0.add_index_on_nestedset_doctypes
|
||||
erpnext.patches.v11_0.remove_modules_setup_page
|
||||
@ -602,9 +603,11 @@ erpnext.patches.v11_1.set_salary_details_submittable
|
||||
erpnext.patches.v11_1.rename_depends_on_lwp
|
||||
execute:frappe.delete_doc("Report", "Inactive Items")
|
||||
erpnext.patches.v11_1.delete_scheduling_tool
|
||||
erpnext.patches.v12_0.rename_tolerance_fields
|
||||
erpnext.patches.v12_0.make_custom_fields_for_bank_remittance #14-06-2019
|
||||
execute:frappe.delete_doc_if_exists("Page", "support-analytics")
|
||||
erpnext.patches.v12_0.make_item_manufacturer
|
||||
erpnext.patches.v12_0.remove_patient_medical_record_page
|
||||
erpnext.patches.v11_1.move_customer_lead_to_dynamic_column
|
||||
erpnext.patches.v11_1.set_default_action_for_quality_inspection
|
||||
erpnext.patches.v11_1.delete_bom_browser
|
||||
@ -619,3 +622,4 @@ execute:frappe.delete_doc("DocType", "Project Task")
|
||||
erpnext.patches.v11_1.update_default_supplier_in_item_defaults
|
||||
erpnext.patches.v12_0.update_due_date_in_gle
|
||||
erpnext.patches.v12_0.add_default_buying_selling_terms_in_company
|
||||
erpnext.patches.v12_0.update_ewaybill_field_position
|
||||
|
@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2019, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty
|
||||
|
||||
count=0
|
||||
for item_code, warehouse in frappe.db.sql("""select distinct item_code, warehouse
|
||||
from `tabMaterial Request Item` where docstatus = 1 and stock_uom<>uom"""):
|
||||
try:
|
||||
count += 1
|
||||
update_bin_qty(item_code, warehouse, {
|
||||
"indented_qty": get_indented_qty(item_code, warehouse),
|
||||
})
|
||||
if count % 200 == 0:
|
||||
frappe.db.commit()
|
||||
except:
|
||||
frappe.db.rollback()
|
@ -0,0 +1,7 @@
|
||||
# Copyright (c) 2019
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.delete_doc("Page", "medical_record")
|
15
erpnext/patches/v12_0/rename_tolerance_fields.py
Normal file
15
erpnext/patches/v12_0/rename_tolerance_fields.py
Normal file
@ -0,0 +1,15 @@
|
||||
import frappe
|
||||
from frappe.model.utils.rename_field import rename_field
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("stock", "doctype", "item")
|
||||
frappe.reload_doc("stock", "doctype", "stock_settings")
|
||||
frappe.reload_doc("accounts", "doctype", "accounts_settings")
|
||||
|
||||
rename_field('Stock Settings', "tolerance", "over_delivery_receipt_allowance")
|
||||
rename_field('Item', "tolerance", "over_delivery_receipt_allowance")
|
||||
|
||||
qty_allowance = frappe.db.get_single_value("Stock Settings", "over_delivery_receipt_allowance")
|
||||
frappe.db.set_value("Accounts Settings", None, "over_delivery_receipt_allowance", qty_allowance)
|
||||
|
||||
frappe.db.sql("update tabItem set over_billing_allowance=over_delivery_receipt_allowance")
|
@ -33,10 +33,13 @@ def set_priorities_service_level():
|
||||
service_level_priorities = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"])
|
||||
|
||||
frappe.reload_doc("support", "doctype", "service_level")
|
||||
frappe.reload_doc("support", "doctype", "support_settings")
|
||||
frappe.db.set_value('Support Settings', None, 'track_service_level_agreement', 1)
|
||||
|
||||
for service_level in service_level_priorities:
|
||||
if service_level:
|
||||
doc = frappe.get_doc("Service Level", service_level.name)
|
||||
if not doc.priorities:
|
||||
doc.append("priorities", {
|
||||
"priority": service_level.priority,
|
||||
"default_priority": 1,
|
||||
@ -45,6 +48,7 @@ def set_priorities_service_level():
|
||||
"resolution_time": service_level.resolution_time,
|
||||
"resolution_time_period": service_level.resolution_time_period
|
||||
})
|
||||
doc.flags.ignore_validate = True
|
||||
doc.save(ignore_permissions=True)
|
||||
except frappe.db.TableMissingError:
|
||||
frappe.reload_doc("support", "doctype", "service_level")
|
||||
@ -73,6 +77,7 @@ def set_priorities_service_level_agreement():
|
||||
"resolution_time": service_level_agreement.resolution_time,
|
||||
"resolution_time_period": service_level_agreement.resolution_time_period
|
||||
})
|
||||
doc.flags.ignore_validate = True
|
||||
doc.save(ignore_permissions=True)
|
||||
except frappe.db.TableMissingError:
|
||||
frappe.reload_doc("support", "doctype", "service_level_agreement")
|
@ -13,5 +13,5 @@ def execute():
|
||||
WHERE
|
||||
`tabGL Entry`.voucher_no = `tab{doctype}`.name and `tabGL Entry`.party is not null
|
||||
and `tabGL Entry`.voucher_type in ('Sales Invoice', 'Purchase Invoice', 'Journal Entry')
|
||||
and account in (select name from `tabAccount` where account_type in ('Receivable', 'Payable') )""" #nosec
|
||||
and `tabGL Entry`.account in (select name from `tabAccount` where account_type in ('Receivable', 'Payable'))""" #nosec
|
||||
.format(doctype=doctype))
|
||||
|
27
erpnext/patches/v12_0/update_ewaybill_field_position.py
Normal file
27
erpnext/patches/v12_0/update_ewaybill_field_position.py
Normal file
@ -0,0 +1,27 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from erpnext.regional.india.setup import make_custom_fields
|
||||
|
||||
def execute():
|
||||
company = frappe.get_all('Company', filters = {'country': 'India'})
|
||||
|
||||
if not company:
|
||||
return
|
||||
|
||||
field = frappe.db.get_value("Custom Field", {"dt": "Sales Invoice", "fieldname": "ewaybill"})
|
||||
|
||||
ewaybill_field = frappe.get_doc("Custom Field", field)
|
||||
|
||||
ewaybill_field.flags.ignore_validate = True
|
||||
|
||||
ewaybill_field.update({
|
||||
'fieldname': 'ewaybill',
|
||||
'label': 'e-Way Bill No.',
|
||||
'fieldtype': 'Data',
|
||||
'depends_on': 'eval:(doc.docstatus === 1)',
|
||||
'allow_on_submit': 1,
|
||||
'insert_after': 'tax_id',
|
||||
'translatable': 0
|
||||
})
|
||||
|
||||
ewaybill_field.save()
|
@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import getdate
|
||||
from frappe.desk.doctype.auto_repeat.auto_repeat import get_next_schedule_date
|
||||
from frappe.automation.doctype.auto_repeat.auto_repeat import get_next_schedule_date
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('accounts', 'doctype', 'subscription')
|
||||
|
@ -126,7 +126,8 @@
|
||||
"fieldname": "project_template",
|
||||
"fieldtype": "Link",
|
||||
"label": "From Template",
|
||||
"options": "Project Template"
|
||||
"options": "Project Template",
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "expected_start_date",
|
||||
@ -442,7 +443,7 @@
|
||||
"icon": "fa fa-puzzle-piece",
|
||||
"idx": 29,
|
||||
"max_attachments": 4,
|
||||
"modified": "2019-06-25 16:14:43.887151",
|
||||
"modified": "2019-07-16 11:11:12.343658",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Project",
|
||||
@ -481,6 +482,7 @@
|
||||
"quick_entry": 1,
|
||||
"search_fields": "customer, status, priority, is_active",
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"timeline_field": "customer",
|
||||
"track_seen": 1
|
||||
|
@ -1,333 +1,85 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2016-03-25 02:52:19.283003",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"user",
|
||||
"email",
|
||||
"image",
|
||||
"column_break_2",
|
||||
"full_name",
|
||||
"welcome_email_sent",
|
||||
"view_attachments",
|
||||
"section_break_5",
|
||||
"project_status"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"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": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "user.email",
|
||||
"fieldname": "email",
|
||||
"fieldtype": "Read Only",
|
||||
"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": "Email",
|
||||
"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
|
||||
"label": "Email"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "user.user_image",
|
||||
"fieldname": "image",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 1,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Image",
|
||||
"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
|
||||
"label": "Image"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_2",
|
||||
"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,
|
||||
"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
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "user.full_name",
|
||||
"fetch_from": "user.full_name",
|
||||
"fieldname": "full_name",
|
||||
"fieldtype": "Read Only",
|
||||
"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": "Full Name",
|
||||
"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
|
||||
"label": "Full Name"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "welcome_email_sent",
|
||||
"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": "Welcome email sent",
|
||||
"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
|
||||
"label": "Welcome email sent"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 1,
|
||||
"default": "0",
|
||||
"fieldname": "view_attachments",
|
||||
"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": "View attachments",
|
||||
"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
|
||||
"label": "View attachments"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_5",
|
||||
"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
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:parent.doctype == 'Project Update'",
|
||||
"fieldname": "project_status",
|
||||
"fieldtype": "Text",
|
||||
"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": "Project Status",
|
||||
"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
|
||||
"label": "Project Status"
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-01-17 17:10:05.339735",
|
||||
"modified": "2019-07-15 19:37:26.942294",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Project User",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -42,20 +42,6 @@ frappe.ui.form.on("Task", {
|
||||
frappe.set_route("List", "Expense Claim");
|
||||
}, __("View"), true);
|
||||
}
|
||||
|
||||
if (frm.perm[0].write) {
|
||||
if (!["Closed", "Cancelled"].includes(frm.doc.status)) {
|
||||
frm.add_custom_button(__("Close"), () => {
|
||||
frm.set_value("status", "Closed");
|
||||
frm.save();
|
||||
});
|
||||
} else {
|
||||
frm.add_custom_button(__("Reopen"), () => {
|
||||
frm.set_value("status", "Open");
|
||||
frm.save();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -52,3 +52,13 @@ $.extend(frappe.breadcrumbs.preferred, {
|
||||
"Sales Partner": "Selling",
|
||||
"Brand": "Selling"
|
||||
});
|
||||
|
||||
$.extend(frappe.breadcrumbs.module_map, {
|
||||
'ERPNext Integrations': 'Integrations',
|
||||
'Geo': 'Settings',
|
||||
'Accounts': 'Accounting',
|
||||
'Portal': 'Website',
|
||||
'Utilities': 'Settings',
|
||||
'Shopping Cart': 'Website',
|
||||
'Contacts': 'CRM'
|
||||
});
|
||||
|
@ -141,6 +141,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
|
||||
price_list_rate: function(doc, cdt, cdn) {
|
||||
var item = frappe.get_doc(cdt, cdn);
|
||||
|
||||
frappe.model.round_floats_in(item, ["price_list_rate", "discount_percentage"]);
|
||||
|
||||
let item_rate = item.price_list_rate;
|
||||
@ -154,6 +155,8 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
|
||||
if (item.discount_amount) {
|
||||
item.rate = flt((item.price_list_rate) - (item.discount_amount), precision('rate', item));
|
||||
} else {
|
||||
item.rate = item_rate;
|
||||
}
|
||||
|
||||
this.calculate_taxes_and_totals();
|
||||
@ -343,7 +346,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
update_auto_repeat_reference: function(doc) {
|
||||
if (doc.auto_repeat) {
|
||||
frappe.call({
|
||||
method:"frappe.desk.doctype.auto_repeat.auto_repeat.update_reference",
|
||||
method:"frappe.automation.doctype.auto_repeat.auto_repeat.update_reference",
|
||||
args:{
|
||||
docname: doc.auto_repeat,
|
||||
reference:doc.name
|
||||
|
@ -1424,11 +1424,14 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
me.frm.set_value("taxes", r.message);
|
||||
if(me.frm.doc.shipping_rule && me.frm.doc.taxes) {
|
||||
for (let tax of r.message) {
|
||||
me.frm.add_child("taxes", tax);
|
||||
}
|
||||
|
||||
if(me.frm.doc.shipping_rule) {
|
||||
me.frm.script_manager.trigger("shipping_rule");
|
||||
refresh_field("taxes");
|
||||
} else {
|
||||
me.frm.set_value("taxes", r.message);
|
||||
me.calculate_taxes_and_totals();
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ $.extend(erpnext.queries, {
|
||||
frappe.throw(__("Please set {0}",
|
||||
[__(frappe.meta.get_label(doc.doctype, frappe.dynamic_link.fieldname, doc.name))]));
|
||||
}
|
||||
|
||||
console.log(frappe.dynamic_link)
|
||||
return {
|
||||
query: 'frappe.contacts.doctype.address.address.address_query',
|
||||
filters: {
|
||||
|
@ -180,7 +180,7 @@ $.extend(erpnext.utils, {
|
||||
|
||||
make_subscription: function(doctype, docname) {
|
||||
frappe.call({
|
||||
method: "frappe.desk.doctype.auto_repeat.auto_repeat.make_auto_repeat",
|
||||
method: "frappe.automation.doctype.auto_repeat.auto_repeat.make_auto_repeat",
|
||||
args: {
|
||||
doctype: doctype,
|
||||
docname: docname
|
||||
@ -573,7 +573,6 @@ erpnext.utils.map_current_doc = function(opts) {
|
||||
if(!r.exc) {
|
||||
var doc = frappe.model.sync(r.message);
|
||||
cur_frm.dirty();
|
||||
erpnext.utils.clear_duplicates();
|
||||
cur_frm.refresh();
|
||||
}
|
||||
}
|
||||
@ -604,28 +603,6 @@ erpnext.utils.map_current_doc = function(opts) {
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.utils.clear_duplicates = function() {
|
||||
if(!cur_frm.doc.items) return;
|
||||
const unique_items = new Map();
|
||||
/*
|
||||
Create a Map of items with
|
||||
item_code => [qty, warehouse, batch_no]
|
||||
*/
|
||||
let items = [];
|
||||
|
||||
for (let item of cur_frm.doc.items) {
|
||||
if (!(unique_items.has(item.item_code) && unique_items.get(item.item_code)[0] === item.qty &&
|
||||
unique_items.get(item.item_code)[1] === item.warehouse && unique_items.get(item.item_code)[2] === item.batch_no &&
|
||||
unique_items.get(item.item_code)[3] === item.delivery_date && unique_items.get(item.item_code)[4] === item.required_date &&
|
||||
unique_items.get(item.item_code)[5] === item.rate)) {
|
||||
|
||||
unique_items.set(item.item_code, [item.qty, item.warehouse, item.batch_no, item.delivery_date, item.required_date, item.rate]);
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
cur_frm.doc.items = items;
|
||||
}
|
||||
|
||||
frappe.form.link_formatters['Item'] = function(value, doc) {
|
||||
if(doc && doc.item_name && doc.item_name !== value) {
|
||||
return value? value + ': ' + doc.item_name: doc.item_name;
|
||||
|
@ -145,7 +145,7 @@ erpnext.utils.set_taxes_from_address = function(frm, triggered_from_field, billi
|
||||
erpnext.utils.set_taxes = function(frm, triggered_from_field) {
|
||||
if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
|
||||
if(!erpnext.utils.validate_mandatory(frm, "Lead/Customer/Supplier",
|
||||
frm.doc.customer || frm.doc.supplier || frm.doc.lead, triggered_from_field)) {
|
||||
frm.doc.customer || frm.doc.supplier || frm.doc.lead || frm.doc.party_name, triggered_from_field)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Rating",
|
||||
"options": "1\n2\n3\n4\n5",
|
||||
"options": "\n1\n2\n3\n4\n5",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
@ -44,7 +44,7 @@
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2019-05-26 21:50:48.951264",
|
||||
"modified": "2019-07-13 19:58:08.966141",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Quality Management",
|
||||
"name": "Quality Feedback Parameter",
|
||||
|
@ -26,7 +26,7 @@
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"label": "Status",
|
||||
"options": "Open\nClose"
|
||||
"options": "Open\nClosed"
|
||||
},
|
||||
{
|
||||
"fieldname": "minutes",
|
||||
@ -55,7 +55,7 @@
|
||||
"label": "Minutes"
|
||||
}
|
||||
],
|
||||
"modified": "2019-05-26 23:12:23.364357",
|
||||
"modified": "2019-07-13 19:57:40.500541",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Quality Management",
|
||||
"name": "Quality Meeting",
|
||||
|
@ -354,7 +354,7 @@ def make_custom_fields(update=True):
|
||||
'fieldtype': 'Data',
|
||||
'depends_on': 'eval:(doc.docstatus === 1)',
|
||||
'allow_on_submit': 1,
|
||||
'insert_after': 'project',
|
||||
'insert_after': 'tax_id',
|
||||
'translatable': 0
|
||||
}
|
||||
]
|
||||
|
@ -25,10 +25,6 @@ def get_data():
|
||||
'label': _('Orders'),
|
||||
'items': ['Sales Order', 'Delivery Note', 'Sales Invoice']
|
||||
},
|
||||
{
|
||||
'label': _('Service Level Agreement'),
|
||||
'items': ['Service Level Agreement']
|
||||
},
|
||||
{
|
||||
'label': _('Payments'),
|
||||
'items': ['Payment Entry']
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
frappe.ui.form.on('Installation Note', {
|
||||
setup: function(frm) {
|
||||
frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'}
|
||||
frappe.dynamic_link = {doc: frm.doc, fieldname: 'customer', doctype: 'Customer'}
|
||||
frm.set_query('customer_address', erpnext.queries.address_query);
|
||||
frm.set_query('contact_person', erpnext.queries.contact_query);
|
||||
frm.set_query('customer', erpnext.queries.customer);
|
||||
|
@ -107,7 +107,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
||||
refresh: function(doc, dt, dn) {
|
||||
var me = this;
|
||||
this._super();
|
||||
var allow_delivery = false;
|
||||
let allow_delivery = false;
|
||||
|
||||
if(doc.docstatus==1) {
|
||||
if(this.frm.has_perm("submit")) {
|
||||
@ -132,6 +132,8 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
||||
if(doc.status !== 'Closed') {
|
||||
if(doc.status !== 'On Hold') {
|
||||
|
||||
allow_delivery = this.frm.doc.items.some(item => item.delivered_by_supplier === 0 && item.qty > flt(item.delivered_qty))
|
||||
|
||||
if (this.frm.has_perm("submit")) {
|
||||
if(flt(doc.per_delivered, 6) < 100 || flt(doc.per_billed) < 100) {
|
||||
// hold
|
||||
|
@ -14,7 +14,7 @@ from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty
|
||||
from frappe.desk.notifications import clear_doctype_notifications
|
||||
from frappe.contacts.doctype.address.address import get_company_address
|
||||
from erpnext.controllers.selling_controller import SellingController
|
||||
from frappe.desk.doctype.auto_repeat.auto_repeat import get_next_schedule_date
|
||||
from frappe.automation.doctype.auto_repeat.auto_repeat import get_next_schedule_date
|
||||
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
||||
from erpnext.stock.doctype.item.item import get_item_defaults
|
||||
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
|
||||
@ -492,13 +492,29 @@ def close_or_unclose_sales_orders(names, status):
|
||||
|
||||
frappe.local.message_log = []
|
||||
|
||||
def get_requested_item_qty(sales_order):
|
||||
return frappe._dict(frappe.db.sql("""
|
||||
select sales_order_item, sum(stock_qty)
|
||||
from `tabMaterial Request Item`
|
||||
where docstatus = 1
|
||||
and sales_order = %s
|
||||
group by sales_order_item
|
||||
""", sales_order))
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_material_request(source_name, target_doc=None):
|
||||
requested_item_qty = get_requested_item_qty(source_name)
|
||||
|
||||
def postprocess(source, doc):
|
||||
doc.material_request_type = "Purchase"
|
||||
|
||||
def update_item(source, target, source_parent):
|
||||
# qty is for packed items, because packed items don't have stock_qty field
|
||||
qty = source.get("stock_qty") or source.get("qty")
|
||||
target.project = source_parent.project
|
||||
target.qty = qty - requested_item_qty.get(source.name, 0)
|
||||
target.conversion_factor = 1
|
||||
target.stock_qty = qty - requested_item_qty.get(source.name, 0)
|
||||
|
||||
doc = get_mapped_doc("Sales Order", source_name, {
|
||||
"Sales Order": {
|
||||
@ -523,7 +539,7 @@ def make_material_request(source_name, target_doc=None):
|
||||
"stock_uom": "uom",
|
||||
"stock_qty": "qty"
|
||||
},
|
||||
"condition": lambda doc: not frappe.db.exists('Product Bundle', doc.item_code),
|
||||
"condition": lambda doc: not frappe.db.exists('Product Bundle', doc.item_code) and doc.stock_qty > requested_item_qty.get(doc.name, 0),
|
||||
"postprocess": update_item
|
||||
}
|
||||
}, target_doc, postprocess)
|
||||
|
@ -34,7 +34,7 @@ frappe.listview_settings['Sales Order'] = {
|
||||
"per_delivered,<,100|per_billed,=,100|status,!=,Closed"];
|
||||
}
|
||||
|
||||
} else if ((flt(doc.per_delivered, 6) == 100)
|
||||
} else if ((flt(doc.per_delivered, 6) === 100)
|
||||
&& flt(doc.grand_total) !== 0 && flt(doc.per_billed, 6) < 100 && doc.status !== "Closed") {
|
||||
// to bill
|
||||
|
||||
@ -48,7 +48,7 @@ frappe.listview_settings['Sales Order'] = {
|
||||
|
||||
if(flt(doc.per_billed, 6) < 100 ){
|
||||
return [__("To Deliver and Bill"), "orange", "per_delivered,=,100|per_billed,<,100|status,!=,Closed"];
|
||||
}else if(flt(doc.per_billed, 6) == 100){
|
||||
}else if(flt(doc.per_billed, 6) === 100){
|
||||
return [__("To Deliver"), "orange", "per_delivered,=,100|per_billed,=,100|status,!=,Closed"];
|
||||
}
|
||||
}
|
||||
|
@ -192,8 +192,8 @@ class TestSalesOrder(unittest.TestCase):
|
||||
|
||||
def test_reserved_qty_for_over_delivery(self):
|
||||
make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
|
||||
# set over-delivery tolerance
|
||||
frappe.db.set_value('Item', "_Test Item", 'tolerance', 50)
|
||||
# set over-delivery allowance
|
||||
frappe.db.set_value('Item', "_Test Item", 'over_delivery_receipt_allowance', 50)
|
||||
|
||||
existing_reserved_qty = get_reserved_qty()
|
||||
|
||||
@ -209,8 +209,9 @@ class TestSalesOrder(unittest.TestCase):
|
||||
def test_reserved_qty_for_over_delivery_via_sales_invoice(self):
|
||||
make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
|
||||
|
||||
# set over-delivery tolerance
|
||||
frappe.db.set_value('Item', "_Test Item", 'tolerance', 50)
|
||||
# set over-delivery allowance
|
||||
frappe.db.set_value('Item', "_Test Item", 'over_delivery_receipt_allowance', 50)
|
||||
frappe.db.set_value('Item', "_Test Item", 'over_billing_allowance', 20)
|
||||
|
||||
existing_reserved_qty = get_reserved_qty()
|
||||
|
||||
@ -291,8 +292,8 @@ class TestSalesOrder(unittest.TestCase):
|
||||
make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
|
||||
make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100)
|
||||
|
||||
# set over-delivery tolerance
|
||||
frappe.db.set_value('Item', "_Test Product Bundle Item", 'tolerance', 50)
|
||||
# set over-delivery allowance
|
||||
frappe.db.set_value('Item', "_Test Product Bundle Item", 'over_delivery_receipt_allowance', 50)
|
||||
|
||||
existing_reserved_qty_item1 = get_reserved_qty("_Test Item")
|
||||
existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100")
|
||||
|
@ -16,20 +16,6 @@ frappe.query_reports["Customer Credit Balance"] = {
|
||||
"label": __("Customer"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Customer"
|
||||
},
|
||||
{
|
||||
"fieldname":"cost_center",
|
||||
"label": __("Cost Center"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Cost Center",
|
||||
get_query: () => {
|
||||
var company = frappe.query_report.get_filter_value('company');
|
||||
return {
|
||||
filters: {
|
||||
'company': company
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -21,8 +21,7 @@ def execute(filters=None):
|
||||
row = []
|
||||
|
||||
outstanding_amt = get_customer_outstanding(d.name, filters.get("company"),
|
||||
ignore_outstanding_sales_order=d.bypass_credit_limit_check_at_sales_order,
|
||||
cost_center=filters.get("cost_center"))
|
||||
ignore_outstanding_sales_order=d.bypass_credit_limit_check_at_sales_order)
|
||||
|
||||
credit_limit = get_credit_limit(d.name, filters.get("company"))
|
||||
|
||||
@ -66,3 +65,4 @@ def get_details(filters):
|
||||
return frappe.db.sql("""select name, customer_name,
|
||||
bypass_credit_limit_check_at_sales_order, is_frozen, disabled from `tabCustomer` %s
|
||||
""" % conditions, filters, as_dict=1)
|
||||
|
||||
|
@ -8,7 +8,7 @@ frappe.query_reports["Sales Analytics"] = {
|
||||
fieldname: "tree_type",
|
||||
label: __("Tree Type"),
|
||||
fieldtype: "Select",
|
||||
options: ["Customer Group","Customer","Item Group","Item","Territory"],
|
||||
options: ["Customer Group","Customer","Item Group","Item","Territory","Order Type"],
|
||||
default: "Customer",
|
||||
reqd: 1
|
||||
},
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user