Compare commits

..

1 Commits

Author SHA1 Message Date
RitvikSardana
3714b795d6 fix: POS opening issue because of Product Bundle 2023-09-18 17:22:02 +05:30
1113 changed files with 77126 additions and 47460 deletions

View File

@@ -9,13 +9,6 @@ trim_trailing_whitespace = true
charset = utf-8
# python, js indentation settings
[{*.py,*.js,*.vue,*.css,*.scss,*.html}]
[{*.py,*.js}]
indent_style = tab
indent_size = 4
max_line_length = 110
# JSON files - mostly doctype schema files
[{*.json}]
insert_final_newline = false
indent_style = space
indent_size = 2

View File

@@ -156,7 +156,6 @@
"onScan": true,
"html2canvas": true,
"extend_cscript": true,
"localforage": true,
"Plaid": true
"localforage": true
}
}

View File

@@ -17,7 +17,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 20
node-version: 18
- name: Setup dependencies
run: |

View File

@@ -21,7 +21,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 20
node-version: 14
check-latest: true
- name: Check commit titles

View File

@@ -5,7 +5,7 @@ fail_fast: false
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v4.0.1
hooks:
- id: trailing-whitespace
files: "erpnext.*"
@@ -15,55 +15,6 @@ repos:
args: ['--branch', 'develop']
- id: check-merge-conflict
- id: check-ast
- id: check-json
- id: check-toml
- id: check-yaml
- id: debug-statements
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1
hooks:
- id: prettier
types_or: [javascript, vue, scss]
# Ignore any files that might contain jinja / bundles
exclude: |
(?x)^(
erpnext/public/dist/.*|
cypress/.*|
.*node_modules.*|
.*boilerplate.*|
erpnext/public/js/controllers/.*|
erpnext/templates/pages/order.js|
erpnext/templates/includes/.*|
.*/supplier_quotation.js|
.*/sales_taxes_and_charges_template.js|
.*/purchase_taxes_and_charges_template.js|
.*/subcontracting_order.js|
.*/landed_cost_voucher.js|
.*/payment_entry.js|
.*/loan_interest_accrual.js|
.*/loan_disbursement.js|
.*/loan_application.js|
.*/italy.js|
.*/sales_invoice.js|
.*/subcontracting_receipt.js|
.*/request_for_quotation.js|
.*/pos_profile.js|
.*/opportunity.js|
.*/quotation.js|
.*/sales_common.js|
.*/sales_order.js|
.*/pos_invoice.js|
.*/purchase_invoice.js|
.*/loan_repayment.js|
.*/material_request.js|
.*/purchase_receipt.js|
.*/delivery_note.js|
.*/loan.js|
.*/stock_entry.js|
.*/purchase_order.js|
.*/loan_write_off.js
)$
- repo: https://github.com/PyCQA/flake8
rev: 5.0.4

View File

@@ -1,13 +1,25 @@
module.exports = {
parserPreset: "conventional-changelog-conventionalcommits",
parserPreset: 'conventional-changelog-conventionalcommits',
rules: {
"subject-empty": [2, "never"],
"type-case": [2, "always", "lower-case"],
"type-empty": [2, "never"],
"type-enum": [
'subject-empty': [2, 'never'],
'type-case': [2, 'always', 'lower-case'],
'type-empty': [2, 'never'],
'type-enum': [
2,
"always",
["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "revert", "style", "test"],
'always',
[
'build',
'chore',
'ci',
'docs',
'feat',
'fix',
'perf',
'refactor',
'revert',
'style',
'test',
],
],
},
};

View File

@@ -3,7 +3,7 @@ import inspect
import frappe
__version__ = "14.66.2"
__version__ = "14.34.3"
def get_default_company(user=None):
@@ -13,7 +13,7 @@ def get_default_company(user=None):
if not user:
user = frappe.session.user
companies = get_user_default_as_list("company", user)
companies = get_user_default_as_list(user, "company")
if companies:
default_company = companies[0]
else:

View File

@@ -1,4 +1,4 @@
frappe.provide("frappe.dashboards.chart_sources");
frappe.provide('frappe.dashboards.chart_sources');
frappe.dashboards.chart_sources["Account Balance Timeline"] = {
method: "erpnext.accounts.dashboard_chart_source.account_balance_timeline.account_balance_timeline.get",
@@ -9,14 +9,14 @@ frappe.dashboards.chart_sources["Account Balance Timeline"] = {
fieldtype: "Link",
options: "Company",
default: frappe.defaults.get_user_default("Company"),
reqd: 1,
reqd: 1
},
{
fieldname: "account",
label: __("Account"),
fieldtype: "Link",
options: "Account",
reqd: 1,
reqd: 1
},
],
]
};

View File

@@ -1,32 +1,33 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on("Account", {
setup: function (frm) {
frm.add_fetch("parent_account", "report_type", "report_type");
frm.add_fetch("parent_account", "root_type", "root_type");
frappe.ui.form.on('Account', {
setup: function(frm) {
frm.add_fetch('parent_account', 'report_type', 'report_type');
frm.add_fetch('parent_account', 'root_type', 'root_type');
},
onload: function (frm) {
frm.set_query("parent_account", function (doc) {
onload: function(frm) {
frm.set_query('parent_account', function(doc) {
return {
filters: {
is_group: 1,
company: doc.company,
},
"is_group": 1,
"company": doc.company
}
};
});
},
refresh: function (frm) {
frm.toggle_display("account_name", frm.is_new());
refresh: function(frm) {
frm.toggle_display('account_name', frm.is_new());
// hide fields if group
frm.toggle_display(["account_type", "tax_rate"], cint(frm.doc.is_group) == 0);
frm.toggle_display(['account_type', 'tax_rate'], cint(frm.doc.is_group) == 0);
// disable fields
frm.toggle_enable(["is_group", "company"], false);
frm.toggle_enable(['is_group', 'company'], false);
if (cint(frm.doc.is_group) == 0) {
frm.toggle_display("freeze_account", frm.doc.__onload && frm.doc.__onload.can_freeze_account);
frm.toggle_display('freeze_account', frm.doc.__onload
&& frm.doc.__onload.can_freeze_account);
}
// read-only for root accounts
@@ -37,101 +38,79 @@ frappe.ui.form.on("Account", {
} else {
// credit days and type if customer or supplier
frm.set_intro(null);
frm.trigger("account_type");
frm.trigger('account_type');
// show / hide convert buttons
frm.trigger("add_toolbar_buttons");
frm.trigger('add_toolbar_buttons');
}
if (frm.has_perm("write")) {
frm.add_custom_button(
__("Merge Account"),
function () {
frm.trigger("merge_account");
},
__("Actions")
);
frm.add_custom_button(
__("Update Account Name / Number"),
function () {
frm.trigger("update_account_number");
},
__("Actions")
);
if (frm.has_perm('write')) {
frm.add_custom_button(__('Merge Account'), function () {
frm.trigger("merge_account");
}, __('Actions'));
frm.add_custom_button(__('Update Account Name / Number'), function () {
frm.trigger("update_account_number");
}, __('Actions'));
}
}
},
account_type: function (frm) {
if (frm.doc.is_group == 0) {
frm.toggle_display(["tax_rate"], frm.doc.account_type == "Tax");
frm.toggle_display("warehouse", frm.doc.account_type == "Stock");
frm.toggle_display(['tax_rate'], frm.doc.account_type == 'Tax');
frm.toggle_display('warehouse', frm.doc.account_type == 'Stock');
}
},
add_toolbar_buttons: function (frm) {
frm.add_custom_button(
__("Chart of Accounts"),
() => {
frappe.set_route("Tree", "Account");
},
__("View")
);
add_toolbar_buttons: function(frm) {
frm.add_custom_button(__('Chart of Accounts'), () => {
frappe.set_route("Tree", "Account");
}, __('View'));
if (frm.doc.is_group == 1) {
frm.add_custom_button(
__("Convert to Non-Group"),
function () {
return frappe.call({
doc: frm.doc,
method: "convert_group_to_ledger",
callback: function () {
frm.refresh();
},
});
},
__("Actions")
);
} else if (cint(frm.doc.is_group) == 0 && frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
frm.add_custom_button(
__("General Ledger"),
function () {
frappe.route_options = {
account: frm.doc.name,
from_date: frappe.sys_defaults.year_start_date,
to_date: frappe.sys_defaults.year_end_date,
company: frm.doc.company,
};
frappe.set_route("query-report", "General Ledger");
},
__("View")
);
frm.add_custom_button(__('Convert to Non-Group'), function () {
return frappe.call({
doc: frm.doc,
method: 'convert_group_to_ledger',
callback: function() {
frm.refresh();
}
});
}, __('Actions'));
frm.add_custom_button(
__("Convert to Group"),
function () {
return frappe.call({
doc: frm.doc,
method: "convert_ledger_to_group",
callback: function () {
frm.refresh();
},
});
},
__("Actions")
);
} else if (cint(frm.doc.is_group) == 0
&& frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
frm.add_custom_button(__('General Ledger'), function () {
frappe.route_options = {
"account": frm.doc.name,
"from_date": frappe.sys_defaults.year_start_date,
"to_date": frappe.sys_defaults.year_end_date,
"company": frm.doc.company
};
frappe.set_route("query-report", "General Ledger");
}, __('View'));
frm.add_custom_button(__('Convert to Group'), function () {
return frappe.call({
doc: frm.doc,
method: 'convert_ledger_to_group',
callback: function() {
frm.refresh();
}
});
}, __('Actions'));
}
},
merge_account: function (frm) {
merge_account: function(frm) {
var d = new frappe.ui.Dialog({
title: __("Merge with Existing Account"),
title: __('Merge with Existing Account'),
fields: [
{
label: "Name",
fieldname: "name",
fieldtype: "Data",
reqd: 1,
default: frm.doc.name,
},
"label" : "Name",
"fieldname": "name",
"fieldtype": "Data",
"reqd": 1,
"default": frm.doc.name
}
],
primary_action: function () {
primary_action: function() {
var data = d.get_values();
frappe.call({
method: "erpnext.accounts.doctype.account.account.merge_account",
@@ -139,45 +118,42 @@ frappe.ui.form.on("Account", {
old: frm.doc.name,
new: data.name,
},
callback: function (r) {
if (!r.exc) {
if (r.message) {
callback: function(r) {
if(!r.exc) {
if(r.message) {
frappe.set_route("Form", "Account", r.message);
}
d.hide();
}
},
}
});
},
primary_action_label: __("Merge"),
primary_action_label: __('Merge')
});
d.show();
},
update_account_number: function (frm) {
update_account_number: function(frm) {
var d = new frappe.ui.Dialog({
title: __("Update Account Number / Name"),
title: __('Update Account Number / Name'),
fields: [
{
label: "Account Name",
fieldname: "account_name",
fieldtype: "Data",
reqd: 1,
default: frm.doc.account_name,
"label": "Account Name",
"fieldname": "account_name",
"fieldtype": "Data",
"reqd": 1,
"default": frm.doc.account_name
},
{
label: "Account Number",
fieldname: "account_number",
fieldtype: "Data",
default: frm.doc.account_number,
},
"label": "Account Number",
"fieldname": "account_number",
"fieldtype": "Data",
"default": frm.doc.account_number
}
],
primary_action: function () {
primary_action: function() {
var data = d.get_values();
if (
data.account_number === frm.doc.account_number &&
data.account_name === frm.doc.account_name
) {
if(data.account_number === frm.doc.account_number && data.account_name === frm.doc.account_name) {
d.hide();
return;
}
@@ -187,11 +163,11 @@ frappe.ui.form.on("Account", {
args: {
account_number: data.account_number,
account_name: data.account_name,
name: frm.doc.name,
name: frm.doc.name
},
callback: function (r) {
if (!r.exc) {
if (r.message) {
callback: function(r) {
if(!r.exc) {
if(r.message) {
frappe.set_route("Form", "Account", r.message);
} else {
frm.set_value("account_number", data.account_number);
@@ -199,11 +175,11 @@ frappe.ui.form.on("Account", {
}
d.hide();
}
},
}
});
},
primary_action_label: __("Update"),
primary_action_label: __('Update')
});
d.show();
},
}
});

View File

@@ -58,7 +58,6 @@ class Account(NestedSet):
self.validate_balance_must_be_debit_or_credit()
self.validate_account_currency()
self.validate_root_company_and_sync_account_to_children()
self.validate_receivable_payable_account_type()
def validate_parent(self):
"""Fetch Parent Details and validate parent account"""
@@ -115,24 +114,6 @@ class Account(NestedSet):
"Balance Sheet" if self.root_type in ("Asset", "Liability", "Equity") else "Profit and Loss"
)
def validate_receivable_payable_account_type(self):
doc_before_save = self.get_doc_before_save()
receivable_payable_types = ["Receivable", "Payable"]
if (
doc_before_save
and doc_before_save.account_type in receivable_payable_types
and doc_before_save.account_type != self.account_type
):
# check for ledger entries
if frappe.db.get_all("GL Entry", filters={"account": self.name, "is_cancelled": 0}, limit=1):
msg = _(
"There are ledger entries against this account. Changing {0} to non-{1} in live system will cause incorrect output in 'Accounts {2}' report"
).format(
frappe.bold("Account Type"), doc_before_save.account_type, doc_before_save.account_type
)
frappe.msgprint(msg)
self.add_comment("Comment", msg)
def validate_root_details(self):
# does not exists parent
if frappe.db.exists("Account", self.name):

View File

@@ -1,4 +1,4 @@
frappe.provide("frappe.treeview_settings");
frappe.provide("frappe.treeview_settings")
frappe.treeview_settings["Account"] = {
breadcrumb: "Accounts",
@@ -7,12 +7,12 @@ frappe.treeview_settings["Account"] = {
filters: [
{
fieldname: "company",
fieldtype: "Select",
fieldtype:"Select",
options: erpnext.utils.get_tree_options("company"),
label: __("Company"),
default: erpnext.utils.get_tree_default("company"),
on_change: function () {
var me = frappe.treeview_settings["Account"].treeview;
on_change: function() {
var me = frappe.treeview_settings['Account'].treeview;
var company = me.page.fields_dict.company.get_value();
if (!company) {
frappe.throw(__("Please set a Company"));
@@ -22,36 +22,30 @@ frappe.treeview_settings["Account"] = {
args: {
company: company,
},
callback: function (r) {
if (r.message) {
callback: function(r) {
if(r.message) {
let root_company = r.message.length ? r.message[0] : "";
me.page.fields_dict.root_company.set_value(root_company);
frappe.db.get_value(
"Company",
{ name: company },
"allow_account_creation_against_child_company",
(r) => {
frappe.flags.ignore_root_company_validation =
r.allow_account_creation_against_child_company;
}
);
frappe.db.get_value("Company", {"name": company}, "allow_account_creation_against_child_company", (r) => {
frappe.flags.ignore_root_company_validation = r.allow_account_creation_against_child_company;
});
}
},
}
});
},
}
},
{
fieldname: "root_company",
fieldtype: "Data",
fieldtype:"Data",
label: __("Root Company"),
hidden: true,
disable_onchange: true,
},
disable_onchange: true
}
],
root_label: "Accounts",
get_tree_nodes: "erpnext.accounts.utils.get_children",
on_get_node: function (nodes, deep = false) {
get_tree_nodes: 'erpnext.accounts.utils.get_children',
on_get_node: function(nodes, deep=false) {
if (frappe.boot.user.can_read.indexOf("GL Entry") == -1) return;
let accounts = [];
@@ -63,231 +57,151 @@ frappe.treeview_settings["Account"] = {
}
frappe.db.get_single_value("Accounts Settings", "show_balance_in_coa").then((value) => {
if (value) {
if(value) {
const get_balances = frappe.call({
method: "erpnext.accounts.utils.get_account_balances",
method: 'erpnext.accounts.utils.get_account_balances',
args: {
accounts: accounts,
company: cur_tree.args.company,
company: cur_tree.args.company
},
});
get_balances.then((r) => {
get_balances.then(r => {
if (!r.message || r.message.length == 0) return;
for (let account of r.message) {
const node = cur_tree.nodes && cur_tree.nodes[account.value];
if (!node || node.is_root) continue;
// show Dr if positive since balance is calculated as debit - credit else show Cr
const balance = account.balance_in_account_currency || account.balance;
const dr_or_cr = balance > 0 ? "Dr" : "Cr";
const dr_or_cr = balance > 0 ? "Dr": "Cr";
const format = (value, currency) => format_currency(Math.abs(value), currency);
if (account.balance !== undefined) {
node.parent && node.parent.find(".balance-area").remove();
$(
'<span class="balance-area pull-right">' +
(account.balance_in_account_currency
? format(
account.balance_in_account_currency,
account.account_currency
) + " / "
: "") +
format(account.balance, account.company_currency) +
" " +
dr_or_cr +
"</span>"
).insertBefore(node.$ul);
if (account.balance!==undefined) {
node.parent && node.parent.find('.balance-area').remove();
$('<span class="balance-area pull-right">'
+ (account.balance_in_account_currency ?
(format(account.balance_in_account_currency, account.account_currency) + " / ") : "")
+ format(account.balance, account.company_currency)
+ " " + dr_or_cr
+ '</span>').insertBefore(node.$ul);
}
}
});
}
});
},
add_tree_node: "erpnext.accounts.utils.add_ac",
menu_items: [
add_tree_node: 'erpnext.accounts.utils.add_ac',
menu_items:[
{
label: __("New Company"),
action: function () {
frappe.new_doc("Company", true);
},
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1',
},
label: __('New Company'),
action: function() { frappe.new_doc("Company", true) },
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1'
}
],
fields: [
{
fieldtype: "Data",
fieldname: "account_name",
label: __("New Account Name"),
reqd: true,
description: __(
"Name of new Account. Note: Please don't create accounts for Customers and Suppliers"
),
},
{
fieldtype: "Data",
fieldname: "account_number",
label: __("Account Number"),
description: __("Number of new Account, it will be included in the account name as a prefix"),
},
{
fieldtype: "Check",
fieldname: "is_group",
label: __("Is Group"),
description: __(
"Further accounts can be made under Groups, but entries can be made against non-Groups"
),
},
{
fieldtype: "Select",
fieldname: "root_type",
label: __("Root Type"),
options: ["Asset", "Liability", "Equity", "Income", "Expense"].join("\n"),
depends_on: "eval:doc.is_group && !doc.parent_account",
},
{
fieldtype: "Select",
fieldname: "account_type",
label: __("Account Type"),
options: frappe.get_meta("Account").fields.filter((d) => d.fieldname == "account_type")[0]
.options,
description: __("Optional. This setting will be used to filter in various transactions."),
},
{
fieldtype: "Float",
fieldname: "tax_rate",
label: __("Tax Rate"),
depends_on: 'eval:doc.is_group==0&&doc.account_type=="Tax"',
},
{
fieldtype: "Link",
fieldname: "account_currency",
label: __("Currency"),
options: "Currency",
description: __("Optional. Sets company's default currency, if not specified."),
{fieldtype:'Data', fieldname:'account_name', label:__('New Account Name'), reqd:true,
description: __("Name of new Account. Note: Please don't create accounts for Customers and Suppliers")},
{fieldtype:'Data', fieldname:'account_number', label:__('Account Number'),
description: __("Number of new Account, it will be included in the account name as a prefix")},
{fieldtype:'Check', fieldname:'is_group', label:__('Is Group'),
description: __('Further accounts can be made under Groups, but entries can be made against non-Groups')},
{fieldtype:'Select', fieldname:'root_type', label:__('Root Type'),
options: ['Asset', 'Liability', 'Equity', 'Income', 'Expense'].join('\n'),
depends_on: 'eval:doc.is_group && !doc.parent_account'},
{fieldtype:'Select', fieldname:'account_type', label:__('Account Type'),
options: frappe.get_meta("Account").fields.filter(d => d.fieldname=='account_type')[0].options,
description: __("Optional. This setting will be used to filter in various transactions.")
},
{fieldtype:'Float', fieldname:'tax_rate', label:__('Tax Rate'),
depends_on: 'eval:doc.is_group==0&&doc.account_type=="Tax"'},
{fieldtype:'Link', fieldname:'account_currency', label:__('Currency'), options:"Currency",
description: __("Optional. Sets company's default currency, if not specified.")}
],
ignore_fields: ["parent_account"],
onload: function (treeview) {
frappe.treeview_settings["Account"].treeview = {};
$.extend(frappe.treeview_settings["Account"].treeview, treeview);
ignore_fields:["parent_account"],
onload: function(treeview) {
frappe.treeview_settings['Account'].treeview = {};
$.extend(frappe.treeview_settings['Account'].treeview, treeview);
function get_company() {
return treeview.page.fields_dict.company.get_value();
}
// tools
treeview.page.add_inner_button(
__("Chart of Cost Centers"),
function () {
frappe.set_route("Tree", "Cost Center", { company: get_company() });
},
__("View")
);
treeview.page.add_inner_button(__("Chart of Cost Centers"), function() {
frappe.set_route('Tree', 'Cost Center', {company: get_company()});
}, __('View'));
treeview.page.add_inner_button(
__("Opening Invoice Creation Tool"),
function () {
frappe.set_route("Form", "Opening Invoice Creation Tool", { company: get_company() });
},
__("View")
);
treeview.page.add_inner_button(__("Opening Invoice Creation Tool"), function() {
frappe.set_route('Form', 'Opening Invoice Creation Tool', {company: get_company()});
}, __('View'));
treeview.page.add_inner_button(
__("Period Closing Voucher"),
function () {
frappe.set_route("List", "Period Closing Voucher", { company: get_company() });
},
__("View")
);
treeview.page.add_inner_button(__("Period Closing Voucher"), function() {
frappe.set_route('List', 'Period Closing Voucher', {company: get_company()});
}, __('View'));
treeview.page.add_inner_button(
__("Journal Entry"),
function () {
frappe.new_doc("Journal Entry", { company: get_company() });
},
__("Create")
);
treeview.page.add_inner_button(
__("Company"),
function () {
frappe.new_doc("Company");
},
__("Create")
);
treeview.page.add_inner_button(__("Journal Entry"), function() {
frappe.new_doc('Journal Entry', {company: get_company()});
}, __('Create'));
treeview.page.add_inner_button(__("Company"), function() {
frappe.new_doc('Company');
}, __('Create'));
// financial statements
for (let report of [
"Trial Balance",
"General Ledger",
"Balance Sheet",
"Profit and Loss Statement",
"Cash Flow Statement",
"Accounts Payable",
"Accounts Receivable",
]) {
treeview.page.add_inner_button(
__(report),
function () {
frappe.set_route("query-report", report, { company: get_company() });
},
__("Financial Statements")
);
for (let report of ['Trial Balance', 'General Ledger', 'Balance Sheet',
'Profit and Loss Statement', 'Cash Flow Statement', 'Accounts Payable', 'Accounts Receivable']) {
treeview.page.add_inner_button(__(report), function() {
frappe.set_route('query-report', report, {company: get_company()});
}, __('Financial Statements'));
}
},
post_render: function (treeview) {
frappe.treeview_settings["Account"].treeview["tree"] = treeview.tree;
treeview.page.set_primary_action(
__("New"),
function () {
let root_company = treeview.page.fields_dict.root_company.get_value();
if (root_company) {
frappe.throw(__("Please add the account to root level Company - {0}"), [root_company]);
} else {
treeview.new_node();
}
},
"add"
);
},
post_render: function(treeview) {
frappe.treeview_settings['Account'].treeview["tree"] = treeview.tree;
treeview.page.set_primary_action(__("New"), function() {
let root_company = treeview.page.fields_dict.root_company.get_value();
if(root_company) {
frappe.throw(__("Please add the account to root level Company - {0}"), [root_company]);
} else {
treeview.new_node();
}
}, "add");
},
toolbar: [
{
label: __("Add Child"),
condition: function (node) {
return (
frappe.boot.user.can_create.indexOf("Account") !== -1 &&
(!frappe.treeview_settings[
"Account"
].treeview.page.fields_dict.root_company.get_value() ||
frappe.flags.ignore_root_company_validation) &&
node.expandable &&
!node.hide_add
);
label:__("Add Child"),
condition: function(node) {
return frappe.boot.user.can_create.indexOf("Account") !== -1
&& (!frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value()
|| frappe.flags.ignore_root_company_validation)
&& node.expandable && !node.hide_add;
},
click: function () {
var me = frappe.views.trees["Account"];
click: function() {
var me = frappe.views.trees['Account'];
me.new_node();
},
btnClass: "hidden-xs",
btnClass: "hidden-xs"
},
{
condition: function (node) {
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1;
condition: function(node) {
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1
},
label: __("View Ledger"),
click: function (node, btn) {
click: function(node, btn) {
frappe.route_options = {
account: node.label,
from_date: frappe.sys_defaults.year_start_date,
to_date: frappe.sys_defaults.year_end_date,
company:
frappe.treeview_settings["Account"].treeview.page.fields_dict.company.get_value(),
"account": node.label,
"from_date": frappe.sys_defaults.year_start_date,
"to_date": frappe.sys_defaults.year_end_date,
"company": frappe.treeview_settings['Account'].treeview.page.fields_dict.company.get_value()
};
frappe.set_route("query-report", "General Ledger");
},
btnClass: "hidden-xs",
},
btnClass: "hidden-xs"
}
],
extend_toolbar: true,
};
extend_toolbar: true
}

View File

@@ -53,13 +53,8 @@
},
"II. Forderungen und sonstige Vermögensgegenstände": {
"is_group": 1,
"Forderungen aus Lieferungen und Leistungen mit Kontokorrent": {
"Ford. a. Lieferungen und Leistungen": {
"account_number": "1400",
"account_type": "Receivable",
"is_group": 1
},
"Forderungen aus Lieferungen und Leistungen ohne Kontokorrent": {
"account_number": "1410",
"account_type": "Receivable"
},
"Durchlaufende Posten": {
@@ -185,13 +180,8 @@
},
"IV. Verbindlichkeiten aus Lieferungen und Leistungen": {
"is_group": 1,
"Verbindlichkeiten aus Lieferungen und Leistungen mit Kontokorrent": {
"Verbindlichkeiten aus Lieferungen u. Leistungen": {
"account_number": "1600",
"account_type": "Payable",
"is_group": 1
},
"Verbindlichkeiten aus Lieferungen und Leistungen ohne Kontokorrent": {
"account_number": "1610",
"account_type": "Payable"
}
},

View File

@@ -407,10 +407,13 @@
"Bewertungskorrektur zu Forderungen aus Lieferungen und Leistungen": {
"account_number": "9960"
},
"Forderungen aus Lieferungen und Leistungen mit Kontokorrent": {
"Debitoren": {
"is_group": 1,
"account_number": "10000"
},
"Forderungen aus Lieferungen und Leistungen": {
"account_number": "1200",
"account_type": "Receivable",
"is_group": 1
"account_type": "Receivable"
},
"Forderungen aus Lieferungen und Leistungen ohne Kontokorrent": {
"account_number": "1210"
@@ -1135,15 +1138,18 @@
"Bewertungskorrektur zu Verb. aus Lieferungen und Leistungen": {
"account_number": "9964"
},
"Verb. aus Lieferungen und Leistungen mit Kontokorrent": {
"account_number": "3300",
"account_type": "Payable",
"Kreditoren": {
"account_number": "70000",
"is_group": 1,
"Wareneingangs-Verrechnungskonto" : {
"Wareneingangs-­Verrechnungskonto" : {
"account_number": "70001",
"account_type": "Stock Received But Not Billed"
}
},
"Verb. aus Lieferungen und Leistungen": {
"account_number": "3300",
"account_type": "Payable"
},
"Verb. aus Lieferungen und Leistungen ohne Kontokorrent": {
"account_number": "3310"
},

View File

@@ -37,7 +37,6 @@ def make_closing_entries(closing_entries, voucher_name, company, closing_date):
}
)
cle.flags.ignore_permissions = True
cle.flags.ignore_links = True
cle.submit()

View File

@@ -1,86 +1,74 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Accounting Dimension", {
refresh: function (frm) {
frm.set_query("document_type", () => {
frappe.ui.form.on('Accounting Dimension', {
refresh: function(frm) {
frm.set_query('document_type', () => {
let invalid_doctypes = frappe.model.core_doctypes_list;
invalid_doctypes.push(
"Accounting Dimension",
"Project",
"Cost Center",
"Accounting Dimension Detail",
"Company"
);
invalid_doctypes.push('Accounting Dimension', 'Project',
'Cost Center', 'Accounting Dimension Detail', 'Company');
return {
filters: {
name: ["not in", invalid_doctypes],
},
name: ['not in', invalid_doctypes]
}
};
});
frm.set_query("offsetting_account", "dimension_defaults", function (doc, cdt, cdn) {
frm.set_query("offsetting_account", "dimension_defaults", function(doc, cdt, cdn) {
let d = locals[cdt][cdn];
return {
filters: {
company: d.company,
root_type: ["in", ["Asset", "Liability"]],
is_group: 0,
},
};
is_group: 0
}
}
});
if (!frm.is_new()) {
frm.add_custom_button(__("Show {0}", [frm.doc.document_type]), function () {
frm.add_custom_button(__('Show {0}', [frm.doc.document_type]), function () {
frappe.set_route("List", frm.doc.document_type);
});
let button = frm.doc.disabled ? "Enable" : "Disable";
frm.add_custom_button(__(button), function () {
frm.set_value("disabled", 1 - frm.doc.disabled);
frm.add_custom_button(__(button), function() {
frm.set_value('disabled', 1 - frm.doc.disabled);
frappe.call({
method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension",
args: {
doc: frm.doc,
doc: frm.doc
},
freeze: true,
callback: function (r) {
callback: function(r) {
let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled";
frm.save();
frappe.show_alert({ message: __(message), indicator: "green" });
},
frappe.show_alert({message:__(message), indicator:'green'});
}
});
});
}
},
document_type: function (frm) {
frm.set_value("label", frm.doc.document_type);
frm.set_value("fieldname", frappe.model.scrub(frm.doc.document_type));
document_type: function(frm) {
frappe.db.get_value(
"Accounting Dimension",
{ document_type: frm.doc.document_type },
"document_type",
(r) => {
if (r && r.document_type) {
frm.set_df_property(
"document_type",
"description",
"Document type is already set as dimension"
);
}
frm.set_value('label', 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 && r.document_type) {
frm.set_df_property('document_type', 'description', "Document type is already set as dimension");
}
);
});
},
});
frappe.ui.form.on("Accounting Dimension Detail", {
dimension_defaults_add: function (frm, cdt, cdn) {
frappe.ui.form.on('Accounting Dimension Detail', {
dimension_defaults_add: function(frm, cdt, cdn) {
let row = locals[cdt][cdn];
row.reference_document = frm.doc.document_type;
},
}
});

View File

@@ -236,16 +236,14 @@ def get_accounting_dimensions(as_list=True, filters=None):
def get_checks_for_pl_and_bs_accounts():
if frappe.flags.accounting_dimensions_details is None:
# nosemgrep
frappe.flags.accounting_dimensions_details = frappe.db.sql(
"""SELECT p.label, p.disabled, p.fieldname, c.default_dimension, c.company, c.mandatory_for_pl, c.mandatory_for_bs
FROM `tabAccounting Dimension`p ,`tabAccounting Dimension Detail` c
WHERE p.name = c.parent""",
as_dict=1,
)
dimensions = frappe.db.sql(
"""SELECT p.label, p.disabled, p.fieldname, c.default_dimension, c.company, c.mandatory_for_pl, c.mandatory_for_bs
FROM `tabAccounting Dimension`p ,`tabAccounting Dimension Detail` c
WHERE p.name = c.parent""",
as_dict=1,
)
return frappe.flags.accounting_dimensions_details
return dimensions
def get_dimension_with_children(doctype, dimensions):
@@ -303,30 +301,3 @@ def get_dimensions(with_cost_center_and_project=False):
default_dimensions_map[dimension.company][dimension.fieldname] = dimension.default_dimension
return dimension_filters, default_dimensions_map
def create_accounting_dimensions_for_doctype(doctype):
accounting_dimensions = frappe.db.get_all(
"Accounting Dimension", fields=["fieldname", "label", "document_type", "disabled"]
)
if not accounting_dimensions:
return
for d in accounting_dimensions:
field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname})
if field:
continue
df = {
"fieldname": d.fieldname,
"label": d.label,
"fieldtype": "Link",
"options": d.document_type,
"insert_after": "accounting_dimensions_section",
}
create_custom_field(doctype, df, ignore_validate=True)
frappe.clear_cache(doctype=doctype)

View File

@@ -78,8 +78,6 @@ class TestAccountingDimension(unittest.TestCase):
def tearDown(self):
disable_dimension()
frappe.flags.accounting_dimensions_details = None
frappe.flags.dimension_filter_map = None
def create_dimension():

View File

@@ -1,9 +1,10 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Accounting Dimension Filter", {
refresh: function (frm, cdt, cdn) {
let help_content = `<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
frappe.ui.form.on('Accounting Dimension Filter', {
refresh: function(frm, cdt, cdn) {
let help_content =
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
<tr><td>
<p>
<i class="fa fa-hand-right"></i>
@@ -12,70 +13,67 @@ frappe.ui.form.on("Accounting Dimension Filter", {
</td></tr>
</table>`;
frm.set_df_property("dimension_filter_help", "options", help_content);
frm.set_df_property('dimension_filter_help', 'options', help_content);
},
onload: function (frm) {
frm.set_query("applicable_on_account", "accounts", function () {
onload: function(frm) {
frm.set_query('applicable_on_account', 'accounts', function() {
return {
filters: {
company: frm.doc.company,
},
'company': frm.doc.company
}
};
});
frappe.db.get_list("Accounting Dimension", { fields: ["document_type"] }).then((res) => {
let options = ["Cost Center", "Project"];
frappe.db.get_list('Accounting Dimension',
{fields: ['document_type']}).then((res) => {
let options = ['Cost Center', 'Project'];
res.forEach((dimension) => {
options.push(dimension.document_type);
});
frm.set_df_property("accounting_dimension", "options", options);
frm.set_df_property('accounting_dimension', 'options', options);
});
frm.trigger("setup_filters");
frm.trigger('setup_filters');
},
setup_filters: function (frm) {
setup_filters: function(frm) {
let filters = {};
if (frm.doc.accounting_dimension) {
frappe.model.with_doctype(frm.doc.accounting_dimension, function () {
frappe.model.with_doctype(frm.doc.accounting_dimension, function() {
if (frappe.model.is_tree(frm.doc.accounting_dimension)) {
filters["is_group"] = 0;
filters['is_group'] = 0;
}
if (frappe.meta.has_field(frm.doc.accounting_dimension, "company")) {
filters["company"] = frm.doc.company;
if (frappe.meta.has_field(frm.doc.accounting_dimension, 'company')) {
filters['company'] = frm.doc.company;
}
frm.set_query("dimension_value", "dimensions", function () {
frm.set_query('dimension_value', 'dimensions', function() {
return {
filters: filters,
filters: filters
};
});
});
}
},
accounting_dimension: function (frm) {
accounting_dimension: function(frm) {
frm.clear_table("dimensions");
let row = frm.add_child("dimensions");
row.accounting_dimension = frm.doc.accounting_dimension;
frm.fields_dict["dimensions"].grid.update_docfield_property(
"dimension_value",
"label",
frm.doc.accounting_dimension
);
frm.fields_dict["dimensions"].grid.update_docfield_property("dimension_value", "label", frm.doc.accounting_dimension);
frm.refresh_field("dimensions");
frm.trigger("setup_filters");
frm.trigger('setup_filters');
},
});
frappe.ui.form.on("Allowed Dimension", {
dimensions_add: function (frm, cdt, cdn) {
frappe.ui.form.on('Allowed Dimension', {
dimensions_add: function(frm, cdt, cdn) {
let row = locals[cdt][cdn];
row.accounting_dimension = frm.doc.accounting_dimension;
frm.refresh_field("dimensions");
},
}
});

View File

@@ -38,41 +38,37 @@ class AccountingDimensionFilter(Document):
def get_dimension_filter_map():
if not frappe.flags.get("dimension_filter_map"):
# nosemgrep
filters = frappe.db.sql(
"""
SELECT
a.applicable_on_account, d.dimension_value, p.accounting_dimension,
p.allow_or_restrict, a.is_mandatory
FROM
`tabApplicable On Account` a, `tabAllowed Dimension` d,
`tabAccounting Dimension Filter` p
WHERE
p.name = a.parent
AND p.disabled = 0
AND p.name = d.parent
""",
as_dict=1,
filters = frappe.db.sql(
"""
SELECT
a.applicable_on_account, d.dimension_value, p.accounting_dimension,
p.allow_or_restrict, a.is_mandatory
FROM
`tabApplicable On Account` a, `tabAllowed Dimension` d,
`tabAccounting Dimension Filter` p
WHERE
p.name = a.parent
AND p.disabled = 0
AND p.name = d.parent
""",
as_dict=1,
)
dimension_filter_map = {}
for f in filters:
f.fieldname = scrub(f.accounting_dimension)
build_map(
dimension_filter_map,
f.fieldname,
f.applicable_on_account,
f.dimension_value,
f.allow_or_restrict,
f.is_mandatory,
)
dimension_filter_map = {}
for f in filters:
f.fieldname = scrub(f.accounting_dimension)
build_map(
dimension_filter_map,
f.fieldname,
f.applicable_on_account,
f.dimension_value,
f.allow_or_restrict,
f.is_mandatory,
)
frappe.flags.dimension_filter_map = dimension_filter_map
return frappe.flags.dimension_filter_map
return dimension_filter_map
def build_map(map_object, dimension, account, filter_value, allow_or_restrict, is_mandatory):

View File

@@ -47,8 +47,6 @@ class TestAccountingDimensionFilter(unittest.TestCase):
def tearDown(self):
disable_dimension_filter()
disable_dimension()
frappe.flags.accounting_dimensions_details = None
frappe.flags.dimension_filter_map = None
for si in self.invoice_list:
si.load_from_db()

View File

@@ -1,33 +1,30 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Accounting Period", {
onload: function (frm) {
if (
frm.doc.closed_documents.length === 0 ||
(frm.doc.closed_documents.length === 1 && frm.doc.closed_documents[0].document_type == undefined)
) {
frappe.ui.form.on('Accounting Period', {
onload: function(frm) {
if(frm.doc.closed_documents.length === 0 || (frm.doc.closed_documents.length === 1 && frm.doc.closed_documents[0].document_type == undefined)) {
frappe.call({
method: "get_doctypes_for_closing",
doc: frm.doc,
callback: function (r) {
if (r.message) {
doc:frm.doc,
callback: function(r) {
if(r.message) {
cur_frm.clear_table("closed_documents");
r.message.forEach(function (element) {
r.message.forEach(function(element) {
var c = frm.add_child("closed_documents");
c.document_type = element.document_type;
c.closed = element.closed;
});
refresh_field("closed_documents");
}
},
}
});
}
frm.set_query("document_type", "closed_documents", () => {
return {
query: "erpnext.controllers.queries.get_doctypes_for_closing",
};
}
});
},
}
});

View File

@@ -1,6 +1,8 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Accounts Settings", {
refresh: function (frm) {},
frappe.ui.form.on('Accounts Settings', {
refresh: function(frm) {
}
});

View File

@@ -68,12 +68,7 @@
"enable_party_matching",
"enable_fuzzy_matching",
"tab_break_dpet",
"show_balance_in_coa",
"reports_tab",
"remarks_section",
"general_ledger_remarks_length",
"column_break_lvjk",
"receivable_payable_remarks_length"
"show_balance_in_coa"
],
"fields": [
{
@@ -434,34 +429,6 @@
"fieldname": "show_balance_in_coa",
"fieldtype": "Check",
"label": "Show Balances in Chart Of Accounts"
},
{
"fieldname": "reports_tab",
"fieldtype": "Tab Break",
"label": "Reports"
},
{
"default": "0",
"description": "Truncates 'Remarks' column to set character length",
"fieldname": "general_ledger_remarks_length",
"fieldtype": "Int",
"label": "General Ledger"
},
{
"default": "0",
"description": "Truncates 'Remarks' column to set character length",
"fieldname": "receivable_payable_remarks_length",
"fieldtype": "Int",
"label": "Accounts Receivable/Payable"
},
{
"fieldname": "column_break_lvjk",
"fieldtype": "Column Break"
},
{
"fieldname": "remarks_section",
"fieldtype": "Section Break",
"label": "Remarks Column Length"
}
],
"icon": "icon-cog",
@@ -469,7 +436,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2023-11-20 09:37:47.650347",
"modified": "2023-07-27 15:05:34.000264",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",

View File

@@ -1,11 +1,8 @@
frappe.ui.form.on("Accounts Settings", {
refresh: function (frm) {
frappe.ui.form.on('Accounts Settings', {
refresh: function(frm) {
frm.set_df_property("acc_frozen_upto", "label", "Books Closed Through");
frm.set_df_property(
"frozen_accounts_modifier",
"label",
"Role Allowed to Close Books & Make Changes to Closed Periods"
);
frm.set_df_property("frozen_accounts_modifier", "label", "Role Allowed to Close Books & Make Changes to Closed Periods");
frm.set_df_property("credit_controller", "label", "Credit Manager");
},
}
});

View File

@@ -11,7 +11,6 @@
{
"fieldname": "company",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"in_list_view": 1,
"label": "Company",
"options": "Company",
@@ -20,7 +19,7 @@
],
"istable": 1,
"links": [],
"modified": "2024-01-03 11:13:02.669632",
"modified": "2020-05-01 12:32:34.044911",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Allowed To Transact With",
@@ -29,6 +28,5 @@
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}

View File

@@ -1,39 +1,41 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.provide("erpnext.integrations");
frappe.provide('erpnext.integrations');
frappe.ui.form.on("Bank", {
onload: function (frm) {
frappe.ui.form.on('Bank', {
onload: function(frm) {
add_fields_to_mapping_table(frm);
},
refresh: function (frm) {
refresh: function(frm) {
add_fields_to_mapping_table(frm);
frappe.dynamic_link = { doc: frm.doc, fieldname: "name", doctype: "Bank" };
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank' };
frm.toggle_display(["address_html", "contact_html"], !frm.doc.__islocal);
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
if (frm.doc.__islocal) {
frm.set_df_property("address_and_contact", "hidden", 1);
frm.set_df_property('address_and_contact', 'hidden', 1);
frappe.contacts.clear_address_and_contact(frm);
} else {
frm.set_df_property("address_and_contact", "hidden", 0);
}
else {
frm.set_df_property('address_and_contact', 'hidden', 0);
frappe.contacts.render_address_and_contact(frm);
}
if (frm.doc.plaid_access_token) {
frm.add_custom_button(__("Refresh Plaid Link"), () => {
frm.add_custom_button(__('Refresh Plaid Link'), () => {
new erpnext.integrations.refreshPlaidLink(frm.doc.plaid_access_token);
});
}
},
}
});
let add_fields_to_mapping_table = function (frm) {
let options = [];
frappe.model.with_doctype("Bank Transaction", function () {
frappe.model.with_doctype("Bank Transaction", function() {
let meta = frappe.get_meta("Bank Transaction");
meta.fields.forEach((value) => {
meta.fields.forEach(value => {
if (!["Section Break", "Column Break"].includes(value.fieldtype)) {
options.push(value.fieldname);
}
@@ -41,32 +43,30 @@ let add_fields_to_mapping_table = function (frm) {
});
frm.fields_dict.bank_transaction_mapping.grid.update_docfield_property(
"bank_transaction_field",
"options",
options
'bank_transaction_field', 'options', options
);
};
erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
constructor(access_token) {
this.access_token = access_token;
this.plaidUrl = "https://cdn.plaid.com/link/v2/stable/link-initialize.js";
this.plaidUrl = 'https://cdn.plaid.com/link/v2/stable/link-initialize.js';
this.init_config();
}
async init_config() {
this.plaid_env = await frappe.db.get_single_value("Plaid Settings", "plaid_env");
this.plaid_env = await frappe.db.get_single_value('Plaid Settings', 'plaid_env');
this.token = await this.get_link_token_for_update();
this.init_plaid();
}
async get_link_token_for_update() {
const token = frappe.xcall(
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.get_link_token_for_update",
'erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.get_link_token_for_update',
{ access_token: this.access_token }
);
)
if (!token) {
frappe.throw(__("Cannot retrieve link token for update. Check Error Log for more information"));
frappe.throw(__('Cannot retrieve link token for update. Check Error Log for more information'));
}
return token;
}
@@ -93,13 +93,13 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
resolve();
return;
}
const el = document.createElement("script");
el.type = "text/javascript";
const el = document.createElement('script');
el.type = 'text/javascript';
el.async = true;
el.src = src;
el.addEventListener("load", resolve);
el.addEventListener("error", reject);
el.addEventListener("abort", reject);
el.addEventListener('load', resolve);
el.addEventListener('error', reject);
el.addEventListener('abort', reject);
document.head.appendChild(el);
});
}
@@ -108,29 +108,20 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
me.linkHandler = Plaid.create({
env: me.plaid_env,
token: me.token,
onSuccess: me.plaid_success,
onSuccess: me.plaid_success
});
}
onScriptError(error) {
frappe.msgprint(
__(
"There was an issue connecting to Plaid's authentication server. Check browser console for more information"
)
);
frappe.msgprint(__("There was an issue connecting to Plaid's authentication server. Check browser console for more information"));
console.log(error);
}
plaid_success(token, response) {
frappe
.xcall(
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.update_bank_account_ids",
{
response: response,
}
)
.then(() => {
frappe.show_alert({ message: __("Plaid Link Updated"), indicator: "green" });
});
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.update_bank_account_ids', {
response: response,
}).then(() => {
frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' });
});
}
};

View File

@@ -1,49 +1,45 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Bank Account", {
setup: function (frm) {
frm.set_query("account", function () {
frappe.ui.form.on('Bank Account', {
setup: function(frm) {
frm.set_query("account", function() {
return {
filters: {
account_type: "Bank",
company: frm.doc.company,
is_group: 0,
},
'account_type': 'Bank',
'company': frm.doc.company,
'is_group': 0
}
};
});
frm.set_query("party_type", function () {
frm.set_query("party_type", function() {
return {
query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
};
});
},
refresh: function (frm) {
frappe.dynamic_link = { doc: frm.doc, fieldname: "name", doctype: "Bank Account" };
refresh: function(frm) {
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank Account' }
frm.toggle_display(["address_html", "contact_html"], !frm.doc.__islocal);
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
if (frm.doc.__islocal) {
frappe.contacts.clear_address_and_contact(frm);
} else {
}
else {
frappe.contacts.render_address_and_contact(frm);
}
if (frm.doc.integration_id) {
frm.add_custom_button(__("Unlink external integrations"), function () {
frappe.confirm(
__(
"This action will unlink this account from any external service integrating ERPNext with your bank accounts. It cannot be undone. Are you certain ?"
),
function () {
frm.set_value("integration_id", "");
}
);
frm.add_custom_button(__("Unlink external integrations"), function() {
frappe.confirm(__("This action will unlink this account from any external service integrating ERPNext with your bank accounts. It cannot be undone. Are you certain ?"), function() {
frm.set_value("integration_id", "");
});
});
}
},
is_company_account: function (frm) {
frm.set_df_property("account", "reqd", frm.doc.is_company_account);
},
is_company_account: function(frm) {
frm.set_df_property('account', 'reqd', frm.doc.is_company_account);
}
});

View File

@@ -13,7 +13,6 @@
"account_type",
"account_subtype",
"column_break_7",
"disabled",
"is_default",
"is_company_account",
"company",
@@ -200,16 +199,10 @@
"fieldtype": "Data",
"in_global_search": 1,
"label": "Branch Code"
},
{
"default": "0",
"fieldname": "disabled",
"fieldtype": "Check",
"label": "Disabled"
}
],
"links": [],
"modified": "2024-02-02 17:50:09.768835",
"modified": "2022-05-04 15:49:42.620630",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account",

View File

@@ -9,7 +9,6 @@ from frappe.contacts.address_and_contact import (
load_address_and_contact,
)
from frappe.model.document import Document
from frappe.utils import comma_and, get_link_to_form
class BankAccount(Document):
@@ -26,19 +25,6 @@ class BankAccount(Document):
def validate(self):
self.validate_company()
self.validate_iban()
self.validate_account()
def validate_account(self):
if self.account:
if accounts := frappe.db.get_all(
"Bank Account", filters={"account": self.account, "name": ["!=", self.name]}, as_list=1
):
frappe.throw(
_("'{0}' account is already used by {1}. Use another account.").format(
frappe.bold(self.account),
frappe.bold(comma_and([get_link_to_form(self.doctype, x[0]) for x in accounts])),
)
)
def validate_company(self):
if self.is_company_account and not self.company:

View File

@@ -1,6 +1,8 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Bank Account Subtype", {
refresh: function () {},
frappe.ui.form.on('Bank Account Subtype', {
refresh: function() {
}
});

View File

@@ -1,7 +1,8 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Bank Account Type", {
frappe.ui.form.on('Bank Account Type', {
// refresh: function(frm) {
// }
});

View File

@@ -2,76 +2,80 @@
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on("Bank Clearance", {
setup: function (frm) {
setup: function(frm) {
frm.add_fetch("account", "account_currency", "account_currency");
frm.set_query("account", function () {
frm.set_query("account", function() {
return {
filters: {
account_type: ["in", ["Bank", "Cash"]],
is_group: 0,
},
"filters": {
"account_type": ["in",["Bank","Cash"]],
"is_group": 0,
}
};
});
frm.set_query("bank_account", function () {
return {
filters: {
is_company_account: 1,
'is_company_account': 1
},
};
});
},
onload: function (frm) {
let default_bank_account = frappe.defaults.get_user_default("Company")
? locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]
: "";
onload: function(frm) {
let default_bank_account = frappe.defaults.get_user_default("Company")?
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "";
frm.set_value("account", default_bank_account);
frm.set_value("from_date", frappe.datetime.month_start());
frm.set_value("to_date", frappe.datetime.month_end());
},
refresh: function (frm) {
refresh: function(frm) {
frm.disable_save();
frm.add_custom_button(__("Get Payment Entries"), () => frm.trigger("get_payment_entries"));
frm.add_custom_button(__('Get Payment Entries'), () =>
frm.trigger("get_payment_entries")
);
frm.change_custom_button_type("Get Payment Entries", null, "primary");
frm.change_custom_button_type('Get Payment Entries', null, 'primary');
},
update_clearance_date: function (frm) {
update_clearance_date: function(frm) {
return frappe.call({
method: "update_clearance_date",
doc: frm.doc,
callback: function (r, rt) {
callback: function(r, rt) {
frm.refresh_field("payment_entries");
frm.refresh_fields();
if (!frm.doc.payment_entries.length) {
frm.change_custom_button_type("Get Payment Entries", null, "primary");
frm.change_custom_button_type("Update Clearance Date", null, "default");
frm.change_custom_button_type('Get Payment Entries', null, 'primary');
frm.change_custom_button_type('Update Clearance Date', null, 'default');
}
},
}
});
},
get_payment_entries: function (frm) {
get_payment_entries: function(frm) {
return frappe.call({
method: "get_payment_entries",
doc: frm.doc,
callback: function (r, rt) {
callback: function(r, rt) {
frm.refresh_field("payment_entries");
if (frm.doc.payment_entries.length) {
frm.add_custom_button(__("Update Clearance Date"), () =>
frm.add_custom_button(__('Update Clearance Date'), () =>
frm.trigger("update_clearance_date")
);
frm.change_custom_button_type("Get Payment Entries", null, "default");
frm.change_custom_button_type("Update Clearance Date", null, "primary");
frm.change_custom_button_type('Get Payment Entries', null, 'default');
frm.change_custom_button_type('Update Clearance Date', null, 'primary');
}
},
}
});
},
}
});

View File

@@ -1,39 +1,39 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
cur_frm.add_fetch("bank_account", "account", "account");
cur_frm.add_fetch("bank_account", "bank_account_no", "bank_account_no");
cur_frm.add_fetch("bank_account", "iban", "iban");
cur_frm.add_fetch("bank_account", "branch_code", "branch_code");
cur_frm.add_fetch("bank", "swift_number", "swift_number");
cur_frm.add_fetch('bank_account','account','account');
cur_frm.add_fetch('bank_account','bank_account_no','bank_account_no');
cur_frm.add_fetch('bank_account','iban','iban');
cur_frm.add_fetch('bank_account','branch_code','branch_code');
cur_frm.add_fetch('bank','swift_number','swift_number');
frappe.ui.form.on("Bank Guarantee", {
setup: function (frm) {
frm.set_query("bank", function () {
frappe.ui.form.on('Bank Guarantee', {
setup: function(frm) {
frm.set_query("bank", function() {
return {
filters: {
company: frm.doc.company
}
};
});
frm.set_query("bank_account", function() {
return {
filters: {
company: frm.doc.company,
},
};
bank: frm.doc.bank
}
}
});
frm.set_query("bank_account", function () {
frm.set_query("project", function() {
return {
filters: {
company: frm.doc.company,
bank: frm.doc.bank,
},
};
});
frm.set_query("project", function () {
return {
filters: {
customer: frm.doc.customer,
},
customer: frm.doc.customer
}
};
});
},
bg_type: function (frm) {
bg_type: function(frm) {
if (frm.doc.bg_type == "Receiving") {
frm.set_value("reference_doctype", "Sales Order");
} else if (frm.doc.bg_type == "Providing") {
@@ -41,33 +41,34 @@ frappe.ui.form.on("Bank Guarantee", {
}
},
reference_docname: function (frm) {
reference_docname: function(frm) {
if (frm.doc.reference_docname && frm.doc.reference_doctype) {
let party_field = frm.doc.reference_doctype == "Sales Order" ? "customer" : "supplier";
frappe.call({
method: "erpnext.accounts.doctype.bank_guarantee.bank_guarantee.get_voucher_details",
args: {
bank_guarantee_type: frm.doc.bg_type,
reference_name: frm.doc.reference_docname,
"bank_guarantee_type": frm.doc.bg_type,
"reference_name": frm.doc.reference_docname
},
callback: function (r) {
callback: function(r) {
if (r.message) {
if (r.message[party_field]) frm.set_value(party_field, r.message[party_field]);
if (r.message.project) frm.set_value("project", r.message.project);
if (r.message.grand_total) frm.set_value("amount", r.message.grand_total);
}
},
}
});
}
},
start_date: function (frm) {
start_date: function(frm) {
var end_date = frappe.datetime.add_days(cur_frm.doc.start_date, cur_frm.doc.validity - 1);
cur_frm.set_value("end_date", end_date);
},
validity: function (frm) {
validity: function(frm) {
var end_date = frappe.datetime.add_days(cur_frm.doc.start_date, cur_frm.doc.validity - 1);
cur_frm.set_value("end_date", end_date);
},
}
});

View File

@@ -8,22 +8,21 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
return {
filters: {
company: frm.doc.company,
is_company_account: 1,
'is_company_account': 1
},
};
});
let no_bank_transactions_text = `<div class="text-muted text-center">${__(
"No Matching Bank Transactions Found"
)}</div>`;
let no_bank_transactions_text =
`<div class="text-muted text-center">${__("No Matching Bank Transactions Found")}</div>`
set_field_options("no_bank_transactions", no_bank_transactions_text);
},
onload: function (frm) {
// Set default filter dates
let today = frappe.datetime.get_today();
let today = frappe.datetime.get_today()
frm.doc.bank_statement_from_date = frappe.datetime.add_months(today, -1);
frm.doc.bank_statement_to_date = today;
frm.trigger("bank_account");
frm.trigger('bank_account');
},
filter_by_reference_date: function (frm) {
@@ -38,27 +37,34 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
refresh: function (frm) {
frm.disable_save();
frappe.require("bank-reconciliation-tool.bundle.js", () => frm.trigger("make_reconciliation_tool"));
frm.add_custom_button(__("Upload Bank Statement"), () =>
frappe.call({
method: "erpnext.accounts.doctype.bank_statement_import.bank_statement_import.upload_bank_statement",
args: {
dt: frm.doc.doctype,
dn: frm.doc.name,
company: frm.doc.company,
bank_account: frm.doc.bank_account,
},
callback: function (r) {
if (!r.exc) {
var doc = frappe.model.sync(r.message);
frappe.set_route("Form", doc[0].doctype, doc[0].name);
}
},
})
frappe.require("bank-reconciliation-tool.bundle.js", () =>
frm.trigger("make_reconciliation_tool")
);
frm.add_custom_button(__("Auto Reconcile"), function () {
frm.add_custom_button(__("Upload Bank Statement"), () =>
frappe.call({
method:
"erpnext.accounts.doctype.bank_statement_import.bank_statement_import.upload_bank_statement",
args: {
dt: frm.doc.doctype,
dn: frm.doc.name,
company: frm.doc.company,
bank_account: frm.doc.bank_account,
},
callback: function (r) {
if (!r.exc) {
var doc = frappe.model.sync(r.message);
frappe.set_route(
"Form",
doc[0].doctype,
doc[0].name
);
}
},
})
);
frm.add_custom_button(__('Auto Reconcile'), function() {
frappe.call({
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.auto_reconcile_vouchers",
args: {
@@ -69,22 +75,33 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
from_reference_date: frm.doc.from_reference_date,
to_reference_date: frm.doc.to_reference_date,
},
});
})
});
frm.add_custom_button(__("Get Unreconciled Entries"), function () {
frm.add_custom_button(__('Get Unreconciled Entries'), function() {
frm.trigger("make_reconciliation_tool");
});
frm.change_custom_button_type("Get Unreconciled Entries", null, "primary");
frm.change_custom_button_type('Get Unreconciled Entries', null, 'primary');
},
bank_account: function (frm) {
frappe.db.get_value("Bank Account", frm.doc.bank_account, "account", (r) => {
frappe.db.get_value("Account", r.account, "account_currency", (r) => {
frm.doc.account_currency = r.account_currency;
frm.trigger("render_chart");
});
});
frappe.db.get_value(
"Bank Account",
frm.doc.bank_account,
"account",
(r) => {
frappe.db.get_value(
"Account",
r.account,
"account_currency",
(r) => {
frm.doc.account_currency = r.account_currency;
frm.trigger("render_chart");
}
);
}
);
frm.trigger("get_account_opening_balance");
},
@@ -103,7 +120,11 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
) {
frm.trigger("render_chart");
frm.trigger("render");
frappe.utils.scroll_to(frm.get_field("reconciliation_tool_cards").$wrapper, true, 30);
frappe.utils.scroll_to(
frm.get_field("reconciliation_tool_cards").$wrapper,
true,
30
);
}
});
}
@@ -112,10 +133,11 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
get_account_opening_balance(frm) {
if (frm.doc.bank_account && frm.doc.bank_statement_from_date) {
frappe.call({
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
method:
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
args: {
bank_account: frm.doc.bank_account,
till_date: frappe.datetime.add_days(frm.doc.bank_statement_from_date, -1),
till_date: frm.doc.bank_statement_from_date,
},
callback: (response) => {
frm.set_value("account_opening_balance", response.message);
@@ -127,7 +149,8 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
get_cleared_balance(frm) {
if (frm.doc.bank_account && frm.doc.bank_statement_to_date) {
return frappe.call({
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
method:
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
args: {
bank_account: frm.doc.bank_account,
till_date: frm.doc.bank_statement_to_date,
@@ -140,30 +163,41 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
},
render_chart(frm) {
frm.cards_manager = new erpnext.accounts.bank_reconciliation.NumberCardManager({
$reconciliation_tool_cards: frm.get_field("reconciliation_tool_cards").$wrapper,
bank_statement_closing_balance: frm.doc.bank_statement_closing_balance,
cleared_balance: frm.cleared_balance,
currency: frm.doc.account_currency,
});
frm.cards_manager = new erpnext.accounts.bank_reconciliation.NumberCardManager(
{
$reconciliation_tool_cards: frm.get_field(
"reconciliation_tool_cards"
).$wrapper,
bank_statement_closing_balance:
frm.doc.bank_statement_closing_balance,
cleared_balance: frm.cleared_balance,
currency: frm.doc.account_currency,
}
);
},
render(frm) {
if (frm.doc.bank_account) {
frm.bank_reconciliation_data_table_manager =
new erpnext.accounts.bank_reconciliation.DataTableManager({
frm.bank_reconciliation_data_table_manager = new erpnext.accounts.bank_reconciliation.DataTableManager(
{
company: frm.doc.company,
bank_account: frm.doc.bank_account,
$reconciliation_tool_dt: frm.get_field("reconciliation_tool_dt").$wrapper,
$no_bank_transactions: frm.get_field("no_bank_transactions").$wrapper,
$reconciliation_tool_dt: frm.get_field(
"reconciliation_tool_dt"
).$wrapper,
$no_bank_transactions: frm.get_field(
"no_bank_transactions"
).$wrapper,
bank_statement_from_date: frm.doc.bank_statement_from_date,
bank_statement_to_date: frm.doc.bank_statement_to_date,
filter_by_reference_date: frm.doc.filter_by_reference_date,
from_reference_date: frm.doc.from_reference_date,
to_reference_date: frm.doc.to_reference_date,
bank_statement_closing_balance: frm.doc.bank_statement_closing_balance,
bank_statement_closing_balance:
frm.doc.bank_statement_closing_balance,
cards_manager: frm.cards_manager,
});
}
);
}
},
});

View File

@@ -17,7 +17,6 @@ from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_s
get_entries,
)
from erpnext.accounts.utils import get_balance_on
from erpnext.setup.utils import get_exchange_rate
class BankReconciliationTool(Document):
@@ -130,7 +129,7 @@ def create_journal_entry_bts(
bank_transaction = frappe.db.get_values(
"Bank Transaction",
bank_transaction_name,
fieldname=["name", "deposit", "withdrawal", "bank_account", "currency"],
fieldname=["name", "deposit", "withdrawal", "bank_account"],
as_dict=True,
)[0]
company_account = frappe.get_value("Bank Account", bank_transaction.bank_account, "account")
@@ -144,94 +143,29 @@ def create_journal_entry_bts(
)
company = frappe.get_value("Account", company_account, "company")
company_default_currency = frappe.get_cached_value("Company", company, "default_currency")
company_account_currency = frappe.get_cached_value("Account", company_account, "account_currency")
second_account_currency = frappe.get_cached_value("Account", second_account, "account_currency")
# determine if multi-currency Journal or not
is_multi_currency = (
True
if company_default_currency != company_account_currency
or company_default_currency != second_account_currency
or company_default_currency != bank_transaction.currency
else False
)
accounts = []
second_account_dict = {
"account": second_account,
"account_currency": second_account_currency,
"credit_in_account_currency": bank_transaction.deposit,
"debit_in_account_currency": bank_transaction.withdrawal,
"party_type": party_type,
"party": party,
"cost_center": get_default_cost_center(company),
}
# Multi Currency?
accounts.append(
{
"account": second_account,
"credit_in_account_currency": bank_transaction.deposit,
"debit_in_account_currency": bank_transaction.withdrawal,
"party_type": party_type,
"party": party,
"cost_center": get_default_cost_center(company),
}
)
company_account_dict = {
"account": company_account,
"account_currency": company_account_currency,
"bank_account": bank_transaction.bank_account,
"credit_in_account_currency": bank_transaction.withdrawal,
"debit_in_account_currency": bank_transaction.deposit,
"cost_center": get_default_cost_center(company),
}
# convert transaction amount to company currency
if is_multi_currency:
exc_rate = get_exchange_rate(bank_transaction.currency, company_default_currency, posting_date)
withdrawal_in_company_currency = flt(exc_rate * abs(bank_transaction.withdrawal))
deposit_in_company_currency = flt(exc_rate * abs(bank_transaction.deposit))
else:
withdrawal_in_company_currency = bank_transaction.withdrawal
deposit_in_company_currency = bank_transaction.deposit
# if second account is of foreign currency, convert and set debit and credit fields.
if second_account_currency != company_default_currency:
exc_rate = get_exchange_rate(second_account_currency, company_default_currency, posting_date)
second_account_dict.update(
{
"exchange_rate": exc_rate,
"credit": deposit_in_company_currency,
"debit": withdrawal_in_company_currency,
"credit_in_account_currency": flt(deposit_in_company_currency / exc_rate) or 0,
"debit_in_account_currency": flt(withdrawal_in_company_currency / exc_rate) or 0,
}
)
else:
second_account_dict.update(
{
"exchange_rate": 1,
"credit": deposit_in_company_currency,
"debit": withdrawal_in_company_currency,
"credit_in_account_currency": deposit_in_company_currency,
"debit_in_account_currency": withdrawal_in_company_currency,
}
)
# if company account is of foreign currency, convert and set debit and credit fields.
if company_account_currency != company_default_currency:
exc_rate = get_exchange_rate(company_account_currency, company_default_currency, posting_date)
company_account_dict.update(
{
"exchange_rate": exc_rate,
"credit": withdrawal_in_company_currency,
"debit": deposit_in_company_currency,
}
)
else:
company_account_dict.update(
{
"exchange_rate": 1,
"credit": withdrawal_in_company_currency,
"debit": deposit_in_company_currency,
"credit_in_account_currency": withdrawal_in_company_currency,
"debit_in_account_currency": deposit_in_company_currency,
}
)
accounts.append(second_account_dict)
accounts.append(company_account_dict)
accounts.append(
{
"account": company_account,
"bank_account": bank_transaction.bank_account,
"credit_in_account_currency": bank_transaction.withdrawal,
"debit_in_account_currency": bank_transaction.deposit,
"cost_center": get_default_cost_center(company),
}
)
journal_entry_dict = {
"voucher_type": entry_type,
@@ -241,9 +175,6 @@ def create_journal_entry_bts(
"cheque_no": reference_number,
"mode_of_payment": mode_of_payment,
}
if is_multi_currency:
journal_entry_dict.update({"multi_currency": True})
journal_entry = frappe.new_doc("Journal Entry")
journal_entry.update(journal_entry_dict)
journal_entry.set("accounts", accounts)

View File

@@ -2,24 +2,16 @@
// For license information, please see license.txt
frappe.ui.form.on("Bank Statement Import", {
onload(frm) {
frm.set_query("bank_account", function (doc) {
return {
filters: {
company: doc.company,
},
};
});
},
setup(frm) {
frappe.realtime.on("data_import_refresh", ({ data_import }) => {
frm.import_in_progress = false;
if (data_import !== frm.doc.name) return;
frappe.model.clear_doc("Bank Statement Import", frm.doc.name);
frappe.model.with_doc("Bank Statement Import", frm.doc.name).then(() => {
frm.refresh();
});
frappe.model
.with_doc("Bank Statement Import", frm.doc.name)
.then(() => {
frm.refresh();
});
});
frappe.realtime.on("data_import_progress", (data) => {
frm.import_in_progress = true;
@@ -46,9 +38,20 @@ frappe.ui.form.on("Bank Statement Import", {
: __("Updating {0} of {1}, {2}", message_args);
}
if (data.skipping) {
message = __("Skipping {0} of {1}, {2}", [data.current, data.total, eta_message]);
message = __(
"Skipping {0} of {1}, {2}",
[
data.current,
data.total,
eta_message,
]
);
}
frm.dashboard.show_progress(__("Import Progress"), percent, message);
frm.dashboard.show_progress(
__("Import Progress"),
percent,
message
);
frm.page.set_indicator(__("In Progress"), "orange");
// hide progress when complete
@@ -90,12 +93,15 @@ frappe.ui.form.on("Bank Statement Import", {
frm.trigger("show_report_error_button");
if (frm.doc.status === "Partial Success") {
frm.add_custom_button(__("Export Errored Rows"), () => frm.trigger("export_errored_rows"));
frm.add_custom_button(__("Export Errored Rows"), () =>
frm.trigger("export_errored_rows")
);
}
if (frm.doc.status.includes("Success")) {
frm.add_custom_button(__("Go to {0} List", [__(frm.doc.reference_doctype)]), () =>
frappe.set_route("List", frm.doc.reference_doctype)
frm.add_custom_button(
__("Go to {0} List", [__(frm.doc.reference_doctype)]),
() => frappe.set_route("List", frm.doc.reference_doctype)
);
}
},
@@ -112,8 +118,13 @@ frappe.ui.form.on("Bank Statement Import", {
frm.disable_save();
if (frm.doc.status !== "Success") {
if (!frm.is_new() && frm.has_import_file()) {
let label = frm.doc.status === "Pending" ? __("Start Import") : __("Retry");
frm.page.set_primary_action(label, () => frm.events.start_import(frm));
let label =
frm.doc.status === "Pending"
? __("Start Import")
: __("Retry");
frm.page.set_primary_action(label, () =>
frm.events.start_import(frm)
);
} else {
frm.page.set_primary_action(__("Save"), () => frm.save());
}
@@ -155,24 +166,24 @@ frappe.ui.form.on("Bank Statement Import", {
message =
successful_records.length > 1
? __(
"Successfully imported {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
"Successfully imported {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
: __(
"Successfully imported {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
"Successfully imported {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
} else {
message =
successful_records.length > 1
? __(
"Successfully updated {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
"Successfully updated {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
: __(
"Successfully updated {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
"Successfully updated {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
}
}
frm.dashboard.set_headline(message);
@@ -215,7 +226,8 @@ frappe.ui.form.on("Bank Statement Import", {
},
download_template() {
let method = "/api/method/frappe.core.doctype.data_import.data_import.download_template";
let method =
"/api/method/frappe.core.doctype.data_import.data_import.download_template";
open_url_post(method, {
doctype: "Bank Transaction",
@@ -228,7 +240,7 @@ frappe.ui.form.on("Bank Statement Import", {
"description",
"reference_number",
"bank_account",
"currency",
"currency"
],
},
});
@@ -299,7 +311,10 @@ frappe.ui.form.on("Bank Statement Import", {
show_import_preview(frm, preview_data) {
let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
if (frm.import_preview && frm.import_preview.doctype === frm.doc.reference_doctype) {
if (
frm.import_preview &&
frm.import_preview.doctype === frm.doc.reference_doctype
) {
frm.import_preview.preview_data = preview_data;
frm.import_preview.import_log = import_log;
frm.import_preview.refresh();
@@ -315,10 +330,19 @@ frappe.ui.form.on("Bank Statement Import", {
frm,
events: {
remap_column(changed_map) {
let template_options = JSON.parse(frm.doc.template_options || "{}");
template_options.column_to_field_map = template_options.column_to_field_map || {};
Object.assign(template_options.column_to_field_map, changed_map);
frm.set_value("template_options", JSON.stringify(template_options));
let template_options = JSON.parse(
frm.doc.template_options || "{}"
);
template_options.column_to_field_map =
template_options.column_to_field_map || {};
Object.assign(
template_options.column_to_field_map,
changed_map
);
frm.set_value(
"template_options",
JSON.stringify(template_options)
);
frm.save().then(() => frm.trigger("import_file"));
},
},
@@ -328,11 +352,10 @@ frappe.ui.form.on("Bank Statement Import", {
export_errored_rows(frm) {
open_url_post(
"/api/method/erpnext.accounts.doctype.bank_statement_import.bank_statement_import.download_errored_template",
"/api/method/frappe.core.doctype.data_import.data_import.download_errored_template",
{
data_import_name: frm.doc.name,
},
true
}
);
},
@@ -352,7 +375,8 @@ frappe.ui.form.on("Bank Statement Import", {
let other_warnings = [];
for (let warning of warnings) {
if (warning.row) {
warnings_by_row[warning.row] = warnings_by_row[warning.row] || [];
warnings_by_row[warning.row] =
warnings_by_row[warning.row] || [];
warnings_by_row[warning.row].push(warning);
} else {
other_warnings.push(warning);
@@ -367,7 +391,9 @@ frappe.ui.form.on("Bank Statement Import", {
if (w.field) {
let label =
w.field.label +
(w.field.parent !== frm.doc.reference_doctype ? ` (${w.field.parent})` : "");
(w.field.parent !== frm.doc.reference_doctype
? ` (${w.field.parent})`
: "");
return `<li>${label}: ${w.message}</li>`;
}
return `<li>${w.message}</li>`;
@@ -386,9 +412,10 @@ frappe.ui.form.on("Bank Statement Import", {
.map((warning) => {
let header = "";
if (warning.col) {
let column_number = `<span class="text-uppercase">${__("Column {0}", [
warning.col,
])}</span>`;
let column_number = `<span class="text-uppercase">${__(
"Column {0}",
[warning.col]
)}</span>`;
let column_header = columns[warning.col].header_title;
header = `${column_number} (${column_header})`;
}
@@ -427,28 +454,36 @@ frappe.ui.form.on("Bank Statement Import", {
let html = "";
if (log.success) {
if (frm.doc.import_type === "Insert New Records") {
html = __("Successfully imported {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]);
html = __(
"Successfully imported {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]
);
} else {
html = __("Successfully updated {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]);
html = __(
"Successfully updated {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]
);
}
} else {
let messages = log.messages
.map(JSON.parse)
.map((m) => {
let title = m.title ? `<strong>${m.title}</strong>` : "";
let message = m.message ? `<div>${m.message}</div>` : "";
let title = m.title
? `<strong>${m.title}</strong>`
: "";
let message = m.message
? `<div>${m.message}</div>`
: "";
return title + message;
})
.join("");

View File

@@ -1,34 +1,36 @@
let imports_in_progress = [];
frappe.listview_settings["Bank Statement Import"] = {
frappe.listview_settings['Bank Statement Import'] = {
onload(listview) {
frappe.realtime.on("data_import_progress", (data) => {
frappe.realtime.on('data_import_progress', data => {
if (!imports_in_progress.includes(data.data_import)) {
imports_in_progress.push(data.data_import);
}
});
frappe.realtime.on("data_import_refresh", (data) => {
imports_in_progress = imports_in_progress.filter((d) => d !== data.data_import);
frappe.realtime.on('data_import_refresh', data => {
imports_in_progress = imports_in_progress.filter(
d => d !== data.data_import
);
listview.refresh();
});
},
get_indicator: function (doc) {
get_indicator: function(doc) {
var colors = {
Pending: "orange",
"Not Started": "orange",
"Partial Success": "orange",
Success: "green",
"In Progress": "orange",
Error: "red",
'Pending': 'orange',
'Not Started': 'orange',
'Partial Success': 'orange',
'Success': 'green',
'In Progress': 'orange',
'Error': 'red'
};
let status = doc.status;
if (imports_in_progress.includes(doc.name)) {
status = "In Progress";
status = 'In Progress';
}
if (status == "Pending") {
status = "Not Started";
if (status == 'Pending') {
status = 'Not Started';
}
return [__(status), colors[status], "status,=," + doc.status];
return [__(status), colors[status], 'status,=,' + doc.status];
},
hide_name_column: true,
hide_name_column: true
};

View File

@@ -112,8 +112,7 @@ class AutoMatchbyPartyNameDescription:
for party in parties:
filters = {"status": "Active"} if party == "Employee" else {"disabled": 0}
field = party.lower() + "_name"
names = frappe.get_all(party, filters=filters, fields=[f"{field} as party_name", "name"])
names = frappe.get_all(party, filters=filters, pluck=party.lower() + "_name")
for field in ["bank_party_name", "description"]:
if not self.get(field):
@@ -132,11 +131,7 @@ class AutoMatchbyPartyNameDescription:
def fuzzy_search_and_return_result(self, party, names, field) -> Union[Tuple, None]:
skip = False
result = process.extract(
query=self.get(field),
choices={row.get("name"): row.get("party_name") for row in names},
scorer=fuzz.token_set_ratio,
)
result = process.extract(query=self.get(field), choices=names, scorer=fuzz.token_set_ratio)
party_name, skip = self.process_fuzzy_result(result)
if not party_name:
@@ -154,14 +149,14 @@ class AutoMatchbyPartyNameDescription:
Returns: Result, Skip (whether or not to discontinue matching)
"""
SCORE, PARTY_ID, CUTOFF = 1, 2, 80
PARTY, SCORE, CUTOFF = 0, 1, 80
if not result or not len(result):
return None, False
first_result = result[0]
if len(result) == 1:
return (first_result[PARTY_ID] if first_result[SCORE] > CUTOFF else None), True
return (first_result[PARTY] if first_result[SCORE] > CUTOFF else None), True
second_result = result[1]
if first_result[SCORE] > CUTOFF:
@@ -170,7 +165,7 @@ class AutoMatchbyPartyNameDescription:
if first_result[SCORE] == second_result[SCORE]:
return None, True
return first_result[PARTY_ID], True
return first_result[PARTY], True
else:
return None, False

View File

@@ -3,7 +3,7 @@
frappe.ui.form.on("Bank Transaction", {
onload(frm) {
frm.set_query("payment_document", "payment_entries", function () {
frm.set_query("payment_document", "payment_entries", function() {
const payment_doctypes = frm.events.get_payment_doctypes(frm);
return {
filters: {
@@ -23,7 +23,7 @@ frappe.ui.form.on("Bank Transaction", {
set_bank_statement_filter(frm);
},
setup: function (frm) {
setup: function(frm) {
frm.set_query("party_type", function () {
return {
filters: {
@@ -33,10 +33,16 @@ frappe.ui.form.on("Bank Transaction", {
});
},
get_payment_doctypes: function () {
get_payment_doctypes: function() {
// get payment doctypes from all the apps
return ["Payment Entry", "Journal Entry", "Sales Invoice", "Purchase Invoice", "Bank Transaction"];
},
return [
"Payment Entry",
"Journal Entry",
"Sales Invoice",
"Purchase Invoice",
"Bank Transaction",
];
}
});
frappe.ui.form.on("Bank Transaction Payments", {
@@ -48,11 +54,10 @@ frappe.ui.form.on("Bank Transaction Payments", {
const update_clearance_date = (frm, cdt, cdn) => {
if (frm.doc.docstatus === 1) {
frappe
.xcall("erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment", {
doctype: cdt,
docname: cdn,
bt_name: frm.doc.name,
})
.xcall(
"erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment",
{ doctype: cdt, docname: cdn, bt_name: frm.doc.name }
)
.then((e) => {
if (e == "success") {
frappe.show_alert({

View File

@@ -2,7 +2,6 @@
# For license information, please see license.txt
import frappe
from frappe.model.docstatus import DocStatus
from frappe.utils import flt
from erpnext.controllers.status_updater import StatusUpdater
@@ -41,10 +40,9 @@ class BankTransaction(StatusUpdater):
else:
allocated_amount = 0.0
unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) - allocated_amount
self.db_set("allocated_amount", flt(allocated_amount, self.precision("allocated_amount")))
self.db_set("unallocated_amount", flt(unallocated_amount, self.precision("unallocated_amount")))
amount = abs(flt(self.withdrawal) - flt(self.deposit))
self.db_set("allocated_amount", flt(allocated_amount))
self.db_set("unallocated_amount", amount - flt(allocated_amount))
self.reload()
self.set_status(update=True)
@@ -70,7 +68,7 @@ class BankTransaction(StatusUpdater):
"payment_entry": voucher["payment_name"],
"allocated_amount": 0.0, # Temporary
}
self.append("payment_entries", pe)
child = self.append("payment_entries", pe)
added = True
# runs on_update_after_submit
@@ -91,6 +89,7 @@ class BankTransaction(StatusUpdater):
- 0 > a: Error: already over-allocated
- clear means: set the latest transaction date as clearance date
"""
gl_bank_account = frappe.db.get_value("Bank Account", self.bank_account, "account")
remaining_amount = self.unallocated_amount
for payment_entry in self.payment_entries:
if payment_entry.allocated_amount == 0.0:
@@ -395,21 +394,3 @@ def unclear_reference_payment(doctype, docname, bt_name):
bt = frappe.get_doc("Bank Transaction", bt_name)
set_voucher_clearance(doctype, docname, None, bt)
return docname
def remove_from_bank_transaction(doctype, docname):
"""Remove a (cancelled) voucher from all Bank Transactions."""
for bt_name in get_reconciled_bank_transactions(doctype, docname):
bt = frappe.get_doc("Bank Transaction", bt_name)
if bt.docstatus == DocStatus.cancelled():
continue
modified = False
for pe in bt.payment_entries:
if pe.payment_document == doctype and pe.payment_entry == docname:
bt.remove(pe)
modified = True
if modified:
bt.save()

View File

@@ -1,15 +1,15 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.listview_settings["Bank Transaction"] = {
frappe.listview_settings['Bank Transaction'] = {
add_fields: ["unallocated_amount"],
get_indicator: function (doc) {
if (doc.docstatus == 2) {
get_indicator: function(doc) {
if(doc.docstatus == 2) {
return [__("Cancelled"), "red", "docstatus,=,2"];
} else if (flt(doc.unallocated_amount) <= 0) {
} else if(flt(doc.unallocated_amount)<=0) {
return [__("Reconciled"), "green", "unallocated_amount,=,0"];
} else if (flt(doc.unallocated_amount) > 0) {
} else if(flt(doc.unallocated_amount)>0) {
return [__("Unreconciled"), "orange", "unallocated_amount,>,0"];
}
},
}
};

View File

@@ -2,10 +2,10 @@
# See license.txt
import json
import unittest
import frappe
from frappe import utils
from frappe.model.docstatus import DocStatus
from frappe.tests.utils import FrappeTestCase
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
@@ -32,16 +32,8 @@ class TestBankTransaction(FrappeTestCase):
frappe.db.delete(dt)
make_pos_profile()
# generate and use a uniq hash identifier for 'Bank Account' and it's linked GL 'Account' to avoid validation error
uniq_identifier = frappe.generate_hash(length=10)
gl_account = create_gl_account("_Test Bank " + uniq_identifier)
bank_account = create_bank_account(
gl_account=gl_account, bank_account_name="Checking Account " + uniq_identifier
)
add_transactions(bank_account=bank_account)
add_vouchers(gl_account=gl_account)
add_transactions()
add_vouchers()
# This test checks if ERPNext is able to provide a linked payment for a bank transaction based on the amount of the bank transaction.
def test_linked_payments(self):
@@ -89,29 +81,6 @@ class TestBankTransaction(FrappeTestCase):
clearance_date = frappe.db.get_value("Payment Entry", payment.name, "clearance_date")
self.assertFalse(clearance_date)
def test_cancel_voucher(self):
bank_transaction = frappe.get_doc(
"Bank Transaction",
dict(description="1512567 BG/000003025 OPSKATTUZWXXX AT776000000098709849 Herr G"),
)
payment = frappe.get_doc("Payment Entry", dict(party="Mr G", paid_amount=1700))
vouchers = json.dumps(
[
{
"payment_doctype": "Payment Entry",
"payment_name": payment.name,
"amount": bank_transaction.unallocated_amount,
}
]
)
reconcile_vouchers(bank_transaction.name, vouchers)
payment.reload()
payment.cancel()
bank_transaction.reload()
self.assertEqual(bank_transaction.docstatus, DocStatus.submitted())
self.assertEqual(bank_transaction.unallocated_amount, 1700)
self.assertEqual(bank_transaction.payment_entries, [])
# Check if ERPNext can correctly filter a linked payments based on the debit/credit amount
def test_debit_credit_output(self):
bank_transaction = frappe.get_doc(
@@ -221,9 +190,7 @@ class TestBankTransaction(FrappeTestCase):
self.assertEqual(linked_payments[0][2], repayment_entry.name)
def create_bank_account(
bank_name="Citi Bank", gl_account="_Test Bank - _TC", bank_account_name="Checking Account"
):
def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
try:
frappe.get_doc(
{
@@ -235,35 +202,21 @@ def create_bank_account(
pass
try:
bank_account = frappe.get_doc(
frappe.get_doc(
{
"doctype": "Bank Account",
"account_name": bank_account_name,
"account_name": "Checking Account",
"bank": bank_name,
"account": gl_account,
"account": account_name,
}
).insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
return bank_account.name
def add_transactions():
create_bank_account()
def create_gl_account(gl_account_name="_Test Bank - _TC"):
gl_account = frappe.get_doc(
{
"doctype": "Account",
"company": "_Test Company",
"parent_account": "Current Assets - _TC",
"account_type": "Bank",
"is_group": 0,
"account_name": gl_account_name,
}
).insert()
return gl_account.name
def add_transactions(bank_account="_Test Bank - _TC"):
doc = frappe.get_doc(
{
"doctype": "Bank Transaction",
@@ -271,7 +224,7 @@ def add_transactions(bank_account="_Test Bank - _TC"):
"date": "2018-10-23",
"deposit": 1200,
"currency": "INR",
"bank_account": bank_account,
"bank_account": "Checking Account - Citi Bank",
}
).insert()
doc.submit()
@@ -283,7 +236,7 @@ def add_transactions(bank_account="_Test Bank - _TC"):
"date": "2018-10-23",
"deposit": 1700,
"currency": "INR",
"bank_account": bank_account,
"bank_account": "Checking Account - Citi Bank",
}
).insert()
doc.submit()
@@ -295,7 +248,7 @@ def add_transactions(bank_account="_Test Bank - _TC"):
"date": "2018-10-26",
"withdrawal": 690,
"currency": "INR",
"bank_account": bank_account,
"bank_account": "Checking Account - Citi Bank",
}
).insert()
doc.submit()
@@ -307,7 +260,7 @@ def add_transactions(bank_account="_Test Bank - _TC"):
"date": "2018-10-27",
"deposit": 3900,
"currency": "INR",
"bank_account": bank_account,
"bank_account": "Checking Account - Citi Bank",
}
).insert()
doc.submit()
@@ -319,13 +272,13 @@ def add_transactions(bank_account="_Test Bank - _TC"):
"date": "2018-10-27",
"withdrawal": 109080,
"currency": "INR",
"bank_account": bank_account,
"bank_account": "Checking Account - Citi Bank",
}
).insert()
doc.submit()
def add_vouchers(gl_account="_Test Bank - _TC"):
def add_vouchers():
try:
frappe.get_doc(
{
@@ -341,7 +294,7 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
pi = make_purchase_invoice(supplier="Conrad Electronic", qty=1, rate=690)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
pe.reference_no = "Conrad Oct 18"
pe.reference_date = "2018-10-24"
pe.insert()
@@ -360,14 +313,14 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
pass
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1200)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
pe.reference_no = "Herr G Oct 18"
pe.reference_date = "2018-10-24"
pe.insert()
pe.submit()
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1700)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
pe.reference_no = "Herr G Nov 18"
pe.reference_date = "2018-11-01"
pe.insert()
@@ -398,10 +351,10 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
pass
pi = make_purchase_invoice(supplier="Poore Simon's", qty=1, rate=3900, is_paid=1, do_not_save=1)
pi.cash_bank_account = gl_account
pi.cash_bank_account = "_Test Bank - _TC"
pi.insert()
pi.submit()
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
pe.reference_no = "Poore Simon's Oct 18"
pe.reference_date = "2018-10-28"
pe.paid_amount = 690
@@ -410,7 +363,7 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
pe.submit()
si = create_sales_invoice(customer="Poore Simon's", qty=1, rate=3900)
pe = get_payment_entry("Sales Invoice", si.name, bank_account=gl_account)
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
pe.reference_no = "Poore Simon's Oct 18"
pe.reference_date = "2018-10-28"
pe.insert()
@@ -433,12 +386,16 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
if not frappe.db.get_value(
"Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}
):
mode_of_payment.append("accounts", {"company": "_Test Company", "default_account": gl_account})
mode_of_payment.append(
"accounts", {"company": "_Test Company", "default_account": "_Test Bank - _TC"}
)
mode_of_payment.save()
si = create_sales_invoice(customer="Fayva", qty=1, rate=109080, do_not_save=1)
si.is_pos = 1
si.append("payments", {"mode_of_payment": "Cash", "account": gl_account, "amount": 109080})
si.append(
"payments", {"mode_of_payment": "Cash", "account": "_Test Bank - _TC", "amount": 109080}
)
si.insert()
si.submit()

View File

@@ -1,100 +0,0 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Bisect Accounting Statements", {
onload(frm) {
frm.trigger("render_heatmap");
},
refresh(frm) {
frm.add_custom_button(__("Bisect Left"), () => {
frm.trigger("bisect_left");
});
frm.add_custom_button(__("Bisect Right"), () => {
frm.trigger("bisect_right");
});
frm.add_custom_button(__("Up"), () => {
frm.trigger("move_up");
});
frm.add_custom_button(__("Build Tree"), () => {
frm.trigger("build_tree");
});
},
render_heatmap(frm) {
let bisect_heatmap = frm.get_field("bisect_heatmap").$wrapper;
bisect_heatmap.addClass("bisect_heatmap_location");
// milliseconds in a day
let msiad = 24 * 60 * 60 * 1000;
let datapoints = {};
let fr_dt = new Date(frm.doc.from_date).getTime();
let to_dt = new Date(frm.doc.to_date).getTime();
let bisect_start = new Date(frm.doc.current_from_date).getTime();
let bisect_end = new Date(frm.doc.current_to_date).getTime();
for (let x = fr_dt; x <= to_dt; x += msiad) {
let epoch_in_seconds = x / 1000;
if (bisect_start <= x && x <= bisect_end) {
datapoints[epoch_in_seconds] = 1.0;
} else {
datapoints[epoch_in_seconds] = 0.0;
}
}
new frappe.Chart(".bisect_heatmap_location", {
type: "heatmap",
data: {
dataPoints: datapoints,
start: new Date(frm.doc.from_date),
end: new Date(frm.doc.to_date),
},
countLabel: "Bisecting",
discreteDomains: 1,
});
},
bisect_left(frm) {
frm.call({
doc: frm.doc,
method: "bisect_left",
freeze: true,
freeze_message: __("Bisecting Left ..."),
callback: (r) => {
frm.trigger("render_heatmap");
},
});
},
bisect_right(frm) {
frm.call({
doc: frm.doc,
freeze: true,
freeze_message: __("Bisecting Right ..."),
method: "bisect_right",
callback: (r) => {
frm.trigger("render_heatmap");
},
});
},
move_up(frm) {
frm.call({
doc: frm.doc,
freeze: true,
freeze_message: __("Moving up in tree ..."),
method: "move_up",
callback: (r) => {
frm.trigger("render_heatmap");
},
});
},
build_tree(frm) {
frm.call({
doc: frm.doc,
freeze: true,
freeze_message: __("Rebuilding BTree for period ..."),
method: "build_tree",
callback: (r) => {
frm.trigger("render_heatmap");
},
});
},
});

View File

@@ -1,194 +0,0 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2023-09-15 21:28:28.054773",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"section_break_cvfg",
"company",
"column_break_hcam",
"from_date",
"column_break_qxbi",
"to_date",
"column_break_iwny",
"algorithm",
"section_break_8ph9",
"current_node",
"section_break_ngid",
"bisect_heatmap",
"section_break_hmsy",
"bisecting_from",
"current_from_date",
"column_break_uqyd",
"bisecting_to",
"current_to_date",
"section_break_hbyo",
"heading_cppb",
"p_l_summary",
"column_break_aivo",
"balance_sheet_summary",
"b_s_summary",
"column_break_gvwx",
"difference_heading",
"difference"
],
"fields": [
{
"fieldname": "column_break_qxbi",
"fieldtype": "Column Break"
},
{
"fieldname": "from_date",
"fieldtype": "Datetime",
"label": "From Date"
},
{
"fieldname": "to_date",
"fieldtype": "Datetime",
"label": "To Date"
},
{
"default": "BFS",
"fieldname": "algorithm",
"fieldtype": "Select",
"label": "Algorithm",
"options": "BFS\nDFS"
},
{
"fieldname": "column_break_iwny",
"fieldtype": "Column Break"
},
{
"fieldname": "current_node",
"fieldtype": "Link",
"label": "Current Node",
"options": "Bisect Nodes"
},
{
"fieldname": "section_break_hmsy",
"fieldtype": "Section Break"
},
{
"fieldname": "current_from_date",
"fieldtype": "Datetime",
"read_only": 1
},
{
"fieldname": "current_to_date",
"fieldtype": "Datetime",
"read_only": 1
},
{
"fieldname": "column_break_uqyd",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_hbyo",
"fieldtype": "Section Break"
},
{
"fieldname": "p_l_summary",
"fieldtype": "Float",
"read_only": 1
},
{
"fieldname": "b_s_summary",
"fieldtype": "Float",
"read_only": 1
},
{
"fieldname": "difference",
"fieldtype": "Float",
"read_only": 1
},
{
"fieldname": "column_break_aivo",
"fieldtype": "Column Break"
},
{
"fieldname": "column_break_gvwx",
"fieldtype": "Column Break"
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company"
},
{
"fieldname": "column_break_hcam",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_ngid",
"fieldtype": "Section Break"
},
{
"fieldname": "section_break_8ph9",
"fieldtype": "Section Break",
"hidden": 1
},
{
"fieldname": "bisect_heatmap",
"fieldtype": "HTML",
"label": "Heatmap"
},
{
"fieldname": "heading_cppb",
"fieldtype": "Heading",
"label": "Profit and Loss Summary"
},
{
"fieldname": "balance_sheet_summary",
"fieldtype": "Heading",
"label": "Balance Sheet Summary"
},
{
"fieldname": "difference_heading",
"fieldtype": "Heading",
"label": "Difference"
},
{
"fieldname": "bisecting_from",
"fieldtype": "Heading",
"label": "Bisecting From"
},
{
"fieldname": "bisecting_to",
"fieldtype": "Heading",
"label": "Bisecting To"
},
{
"fieldname": "section_break_cvfg",
"fieldtype": "Section Break"
}
],
"hide_toolbar": 1,
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2023-12-01 16:49:54.073890",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bisect Accounting Statements",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "Administrator",
"share": 1,
"write": 1
}
],
"read_only": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@@ -1,226 +0,0 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
import datetime
from collections import deque
from math import floor
import frappe
from dateutil.relativedelta import relativedelta
from frappe import _
from frappe.model.document import Document
from frappe.utils import getdate
from frappe.utils.data import guess_date_format
class BisectAccountingStatements(Document):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from frappe.types import DF
algorithm: DF.Literal["BFS", "DFS"]
b_s_summary: DF.Float
company: DF.Link | None
current_from_date: DF.Datetime | None
current_node: DF.Link | None
current_to_date: DF.Datetime | None
difference: DF.Float
from_date: DF.Datetime | None
p_l_summary: DF.Float
to_date: DF.Datetime | None
# end: auto-generated types
def validate(self):
self.validate_dates()
def validate_dates(self):
if getdate(self.from_date) > getdate(self.to_date):
frappe.throw(
_("From Date: {0} cannot be greater than To date: {1}").format(
frappe.bold(self.from_date), frappe.bold(self.to_date)
)
)
def bfs(self, from_date: datetime, to_date: datetime):
# Make Root node
node = frappe.new_doc("Bisect Nodes")
node.root = None
node.period_from_date = from_date
node.period_to_date = to_date
node.insert()
period_queue = deque([node])
while period_queue:
cur_node = period_queue.popleft()
delta = cur_node.period_to_date - cur_node.period_from_date
if delta.days == 0:
continue
else:
cur_floor = floor(delta.days / 2)
next_to_date = cur_node.period_from_date + relativedelta(days=+cur_floor)
left_node = frappe.new_doc("Bisect Nodes")
left_node.period_from_date = cur_node.period_from_date
left_node.period_to_date = next_to_date
left_node.root = cur_node.name
left_node.generated = False
left_node.insert()
cur_node.left_child = left_node.name
period_queue.append(left_node)
next_from_date = cur_node.period_from_date + relativedelta(days=+(cur_floor + 1))
right_node = frappe.new_doc("Bisect Nodes")
right_node.period_from_date = next_from_date
right_node.period_to_date = cur_node.period_to_date
right_node.root = cur_node.name
right_node.generated = False
right_node.insert()
cur_node.right_child = right_node.name
period_queue.append(right_node)
cur_node.save()
def dfs(self, from_date: datetime, to_date: datetime):
# Make Root node
node = frappe.new_doc("Bisect Nodes")
node.root = None
node.period_from_date = from_date
node.period_to_date = to_date
node.insert()
period_stack = [node]
while period_stack:
cur_node = period_stack.pop()
delta = cur_node.period_to_date - cur_node.period_from_date
if delta.days == 0:
continue
else:
cur_floor = floor(delta.days / 2)
next_to_date = cur_node.period_from_date + relativedelta(days=+cur_floor)
left_node = frappe.new_doc("Bisect Nodes")
left_node.period_from_date = cur_node.period_from_date
left_node.period_to_date = next_to_date
left_node.root = cur_node.name
left_node.generated = False
left_node.insert()
cur_node.left_child = left_node.name
period_stack.append(left_node)
next_from_date = cur_node.period_from_date + relativedelta(days=+(cur_floor + 1))
right_node = frappe.new_doc("Bisect Nodes")
right_node.period_from_date = next_from_date
right_node.period_to_date = cur_node.period_to_date
right_node.root = cur_node.name
right_node.generated = False
right_node.insert()
cur_node.right_child = right_node.name
period_stack.append(right_node)
cur_node.save()
@frappe.whitelist()
def build_tree(self):
frappe.db.delete("Bisect Nodes")
# Convert str to datetime format
dt_format = guess_date_format(self.from_date)
from_date = datetime.datetime.strptime(self.from_date, dt_format)
to_date = datetime.datetime.strptime(self.to_date, dt_format)
if self.algorithm == "BFS":
self.bfs(from_date, to_date)
if self.algorithm == "DFS":
self.dfs(from_date, to_date)
# set root as current node
root = frappe.db.get_all("Bisect Nodes", filters={"root": ["is", "not set"]})[0]
self.get_report_summary()
self.current_node = root.name
self.current_from_date = self.from_date
self.current_to_date = self.to_date
self.save()
def get_report_summary(self):
filters = {
"company": self.company,
"filter_based_on": "Date Range",
"period_start_date": self.current_from_date,
"period_end_date": self.current_to_date,
"periodicity": "Yearly",
}
pl_summary = frappe.get_doc("Report", "Profit and Loss Statement")
self.p_l_summary = pl_summary.execute_script_report(filters=filters)[5]
bs_summary = frappe.get_doc("Report", "Balance Sheet")
self.b_s_summary = bs_summary.execute_script_report(filters=filters)[5]
self.difference = abs(self.p_l_summary - self.b_s_summary)
def update_node(self):
current_node = frappe.get_doc("Bisect Nodes", self.current_node)
current_node.balance_sheet_summary = self.b_s_summary
current_node.profit_loss_summary = self.p_l_summary
current_node.difference = self.difference
current_node.generated = True
current_node.save()
def current_node_has_summary_info(self):
"Assertion method"
return frappe.db.get_value("Bisect Nodes", self.current_node, "generated")
def fetch_summary_info_from_current_node(self):
current_node = frappe.get_doc("Bisect Nodes", self.current_node)
self.p_l_summary = current_node.balance_sheet_summary
self.b_s_summary = current_node.profit_loss_summary
self.difference = abs(self.p_l_summary - self.b_s_summary)
def fetch_or_calculate(self):
if self.current_node_has_summary_info():
self.fetch_summary_info_from_current_node()
else:
self.get_report_summary()
self.update_node()
@frappe.whitelist()
def bisect_left(self):
if self.current_node is not None:
cur_node = frappe.get_doc("Bisect Nodes", self.current_node)
if cur_node.left_child is not None:
lft_node = frappe.get_doc("Bisect Nodes", cur_node.left_child)
self.current_node = cur_node.left_child
self.current_from_date = lft_node.period_from_date
self.current_to_date = lft_node.period_to_date
self.fetch_or_calculate()
self.save()
else:
frappe.msgprint(_("No more children on Left"))
@frappe.whitelist()
def bisect_right(self):
if self.current_node is not None:
cur_node = frappe.get_doc("Bisect Nodes", self.current_node)
if cur_node.right_child is not None:
rgt_node = frappe.get_doc("Bisect Nodes", cur_node.right_child)
self.current_node = cur_node.right_child
self.current_from_date = rgt_node.period_from_date
self.current_to_date = rgt_node.period_to_date
self.fetch_or_calculate()
self.save()
else:
frappe.msgprint(_("No more children on Right"))
@frappe.whitelist()
def move_up(self):
if self.current_node is not None:
cur_node = frappe.get_doc("Bisect Nodes", self.current_node)
if cur_node.root is not None:
root = frappe.get_doc("Bisect Nodes", cur_node.root)
self.current_node = cur_node.root
self.current_from_date = root.period_from_date
self.current_to_date = root.period_to_date
self.fetch_or_calculate()
self.save()
else:
frappe.msgprint(_("Reached Root"))

View File

@@ -1,9 +0,0 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestBisectAccountingStatements(FrappeTestCase):
pass

View File

@@ -1,8 +0,0 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Bisect Nodes", {
// refresh(frm) {
// },
// });

View File

@@ -1,97 +0,0 @@
{
"actions": [],
"autoname": "autoincrement",
"creation": "2023-09-27 14:56:38.112462",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"root",
"left_child",
"right_child",
"period_from_date",
"period_to_date",
"difference",
"balance_sheet_summary",
"profit_loss_summary",
"generated"
],
"fields": [
{
"fieldname": "root",
"fieldtype": "Link",
"label": "Root",
"options": "Bisect Nodes"
},
{
"fieldname": "left_child",
"fieldtype": "Link",
"label": "Left Child",
"options": "Bisect Nodes"
},
{
"fieldname": "right_child",
"fieldtype": "Link",
"label": "Right Child",
"options": "Bisect Nodes"
},
{
"fieldname": "period_from_date",
"fieldtype": "Datetime",
"label": "Period_from_date"
},
{
"fieldname": "period_to_date",
"fieldtype": "Datetime",
"label": "Period To Date"
},
{
"fieldname": "difference",
"fieldtype": "Float",
"label": "Difference"
},
{
"fieldname": "balance_sheet_summary",
"fieldtype": "Float",
"label": "Balance Sheet Summary"
},
{
"fieldname": "profit_loss_summary",
"fieldtype": "Float",
"label": "Profit and Loss Summary"
},
{
"default": "0",
"fieldname": "generated",
"fieldtype": "Check",
"label": "Generated"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-12-01 17:46:12.437996",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bisect Nodes",
"naming_rule": "Autoincrement",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Administrator",
"share": 1,
"write": 1
}
],
"read_only": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@@ -1,29 +0,0 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class BisectNodes(Document):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from frappe.types import DF
balance_sheet_summary: DF.Float
difference: DF.Float
generated: DF.Check
left_child: DF.Link | None
name: DF.Int | None
period_from_date: DF.Datetime | None
period_to_date: DF.Datetime | None
profit_loss_summary: DF.Float
right_child: DF.Link | None
root: DF.Link | None
# end: auto-generated types
pass

View File

@@ -1,9 +0,0 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestBisectNodes(FrappeTestCase):
pass

View File

@@ -2,48 +2,48 @@
// For license information, please see license.txt
frappe.provide("erpnext.accounts.dimensions");
frappe.ui.form.on("Budget", {
onload: function (frm) {
frm.set_query("account", "accounts", function () {
frappe.ui.form.on('Budget', {
onload: function(frm) {
frm.set_query("account", "accounts", function() {
return {
filters: {
company: frm.doc.company,
report_type: "Profit and Loss",
is_group: 0,
},
is_group: 0
}
};
});
frm.set_query("monthly_distribution", function () {
frm.set_query("monthly_distribution", function() {
return {
filters: {
fiscal_year: frm.doc.fiscal_year,
},
fiscal_year: frm.doc.fiscal_year
}
};
});
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
},
refresh: function (frm) {
frm.trigger("toggle_reqd_fields");
refresh: function(frm) {
frm.trigger("toggle_reqd_fields")
},
budget_against: function (frm) {
frm.trigger("set_null_value");
frm.trigger("toggle_reqd_fields");
budget_against: function(frm) {
frm.trigger("set_null_value")
frm.trigger("toggle_reqd_fields")
},
set_null_value: function (frm) {
if (frm.doc.budget_against == "Cost Center") {
frm.set_value("project", null);
set_null_value: function(frm) {
if(frm.doc.budget_against == 'Cost Center') {
frm.set_value('project', null)
} else {
frm.set_value("cost_center", null);
frm.set_value('cost_center', null)
}
},
toggle_reqd_fields: function (frm) {
frm.toggle_reqd("cost_center", frm.doc.budget_against == "Cost Center");
frm.toggle_reqd("project", frm.doc.budget_against == "Project");
},
toggle_reqd_fields: function(frm) {
frm.toggle_reqd("cost_center", frm.doc.budget_against=="Cost Center");
frm.toggle_reqd("project", frm.doc.budget_against=="Project");
}
});

View File

@@ -109,8 +109,6 @@ class Budget(Document):
def validate_expense_against_budget(args, expense_amount=0):
args = frappe._dict(args)
if not frappe.get_all("Budget", limit=1):
return
if args.get("company") and not args.fiscal_year:
args.fiscal_year = get_fiscal_year(args.get("posting_date"), company=args.get("company"))[0]
@@ -118,11 +116,6 @@ def validate_expense_against_budget(args, expense_amount=0):
"Company", args.get("company"), "exception_budget_approver_role"
)
if not frappe.get_cached_value(
"Budget", {"fiscal_year": args.fiscal_year, "company": args.company}
): # nosec
return
if not args.account:
args.account = args.get("expense_account")
@@ -149,13 +142,13 @@ def validate_expense_against_budget(args, expense_amount=0):
if (
args.get(budget_against)
and args.account
and (frappe.get_cached_value("Account", args.account, "root_type") == "Expense")
and frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"})
):
doctype = dimension.get("document_type")
if frappe.get_cached_value("DocType", doctype, "is_tree"):
lft, rgt = frappe.get_cached_value(doctype, args.get(budget_against), ["lft", "rgt"])
lft, rgt = frappe.db.get_value(doctype, args.get(budget_against), ["lft", "rgt"])
condition = """and exists(select name from `tab%s`
where lft<=%s and rgt>=%s and name=b.%s)""" % (
doctype,

View File

@@ -1,42 +1,94 @@
{
"actions": [],
"creation": "2016-05-16 11:54:09.286135",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"account",
"budget_amount"
],
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2016-05-16 11:54:09.286135",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"fieldname": "account",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Account",
"options": "Account",
"reqd": 1,
"search_index": 1
},
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "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,
"unique": 0
},
{
"fieldname": "budget_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Budget Amount",
"options": "Company:company:default_currency",
"reqd": 1
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "budget_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Budget 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": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"istable": 1,
"links": [],
"modified": "2024-03-04 15:43:27.016947",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Budget Account",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": []
],
"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": "2017-01-02 17:02:53.339420",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Budget Account",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_seen": 0
}

View File

@@ -1,4 +1,6 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Cash Flow Mapper", {});
frappe.ui.form.on('Cash Flow Mapper', {
});

View File

@@ -1,45 +1,43 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Cash Flow Mapping", {
refresh: function (frm) {
frappe.ui.form.on('Cash Flow Mapping', {
refresh: function(frm) {
frm.events.disable_unchecked_fields(frm);
},
reset_check_fields: function (frm) {
frm.fields
.filter((field) => field.df.fieldtype === "Check")
.map((field) => frm.set_df_property(field.df.fieldname, "read_only", 0));
reset_check_fields: function(frm) {
frm.fields.filter(field => field.df.fieldtype === 'Check')
.map(field => frm.set_df_property(field.df.fieldname, 'read_only', 0));
},
has_checked_field(frm) {
const val = frm.fields.filter((field) => field.value === 1);
const val = frm.fields.filter(field => field.value === 1);
return val.length ? 1 : 0;
},
_disable_unchecked_fields: function (frm) {
_disable_unchecked_fields: function(frm) {
// get value of clicked field
frm.fields
.filter((field) => field.value === 0)
.map((field) => frm.set_df_property(field.df.fieldname, "read_only", 1));
frm.fields.filter(field => field.value === 0)
.map(field => frm.set_df_property(field.df.fieldname, 'read_only', 1));
},
disable_unchecked_fields: function (frm) {
disable_unchecked_fields: function(frm) {
frm.events.reset_check_fields(frm);
const checked = frm.events.has_checked_field(frm);
if (checked) {
frm.events._disable_unchecked_fields(frm);
}
},
is_working_capital: function (frm) {
is_working_capital: function(frm) {
frm.events.disable_unchecked_fields(frm);
},
is_finance_cost: function (frm) {
is_finance_cost: function(frm) {
frm.events.disable_unchecked_fields(frm);
},
is_income_tax_liability: function (frm) {
is_income_tax_liability: function(frm) {
frm.events.disable_unchecked_fields(frm);
},
is_income_tax_expense: function (frm) {
is_income_tax_expense: function(frm) {
frm.events.disable_unchecked_fields(frm);
},
is_finance_cost_adjustment: function (frm) {
is_finance_cost_adjustment: function(frm) {
frm.events.disable_unchecked_fields(frm);
},
}
});

View File

@@ -1,4 +1,6 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Cash Flow Mapping Template", {});
frappe.ui.form.on('Cash Flow Mapping Template', {
});

View File

@@ -1,4 +1,6 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Cash Flow Mapping Template Details", {});
frappe.ui.form.on('Cash Flow Mapping Template Details', {
});

View File

@@ -1,10 +1,11 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on("Cashier Closing", {
setup: function (frm) {
frappe.ui.form.on('Cashier Closing', {
setup: function(frm){
if (frm.doc.user == "" || frm.doc.user == null) {
frm.doc.user = frappe.session.user;
}
},
}
});

View File

@@ -1,152 +1,457 @@
{
"actions": [],
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "naming_series:",
"beta": 0,
"creation": "2018-06-18 16:51:49.994750",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"naming_series",
"user",
"date",
"from_time",
"time",
"expense",
"custody",
"returns",
"outstanding_amount",
"payments",
"net_amount",
"amended_from"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "POS-CLO-",
"fieldname": "naming_series",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Series",
"length": 0,
"no_copy": 0,
"options": "POS-CLO-",
"read_only": 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
},
{
"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": 1,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "User",
"length": 0,
"no_copy": 0,
"options": "User",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"reqd": 1
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Today",
"fieldname": "date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Date",
"read_only": 1
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "from_time",
"fieldtype": "Time",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "From Time",
"reqd": 1
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "",
"fieldname": "time",
"fieldtype": "Time",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "To Time",
"reqd": 1
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.00",
"fieldname": "expense",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"label": "Expense"
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Expense",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.00",
"fieldname": "custody",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"label": "Custody"
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Custody",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.00",
"fieldname": "returns",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Returns",
"precision": "2"
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "2",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.00",
"fieldname": "outstanding_amount",
"fieldtype": "Float",
"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": "Outstanding Amount",
"read_only": 1
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.0",
"fieldname": "payments",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Payments",
"options": "Cashier Closing Payments"
"length": 0,
"no_copy": 0,
"options": "Cashier Closing Payments",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "net_amount",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Net Amount",
"read_only": 1
"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
},
{
"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": "Cashier Closing",
"permlevel": 0,
"print_hide": 1,
"read_only": 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
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 1,
"links": [],
"modified": "2023-12-28 13:15:46.858427",
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-02-19 08:35:24.157327",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cashier Closing",
"naming_rule": "By \"Naming Series\" field",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"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": "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",
"states": [],
"track_changes": 1
}
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@@ -1,4 +1,4 @@
frappe.ui.form.on("Chart of Accounts Importer", {
frappe.ui.form.on('Chart of Accounts Importer', {
onload: function (frm) {
frm.set_value("company", "");
frm.set_value("import_file", "");
@@ -8,34 +8,31 @@ frappe.ui.form.on("Chart of Accounts Importer", {
frm.disable_save();
// make company mandatory
frm.set_df_property("company", "reqd", frm.doc.company ? 0 : 1);
frm.set_df_property("import_file_section", "hidden", frm.doc.company ? 0 : 1);
frm.set_df_property('company', 'reqd', frm.doc.company ? 0 : 1);
frm.set_df_property('import_file_section', 'hidden', frm.doc.company ? 0 : 1);
if (frm.doc.import_file) {
frappe.run_serially([
() => generate_tree_preview(frm),
() => create_import_button(frm),
() => frm.set_df_property("chart_preview", "hidden", 0),
() => frm.set_df_property('chart_preview', 'hidden', 0)
]);
}
frm.set_df_property(
"chart_preview",
"hidden",
$(frm.fields_dict["chart_tree"].wrapper).html() != "" ? 0 : 1
);
frm.set_df_property('chart_preview', 'hidden',
$(frm.fields_dict['chart_tree'].wrapper).html()!="" ? 0 : 1);
},
download_template: function (frm) {
download_template: function(frm) {
var d = new frappe.ui.Dialog({
title: __("Download Template"),
fields: [
{
label: "File Type",
label : "File Type",
fieldname: "file_type",
fieldtype: "Select",
reqd: 1,
options: ["Excel", "CSV"],
options: ["Excel", "CSV"]
},
{
label: "Template Type",
@@ -44,53 +41,38 @@ frappe.ui.form.on("Chart of Accounts Importer", {
reqd: 1,
options: ["Sample Template", "Blank Template"],
change: () => {
let template_type = d.get_value("template_type");
let template_type = d.get_value('template_type');
if (template_type === "Sample Template") {
d.set_df_property(
"template_type",
"description",
d.set_df_property('template_type', 'description',
`The Sample Template contains all the required accounts pre filled in the template.
You can add more accounts or change existing accounts in the template as per your choice.`
);
You can add more accounts or change existing accounts in the template as per your choice.`);
} else {
d.set_df_property(
"template_type",
"description",
d.set_df_property('template_type', 'description',
`The Blank Template contains just the account type and root type required to build the Chart
of Accounts. Please enter the account names and add more rows as per your requirement.`
);
of Accounts. Please enter the account names and add more rows as per your requirement.`);
}
},
},
{
label: "Company",
fieldname: "company",
fieldtype: "Link",
reqd: 1,
hidden: 1,
default: frm.doc.company,
},
}
}
],
primary_action: function () {
let data = d.get_values();
primary_action: function() {
var data = d.get_values();
if (!data.template_type) {
frappe.throw(__("Please select <b>Template Type</b> to download template"));
frappe.throw(__('Please select <b>Template Type</b> to download template'));
}
open_url_post(
"/api/method/erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template",
'/api/method/erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template',
{
file_type: data.file_type,
template_type: data.template_type,
company: data.company,
template_type: data.template_type
}
);
d.hide();
},
primary_action_label: __("Download"),
primary_action_label: __('Download')
});
d.show();
},
@@ -98,7 +80,7 @@ frappe.ui.form.on("Chart of Accounts Importer", {
import_file: function (frm) {
if (!frm.doc.import_file) {
frm.page.set_indicator("");
$(frm.fields_dict["chart_tree"].wrapper).empty(); // empty wrapper on removing file
$(frm.fields_dict['chart_tree'].wrapper).empty(); // empty wrapper on removing file
}
},
@@ -108,97 +90,89 @@ frappe.ui.form.on("Chart of Accounts Importer", {
frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.validate_company",
args: {
company: frm.doc.company,
company: frm.doc.company
},
callback: function (r) {
if (r.message === false) {
callback: function(r) {
if(r.message===false) {
frm.set_value("company", "");
frappe.throw(
__(
"Transactions against the Company already exist! Chart of Accounts can only be imported for a Company with no transactions."
)
);
frappe.throw(__("Transactions against the Company already exist! Chart of Accounts can only be imported for a Company with no transactions."));
} else {
frm.trigger("refresh");
}
},
}
});
}
},
}
});
var create_import_button = function (frm) {
frm.page
.set_primary_action(__("Import"), function () {
return frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
args: {
file_name: frm.doc.import_file,
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 Successful"), "blue");
create_reset_button(frm);
}
},
});
})
.addClass("btn btn-primary");
};
var create_reset_button = function (frm) {
frm.page
.set_primary_action(__("Reset"), function () {
frm.page.clear_primary_action();
delete frm.page["show_import_button"];
frm.reload_doc();
})
.addClass("btn btn-primary");
};
var validate_coa = function (frm) {
if (frm.doc.import_file) {
let parent = __("All Accounts");
var create_import_button = function(frm) {
frm.page.set_primary_action(__("Import"), function () {
return frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa",
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
args: {
file_name: frm.doc.import_file,
parent: parent,
doctype: "Chart of Accounts Importer",
file_type: frm.doc.file_type,
for_validate: 1,
company: frm.doc.company
},
callback: function (r) {
if (r.message["show_import_button"]) {
frm.page["show_import_button"] = Boolean(r.message["show_import_button"]);
freeze: true,
freeze_message: __("Creating Accounts..."),
callback: function(r) {
if (!r.exc) {
clearInterval(frm.page["interval"]);
frm.page.set_indicator(__('Import Successful'), 'blue');
create_reset_button(frm);
}
}
});
}).addClass('btn btn-primary');
};
var create_reset_button = function(frm) {
frm.page.set_primary_action(__("Reset"), function () {
frm.page.clear_primary_action();
delete frm.page["show_import_button"];
frm.reload_doc();
}).addClass('btn btn-primary');
};
var validate_coa = function(frm) {
if (frm.doc.import_file) {
let parent = __('All Accounts');
return frappe.call({
'method': 'erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa',
'args': {
file_name: frm.doc.import_file,
parent: parent,
doctype: 'Chart of Accounts Importer',
file_type: frm.doc.file_type,
for_validate: 1
},
callback: function(r) {
if (r.message['show_import_button']) {
frm.page['show_import_button'] = Boolean(r.message['show_import_button']);
}
}
});
}
};
var generate_tree_preview = function (frm) {
let parent = __("All Accounts");
$(frm.fields_dict["chart_tree"].wrapper).empty(); // empty wrapper to load new data
var generate_tree_preview = function(frm) {
let parent = __('All Accounts');
$(frm.fields_dict['chart_tree'].wrapper).empty(); // empty wrapper to load new data
// generate tree structure based on the csv data
return new frappe.ui.Tree({
parent: $(frm.fields_dict["chart_tree"].wrapper),
parent: $(frm.fields_dict['chart_tree'].wrapper),
label: parent,
expandable: true,
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa",
method: 'erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa',
args: {
file_name: frm.doc.import_file,
parent: parent,
doctype: "Chart of Accounts Importer",
file_type: frm.doc.file_type,
doctype: 'Chart of Accounts Importer',
file_type: frm.doc.file_type
},
onclick: function (node) {
onclick: function(node) {
parent = node.value;
},
}
});
};

View File

@@ -8,7 +8,6 @@ from functools import reduce
import frappe
from frappe import _
from frappe.desk.form.linked_with import get_linked_fields
from frappe.model.document import Document
from frappe.utils import cint, cstr
from frappe.utils.csvutils import UnicodeWriter
@@ -113,7 +112,7 @@ def generate_data_from_csv(file_doc, as_dict=False):
if as_dict:
data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)})
else:
if not row[1] and len(row) > 1:
if not row[1]:
row[1] = row[0]
row[3] = row[2]
data.append(row)
@@ -295,8 +294,10 @@ def build_response_as_excel(writer):
@frappe.whitelist()
def download_template(file_type, template_type, company):
writer = get_template(template_type, company)
def download_template(file_type, template_type):
data = frappe._dict(frappe.local.form_dict)
writer = get_template(template_type)
if file_type == "CSV":
# download csv file
@@ -307,7 +308,8 @@ def download_template(file_type, template_type, company):
build_response_as_excel(writer)
def get_template(template_type, company):
def get_template(template_type):
fields = [
"Account Name",
"Parent Account",
@@ -333,17 +335,34 @@ def get_template(template_type, company):
["", "", "", "", 0, account_type.get("account_type"), account_type.get("root_type")]
)
else:
writer = get_sample_template(writer, company)
writer = get_sample_template(writer)
return writer
def get_sample_template(writer, company):
currency = frappe.db.get_value("Company", company, "default_currency")
with open(os.path.join(os.path.dirname(__file__), "coa_sample_template.csv"), "r") as f:
for row in f:
row = row.strip().split(",") + [currency]
writer.writerow(row)
def get_sample_template(writer):
template = [
["Application Of Funds(Assets)", "", "", "", 1, "", "Asset"],
["Sources Of Funds(Liabilities)", "", "", "", 1, "", "Liability"],
["Equity", "", "", "", 1, "", "Equity"],
["Expenses", "", "", "", 1, "", "Expense"],
["Income", "", "", "", 1, "", "Income"],
["Bank Accounts", "Application Of Funds(Assets)", "", "", 1, "Bank", "Asset"],
["Cash In Hand", "Application Of Funds(Assets)", "", "", 1, "Cash", "Asset"],
["Stock Assets", "Application Of Funds(Assets)", "", "", 1, "Stock", "Asset"],
["Cost Of Goods Sold", "Expenses", "", "", 0, "Cost of Goods Sold", "Expense"],
["Asset Depreciation", "Expenses", "", "", 0, "Depreciation", "Expense"],
["Fixed Assets", "Application Of Funds(Assets)", "", "", 0, "Fixed Asset", "Asset"],
["Accounts Payable", "Sources Of Funds(Liabilities)", "", "", 0, "Payable", "Liability"],
["Accounts Receivable", "Application Of Funds(Assets)", "", "", 1, "Receivable", "Asset"],
["Stock Expenses", "Expenses", "", "", 0, "Stock Adjustment", "Expense"],
["Sample Bank", "Bank Accounts", "", "", 0, "Bank", "Asset"],
["Cash", "Cash In Hand", "", "", 0, "Cash", "Asset"],
["Stores", "Stock Assets", "", "", 0, "Stock", "Asset"],
]
for row in template:
writer.writerow(row)
return writer
@@ -434,11 +453,14 @@ def get_mandatory_account_types():
def unset_existing_data(company):
# remove accounts data from company
linked = frappe.db.sql(
'''select fieldname from tabDocField
where fieldtype="Link" and options="Account" and parent="Company"''',
as_dict=True,
)
fieldnames = get_linked_fields("Account").get("Company", {}).get("fieldname", [])
linked = [{"fieldname": name} for name in fieldnames]
update_values = {d.get("fieldname"): "" for d in linked}
# remove accounts data from company
update_values = {d.fieldname: "" for d in linked}
frappe.db.set_value("Company", company, update_values, update_values)
# remove accounts data from various doctypes

View File

@@ -1,17 +0,0 @@
Application Of Funds(Assets),,,,1,,Asset
Sources Of Funds(Liabilities),,,,1,,Liability
Equity,,,,1,,Equity
Expenses,,,,1,Expense Account,Expense
Income,,,,1,Income Account,Income
Bank Accounts,Application Of Funds(Assets),,,1,Bank,Asset
Cash In Hand,Application Of Funds(Assets),,,1,Cash,Asset
Stock Assets,Application Of Funds(Assets),,,1,Stock,Asset
Cost Of Goods Sold,Expenses,,,0,Cost of Goods Sold,Expense
Asset Depreciation,Expenses,,,0,Depreciation,Expense
Fixed Assets,Application Of Funds(Assets),,,0,Fixed Asset,Asset
Accounts Payable,Sources Of Funds(Liabilities),,,0,Payable,Liability
Accounts Receivable,Application Of Funds(Assets),,,1,Receivable,Asset
Stock Expenses,Expenses,,,0,Stock Adjustment,Expense
Sample Bank,Bank Accounts,,,0,Bank,Asset
Cash,Cash In Hand,,,0,Cash,Asset
Stores,Stock Assets,,,0,Stock,Asset
1 Application Of Funds(Assets) 1 Asset
2 Sources Of Funds(Liabilities) 1 Liability
3 Equity 1 Equity
4 Expenses 1 Expense Account Expense
5 Income 1 Income Account Income
6 Bank Accounts Application Of Funds(Assets) 1 Bank Asset
7 Cash In Hand Application Of Funds(Assets) 1 Cash Asset
8 Stock Assets Application Of Funds(Assets) 1 Stock Asset
9 Cost Of Goods Sold Expenses 0 Cost of Goods Sold Expense
10 Asset Depreciation Expenses 0 Depreciation Expense
11 Fixed Assets Application Of Funds(Assets) 0 Fixed Asset Asset
12 Accounts Payable Sources Of Funds(Liabilities) 0 Payable Liability
13 Accounts Receivable Application Of Funds(Assets) 1 Receivable Asset
14 Stock Expenses Expenses 0 Stock Adjustment Expense
15 Sample Bank Bank Accounts 0 Bank Asset
16 Cash Cash In Hand 0 Cash Asset
17 Stores Stock Assets 0 Stock Asset

View File

@@ -3,20 +3,18 @@
frappe.provide("erpnext.cheque_print");
frappe.ui.form.on("Cheque Print Template", {
refresh: function (frm) {
if (!frm.doc.__islocal) {
frm.add_custom_button(
frm.doc.has_print_format ? __("Update Print Format") : __("Create Print Format"),
function () {
frappe.ui.form.on('Cheque Print Template', {
refresh: function(frm) {
if(!frm.doc.__islocal) {
frm.add_custom_button(frm.doc.has_print_format?__("Update Print Format"):__("Create Print Format"),
function() {
erpnext.cheque_print.view_cheque_print(frm);
}
).addClass("btn-primary");
}).addClass("btn-primary");
$(frm.fields_dict.cheque_print_preview.wrapper).empty();
$(frm.fields_dict.cheque_print_preview.wrapper).empty()
var template =
'<div style="position: relative; overflow-x: scroll;">\
var template = '<div style="position: relative; overflow-x: scroll;">\
<div id="cheque_preview" style="width: {{ cheque_width }}cm; \
height: {{ cheque_height }}cm;\
background-repeat: no-repeat;\
@@ -50,30 +48,30 @@ frappe.ui.form.on("Cheque Print Template", {
</div>\
</div>';
$(frappe.render(template, frm.doc)).appendTo(frm.fields_dict.cheque_print_preview.wrapper);
$(frappe.render(template, frm.doc)).appendTo(frm.fields_dict.cheque_print_preview.wrapper)
if (frm.doc.scanned_cheque) {
$(frm.fields_dict.cheque_print_preview.wrapper)
.find("#cheque_preview")
.css("background-image", "url(" + frm.doc.scanned_cheque + ")");
$(frm.fields_dict.cheque_print_preview.wrapper).find("#cheque_preview").css('background-image', 'url(' + frm.doc.scanned_cheque + ')');
}
}
},
}
});
erpnext.cheque_print.view_cheque_print = function (frm) {
erpnext.cheque_print.view_cheque_print = function(frm) {
frappe.call({
method: "erpnext.accounts.doctype.cheque_print_template.cheque_print_template.create_or_update_cheque_print_format",
args: {
template_name: frm.doc.name,
args:{
"template_name": frm.doc.name
},
callback: function (r) {
callback: function(r) {
if (!r.exe && !frm.doc.has_print_format) {
var doc = frappe.model.sync(r.message);
frappe.set_route("Form", r.message.doctype, r.message.name);
} else {
frappe.msgprint(__("Print settings updated in respective print format"));
}
},
});
};
else {
frappe.msgprint(__("Print settings updated in respective print format"))
}
}
})
}

View File

@@ -3,80 +3,75 @@
frappe.provide("erpnext.accounts");
frappe.ui.form.on("Cost Center", {
onload: function (frm) {
frm.set_query("parent_cost_center", function () {
frappe.ui.form.on('Cost Center', {
onload: function(frm) {
frm.set_query("parent_cost_center", function() {
return {
filters: {
company: frm.doc.company,
is_group: 1,
},
};
is_group: 1
}
}
});
},
refresh: function (frm) {
refresh: function(frm) {
if (!frm.is_new()) {
frm.add_custom_button(__("Update Cost Center Name / Number"), function () {
frm.add_custom_button(__('Update Cost Center Name / Number'), function () {
frm.trigger("update_cost_center_number");
});
}
let intro_txt = "";
let intro_txt = '';
let doc = frm.doc;
frm.toggle_display("cost_center_name", doc.__islocal);
frm.toggle_enable(["is_group", "company"], doc.__islocal);
frm.toggle_display('cost_center_name', doc.__islocal);
frm.toggle_enable(['is_group', 'company'], doc.__islocal);
if (!doc.__islocal && doc.is_group == 1) {
intro_txt += __(
"Note: This Cost Center is a Group. Cannot make accounting entries against groups."
);
if(!doc.__islocal && doc.is_group==1) {
intro_txt += __('Note: This Cost Center is a Group. Cannot make accounting entries against groups.');
}
frm.events.hide_unhide_group_ledger(frm);
frm.toggle_display("sb1", doc.is_group == 0);
frm.toggle_display('sb1', doc.is_group==0);
frm.set_intro(intro_txt);
if (!frm.doc.__islocal) {
frm.add_custom_button(__("Chart of Cost Centers"), function () {
frappe.set_route("Tree", "Cost Center");
});
if(!frm.doc.__islocal) {
frm.add_custom_button(__('Chart of Cost Centers'),
function() { frappe.set_route("Tree", "Cost Center"); });
frm.add_custom_button(__("Budget"), function () {
frappe.set_route("List", "Budget", { cost_center: frm.doc.name });
});
frm.add_custom_button(__('Budget'),
function() { frappe.set_route("List", "Budget", {'cost_center': frm.doc.name}); });
}
},
update_cost_center_number: function (frm) {
update_cost_center_number: function(frm) {
var d = new frappe.ui.Dialog({
title: __("Update Cost Center Name / Number"),
title: __('Update Cost Center Name / Number'),
fields: [
{
label: "Cost Center Name",
fieldname: "cost_center_name",
fieldtype: "Data",
reqd: 1,
default: frm.doc.cost_center_name,
"label": "Cost Center Name",
"fieldname": "cost_center_name",
"fieldtype": "Data",
"reqd": 1,
"default": frm.doc.cost_center_name
},
{
label: "Cost Center Number",
fieldname: "cost_center_number",
fieldtype: "Data",
default: frm.doc.cost_center_number,
"label": "Cost Center Number",
"fieldname": "cost_center_number",
"fieldtype": "Data",
"default": frm.doc.cost_center_number
},
{
label: __("Merge with existing"),
fieldname: "merge",
fieldtype: "Check",
default: 0,
},
"label": __("Merge with existing"),
"fieldname": "merge",
"fieldtype": "Check",
"default": 0
}
],
primary_action: function () {
primary_action: function() {
var data = d.get_values();
if (
data.cost_center_name === frm.doc.cost_center_name &&
data.cost_center_number === frm.doc.cost_center_number
) {
if(data.cost_center_name === frm.doc.cost_center_name && data.cost_center_number === frm.doc.cost_center_number) {
d.hide();
return;
}
@@ -88,12 +83,12 @@ frappe.ui.form.on("Cost Center", {
cost_center_name: data.cost_center_name,
cost_center_number: cstr(data.cost_center_number),
company: frm.doc.company,
merge: data.merge,
merge: data.merge
},
callback: function (r) {
callback: function(r) {
frappe.dom.unfreeze();
if (!r.exc) {
if (r.message) {
if(!r.exc) {
if(r.message) {
frappe.set_route("Form", "Cost Center", r.message);
} else {
me.frm.set_value("cost_center_name", data.cost_center_name);
@@ -101,42 +96,44 @@ frappe.ui.form.on("Cost Center", {
}
d.hide();
}
},
}
});
},
primary_action_label: __("Update"),
primary_action_label: __('Update')
});
d.show();
},
parent_cost_center(frm) {
if (!frm.doc.company) {
frappe.msgprint(__("Please enter company name first"));
if(!frm.doc.company) {
frappe.msgprint(__('Please enter company name first'));
}
},
hide_unhide_group_ledger(frm) {
let doc = frm.doc;
if (doc.is_group == 1) {
frm.add_custom_button(__("Convert to Non-Group"), () => frm.events.convert_to_ledger(frm));
frm.add_custom_button(__('Convert to Non-Group'),
() => frm.events.convert_to_ledger(frm));
} else if (doc.is_group == 0) {
frm.add_custom_button(__("Convert to Group"), () => frm.events.convert_to_group(frm));
frm.add_custom_button(__('Convert to Group'),
() => frm.events.convert_to_group(frm));
}
},
convert_to_group(frm) {
frm.call("convert_ledger_to_group").then((r) => {
if (r.message === 1) {
frm.call('convert_ledger_to_group').then(r => {
if(r.message === 1) {
frm.refresh();
}
});
},
convert_to_ledger(frm) {
frm.call("convert_group_to_ledger").then((r) => {
if (r.message === 1) {
frm.call('convert_group_to_ledger').then(r => {
if(r.message === 1) {
frm.refresh();
}
});
},
}
});

View File

@@ -1,84 +1,54 @@
frappe.treeview_settings["Cost Center"] = {
breadcrumb: "Accounts",
get_tree_root: false,
filters: [
{
fieldname: "company",
fieldtype: "Select",
options: erpnext.utils.get_tree_options("company"),
label: __("Company"),
default: erpnext.utils.get_tree_default("company"),
},
],
filters: [{
fieldname: "company",
fieldtype:"Select",
options: erpnext.utils.get_tree_options("company"),
label: __("Company"),
default: erpnext.utils.get_tree_default("company")
}],
root_label: "Cost Centers",
get_tree_nodes: "erpnext.accounts.utils.get_children",
add_tree_node: "erpnext.accounts.utils.add_cc",
menu_items: [
get_tree_nodes: 'erpnext.accounts.utils.get_children',
add_tree_node: 'erpnext.accounts.utils.add_cc',
menu_items:[
{
label: __("New Company"),
action: function () {
frappe.new_doc("Company", true);
},
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1',
},
label: __('New Company'),
action: function() { frappe.new_doc("Company", true) },
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1'
}
],
fields: [
{ fieldtype: "Data", fieldname: "cost_center_name", label: __("New Cost Center Name"), reqd: true },
{
fieldtype: "Check",
fieldname: "is_group",
label: __("Is Group"),
description: __(
"Further cost centers can be made under Groups but entries can be made against non-Groups"
),
},
{
fieldtype: "Data",
fieldname: "cost_center_number",
label: __("Cost Center Number"),
description: __(
"Number of new Cost Center, it will be included in the cost center name as a prefix"
),
},
fields:[
{fieldtype:'Data', fieldname:'cost_center_name', label:__('New Cost Center Name'), reqd:true},
{fieldtype:'Check', fieldname:'is_group', label:__('Is Group'),
description:__('Further cost centers can be made under Groups but entries can be made against non-Groups')},
{fieldtype:'Data', fieldname:'cost_center_number', label:__('Cost Center Number'),
description: __("Number of new Cost Center, it will be included in the cost center name as a prefix")}
],
ignore_fields: ["parent_cost_center"],
onload: function (treeview) {
ignore_fields:["parent_cost_center"],
onload: function(treeview) {
function get_company() {
return treeview.page.fields_dict.company.get_value();
}
// tools
treeview.page.add_inner_button(
__("Chart of Accounts"),
function () {
frappe.set_route("Tree", "Account", { company: get_company() });
},
__("View")
);
treeview.page.add_inner_button(__("Chart of Accounts"), function() {
frappe.set_route('Tree', 'Account', {company: get_company()});
}, __('View'));
// make
treeview.page.add_inner_button(
__("Budget List"),
function () {
frappe.set_route("List", "Budget", { company: get_company() });
},
__("Budget")
);
treeview.page.add_inner_button(__("Budget List"), function() {
frappe.set_route('List', 'Budget', {company: get_company()});
}, __('Budget'));
treeview.page.add_inner_button(
__("Monthly Distribution"),
function () {
frappe.set_route("List", "Monthly Distribution", { company: get_company() });
},
__("Budget")
);
treeview.page.add_inner_button(__("Monthly Distribution"), function() {
frappe.set_route('List', 'Monthly Distribution', {company: get_company()});
}, __('Budget'));
treeview.page.add_inner_button(
__("Budget Variance Report"),
function () {
frappe.set_route("query-report", "Budget Variance Report", { company: get_company() });
},
__("Budget")
);
},
};
treeview.page.add_inner_button(__("Budget Variance Report"), function() {
frappe.set_route('query-report', 'Budget Variance Report', {company: get_company()});
}, __('Budget'));
}
}

View File

@@ -1,24 +1,19 @@
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Cost Center Allocation", {
setup: function (frm) {
frm.set_query("main_cost_center", function () {
return {
filters: {
company: frm.doc.company,
is_group: 0,
},
};
});
frappe.ui.form.on('Cost Center Allocation', {
setup: function(frm) {
let filters = {"is_group": 0};
if (frm.doc.company) {
$.extend(filters, {
"company": frm.doc.company
});
}
frm.set_query("cost_center", "allocation_percentages", function () {
frm.set_query('main_cost_center', function() {
return {
filters: {
company: frm.doc.company,
is_group: 0,
},
filters: filters
};
});
},
}
});

View File

@@ -1,41 +1,44 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Coupon Code", {
setup: function (frm) {
frm.set_query("pricing_rule", function () {
frappe.ui.form.on('Coupon Code', {
setup: function(frm) {
frm.set_query("pricing_rule", function() {
return {
filters: [["Pricing Rule", "coupon_code_based", "=", "1"]],
filters: [
["Pricing Rule","coupon_code_based", "=", "1"]
]
};
});
},
coupon_name: function (frm) {
if (frm.doc.__islocal === 1) {
coupon_name:function(frm){
if (frm.doc.__islocal===1) {
frm.trigger("make_coupon_code");
}
},
coupon_type: function (frm) {
if (frm.doc.__islocal === 1) {
coupon_type:function(frm){
if (frm.doc.__islocal===1) {
frm.trigger("make_coupon_code");
}
},
make_coupon_code: function (frm) {
var coupon_name = frm.doc.coupon_name;
make_coupon_code: function(frm) {
var coupon_name=frm.doc.coupon_name;
var coupon_code;
if (frm.doc.coupon_type == "Gift Card") {
coupon_code = Math.random().toString(12).substring(2, 12).toUpperCase();
} else if (frm.doc.coupon_type == "Promotional") {
coupon_name = coupon_name.replace(/\s/g, "");
coupon_code = coupon_name.toUpperCase().slice(0, 8);
if (frm.doc.coupon_type=='Gift Card') {
coupon_code=Math.random().toString(12).substring(2, 12).toUpperCase();
}
frm.doc.coupon_code = coupon_code;
frm.refresh_field("coupon_code");
else if(frm.doc.coupon_type=='Promotional'){
coupon_name=coupon_name.replace(/\s/g,'');
coupon_code=coupon_name.toUpperCase().slice(0,8);
}
frm.doc.coupon_code=coupon_code;
frm.refresh_field('coupon_code');
},
refresh: function (frm) {
refresh: function(frm) {
if (frm.doc.pricing_rule) {
frm.add_custom_button(__("Add/Edit Coupon Conditions"), function () {
frm.add_custom_button(__("Add/Edit Coupon Conditions"), function(){
frappe.set_route("Form", "Pricing Rule", frm.doc.pricing_rule);
});
}
},
}
});

View File

@@ -1,41 +1,28 @@
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Currency Exchange Settings", {
service_provider: function (frm) {
frm.call({
method: "erpnext.accounts.doctype.currency_exchange_settings.currency_exchange_settings.get_api_endpoint",
args: {
service_provider: frm.doc.service_provider,
use_http: frm.doc.use_http,
},
callback: function (r) {
if (r && r.message) {
if (frm.doc.service_provider == "exchangerate.host") {
let result = ["result"];
let params = {
date: "{transaction_date}",
from: "{from_currency}",
to: "{to_currency}",
};
add_param(frm, r.message, params, result);
} else if (frm.doc.service_provider == "frankfurter.app") {
let result = ["rates", "{to_currency}"];
let params = {
base: "{from_currency}",
symbols: "{to_currency}",
};
add_param(frm, r.message, params, result);
}
}
},
});
},
use_http: function (frm) {
frm.trigger("service_provider");
},
frappe.ui.form.on('Currency Exchange Settings', {
service_provider: function(frm) {
if (frm.doc.service_provider == "exchangerate.host") {
let result = ['result'];
let params = {
date: '{transaction_date}',
from: '{from_currency}',
to: '{to_currency}'
};
add_param(frm, "https://api.exchangerate.host/convert", params, result);
} else if (frm.doc.service_provider == "frankfurter.app") {
let result = ['rates', '{to_currency}'];
let params = {
base: '{from_currency}',
symbols: '{to_currency}'
};
add_param(frm, "https://frankfurter.app/{transaction_date}", params, result);
}
}
});
function add_param(frm, api, params, result) {
var row;
frm.clear_table("req_params");
@@ -43,13 +30,13 @@ function add_param(frm, api, params, result) {
frm.doc.api_endpoint = api;
$.each(params, function (key, value) {
$.each(params, function(key, value) {
row = frm.add_child("req_params");
row.key = key;
row.value = value;
});
$.each(result, function (key, value) {
$.each(result, function(key, value) {
row = frm.add_child("result_key");
row.key = value;
});

View File

@@ -6,11 +6,8 @@
"engine": "InnoDB",
"field_order": [
"api_details_section",
"disabled",
"service_provider",
"api_endpoint",
"use_http",
"access_key",
"url",
"column_break_3",
"help",
@@ -80,31 +77,12 @@
"label": "Service Provider",
"options": "frankfurter.app\nexchangerate.host\nCustom",
"reqd": 1
},
{
"default": "0",
"fieldname": "disabled",
"fieldtype": "Check",
"label": "Disabled"
},
{
"depends_on": "eval:doc.service_provider == 'exchangerate.host';",
"fieldname": "access_key",
"fieldtype": "Data",
"label": "Access Key"
},
{
"default": "0",
"depends_on": "eval: doc.service_provider != \"Custom\"",
"fieldname": "use_http",
"fieldtype": "Check",
"label": "Use HTTP Protocol"
}
],
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2024-03-18 08:32:26.895076",
"modified": "2022-01-10 15:51:14.521174",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Currency Exchange Settings",

View File

@@ -18,21 +18,11 @@ class CurrencyExchangeSettings(Document):
def set_parameters_and_result(self):
if self.service_provider == "exchangerate.host":
if not self.access_key:
frappe.throw(
_("Access Key is required for Service Provider: {0}").format(
frappe.bold(self.service_provider)
)
)
self.set("result_key", [])
self.set("req_params", [])
self.api_endpoint = get_api_endpoint(self.service_provider, self.use_http)
self.api_endpoint = "https://api.exchangerate.host/convert"
self.append("result_key", {"key": "result"})
self.append("req_params", {"key": "access_key", "value": self.access_key})
self.append("req_params", {"key": "amount", "value": "1"})
self.append("req_params", {"key": "date", "value": "{transaction_date}"})
self.append("req_params", {"key": "from", "value": "{from_currency}"})
self.append("req_params", {"key": "to", "value": "{to_currency}"})
@@ -40,7 +30,7 @@ class CurrencyExchangeSettings(Document):
self.set("result_key", [])
self.set("req_params", [])
self.api_endpoint = get_api_endpoint(self.service_provider, self.use_http)
self.api_endpoint = "https://frankfurter.app/{transaction_date}"
self.append("result_key", {"key": "rates"})
self.append("result_key", {"key": "{to_currency}"})
self.append("req_params", {"key": "base", "value": "{from_currency}"})
@@ -79,19 +69,3 @@ class CurrencyExchangeSettings(Document):
frappe.throw(_("Returned exchange rate is neither integer not float."))
self.url = response.url
@frappe.whitelist()
def get_api_endpoint(service_provider: str = None, use_http: bool = False):
if service_provider and service_provider in ["exchangerate.host", "frankfurter.app"]:
if service_provider == "exchangerate.host":
api = "api.exchangerate.host/convert"
elif service_provider == "frankfurter.app":
api = "frankfurter.app/{transaction_date}"
protocol = "https://"
if use_http:
protocol = "http://"
return protocol + api
return None

View File

@@ -9,7 +9,7 @@ frappe.ui.form.on("Dunning", {
docstatus: 1,
company: frm.doc.company,
outstanding_amount: [">", 0],
status: "Overdue",
status: "Overdue"
},
};
});
@@ -18,14 +18,18 @@ frappe.ui.form.on("Dunning", {
filters: {
company: frm.doc.company,
root_type: "Income",
is_group: 0,
},
is_group: 0
}
};
});
},
refresh: function (frm) {
frm.set_df_property("company", "read_only", frm.doc.__islocal ? 0 : 1);
frm.set_df_property("sales_invoice", "read_only", frm.doc.__islocal ? 0 : 1);
frm.set_df_property(
"sales_invoice",
"read_only",
frm.doc.__islocal ? 0 : 1
);
if (frm.doc.docstatus === 1 && frm.doc.status === "Unresolved") {
frm.add_custom_button(__("Resolve"), () => {
frm.set_value("status", "Resolved");
@@ -36,27 +40,22 @@ frappe.ui.form.on("Dunning", {
__("Payment"),
function () {
frm.events.make_payment_entry(frm);
},
__("Create")
},__("Create")
);
frm.page.set_inner_btn_group_as_primary(__("Create"));
}
if (frm.doc.docstatus > 0) {
frm.add_custom_button(
__("Ledger"),
function () {
frappe.route_options = {
voucher_no: frm.doc.name,
from_date: frm.doc.posting_date,
to_date: frm.doc.posting_date,
company: frm.doc.company,
show_cancelled_entries: frm.doc.docstatus === 2,
};
frappe.set_route("query-report", "General Ledger");
},
__("View")
);
if(frm.doc.docstatus > 0) {
frm.add_custom_button(__('Ledger'), function() {
frappe.route_options = {
"voucher_no": frm.doc.name,
"from_date": frm.doc.posting_date,
"to_date": frm.doc.posting_date,
"company": frm.doc.company,
"show_cancelled_entries": frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, __('View'));
}
},
overdue_days: function (frm) {
@@ -87,7 +86,8 @@ frappe.ui.form.on("Dunning", {
get_dunning_letter_text: function (frm) {
if (frm.doc.dunning_type) {
frappe.call({
method: "erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
method:
"erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
args: {
dunning_type: frm.doc.dunning_type,
language: frm.doc.language,
@@ -129,25 +129,26 @@ frappe.ui.form.on("Dunning", {
},
calculate_overdue_days: function (frm) {
if (frm.doc.posting_date && frm.doc.due_date) {
const overdue_days = moment(frm.doc.posting_date).diff(frm.doc.due_date, "days");
const overdue_days = moment(frm.doc.posting_date).diff(
frm.doc.due_date,
"days"
);
frm.set_value("overdue_days", overdue_days);
}
},
calculate_interest_and_amount: function (frm) {
const interest_per_year = (frm.doc.outstanding_amount * frm.doc.rate_of_interest) / 100;
const interest_amount = flt(
(interest_per_year * cint(frm.doc.overdue_days)) / 365 || 0,
precision("interest_amount")
);
const dunning_amount = flt(interest_amount + frm.doc.dunning_fee, precision("dunning_amount"));
const grand_total = flt(frm.doc.outstanding_amount + dunning_amount, precision("grand_total"));
const interest_per_year = frm.doc.outstanding_amount * frm.doc.rate_of_interest / 100;
const interest_amount = flt((interest_per_year * cint(frm.doc.overdue_days)) / 365 || 0, precision('interest_amount'));
const dunning_amount = flt(interest_amount + frm.doc.dunning_fee, precision('dunning_amount'));
const grand_total = flt(frm.doc.outstanding_amount + dunning_amount, precision('grand_total'));
frm.set_value("interest_amount", interest_amount);
frm.set_value("dunning_amount", dunning_amount);
frm.set_value("grand_total", grand_total);
},
make_payment_entry: function (frm) {
return frappe.call({
method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
method:
"erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
args: {
dt: frm.doc.doctype,
dn: frm.doc.name,

View File

@@ -1,7 +1,8 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Dunning Type", {
frappe.ui.form.on('Dunning Type', {
// refresh: function(frm) {
// }
});

View File

@@ -1,79 +1,75 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Exchange Rate Revaluation", {
setup: function (frm) {
frm.set_query("party_type", "accounts", function () {
frappe.ui.form.on('Exchange Rate Revaluation', {
setup: function(frm) {
frm.set_query("party_type", "accounts", function() {
return {
filters: {
name: ["in", Object.keys(frappe.boot.party_account_types)],
},
"filters": {
"name": ["in", Object.keys(frappe.boot.party_account_types)],
}
};
});
frm.set_query("account", "accounts", function (doc) {
frm.set_query("account", "accounts", function(doc) {
return {
filters: {
company: doc.company,
},
"filters": {
"company": doc.company
}
};
});
},
refresh: function (frm) {
if (frm.doc.docstatus == 1) {
refresh: function(frm) {
if(frm.doc.docstatus==1) {
frappe.call({
method: "check_journal_entry_condition",
method: 'check_journal_entry_condition',
doc: frm.doc,
callback: function (r) {
callback: function(r) {
if (r.message) {
frm.add_custom_button(
__("Journal Entries"),
function () {
return frm.events.make_jv(frm);
},
__("Create")
);
frm.add_custom_button(__('Journal Entries'), function() {
return frm.events.make_jv(frm);
}, __('Create'));
}
},
}
});
}
},
validate_rounding_loss: function (frm) {
validate_rounding_loss: function(frm) {
let allowance = frm.doc.rounding_loss_allowance;
if (!(allowance >= 0 && allowance < 1)) {
frappe.throw(__("Rounding Loss Allowance should be between 0 and 1"));
}
},
rounding_loss_allowance: function (frm) {
rounding_loss_allowance: function(frm) {
frm.events.validate_rounding_loss(frm);
},
validate: function (frm) {
validate: function(frm) {
frm.events.validate_rounding_loss(frm);
},
get_entries: function (frm, account) {
get_entries: function(frm, account) {
frappe.call({
method: "get_accounts_data",
doc: cur_frm.doc,
account: account,
callback: function (r) {
callback: function(r){
frappe.model.clear_table(frm.doc, "accounts");
if (r.message) {
if(r.message) {
r.message.forEach((d) => {
cur_frm.add_child("accounts", d);
cur_frm.add_child("accounts",d);
});
frm.events.get_total_gain_loss(frm);
refresh_field("accounts");
}
},
}
});
},
get_total_gain_loss: function (frm) {
if (!(frm.doc.accounts && frm.doc.accounts.length)) return;
get_total_gain_loss: function(frm) {
if(!(frm.doc.accounts && frm.doc.accounts.length)) return;
let total_gain_loss = 0;
frm.doc.accounts.forEach((d) => {
@@ -84,7 +80,7 @@ frappe.ui.form.on("Exchange Rate Revaluation", {
frm.refresh_fields();
},
make_jv: function (frm) {
make_jv : function(frm) {
let revaluation_journal = null;
let zero_balance_journal = null;
frappe.call({
@@ -92,68 +88,66 @@ frappe.ui.form.on("Exchange Rate Revaluation", {
doc: frm.doc,
freeze: true,
freeze_message: "Making Journal Entries...",
callback: function (r) {
callback: function(r){
if (r.message) {
let response = r.message;
if (response["revaluation_jv"] || response["zero_balance_jv"]) {
if(response['revaluation_jv'] || response['zero_balance_jv']) {
frappe.msgprint(__("Journals have been created"));
}
}
},
}
});
},
}
});
frappe.ui.form.on("Exchange Rate Revaluation Account", {
new_exchange_rate: function (frm, cdt, cdn) {
new_exchange_rate: function(frm, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
row.new_balance_in_base_currency = flt(
row.new_exchange_rate * flt(row.balance_in_account_currency),
precision("new_balance_in_base_currency", row)
);
row.new_balance_in_base_currency = flt(row.new_exchange_rate * flt(row.balance_in_account_currency),
precision("new_balance_in_base_currency", row));
row.gain_loss = row.new_balance_in_base_currency - flt(row.balance_in_base_currency);
refresh_field("accounts");
frm.events.get_total_gain_loss(frm);
},
account: function (frm, cdt, cdn) {
account: function(frm, cdt, cdn) {
var row = locals[cdt][cdn];
if (row.account) {
get_account_details(frm, cdt, cdn);
}
},
party: function (frm, cdt, cdn) {
party: function(frm, cdt, cdn) {
var row = locals[cdt][cdn];
if (row.party && row.account) {
get_account_details(frm, cdt, cdn);
}
},
accounts_remove: function (frm) {
accounts_remove: function(frm) {
frm.events.get_total_gain_loss(frm);
},
}
});
var get_account_details = function (frm, cdt, cdn) {
var get_account_details = function(frm, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
if (!frm.doc.company || !frm.doc.posting_date) {
if(!frm.doc.company || !frm.doc.posting_date) {
frappe.throw(__("Please select Company and Posting Date to getting entries"));
}
frappe.call({
method: "erpnext.accounts.doctype.exchange_rate_revaluation.exchange_rate_revaluation.get_account_details",
args: {
args:{
account: row.account,
company: frm.doc.company,
posting_date: frm.doc.posting_date,
party_type: row.party_type,
party: row.party,
rounding_loss_allowance: frm.doc.rounding_loss_allowance,
rounding_loss_allowance: frm.doc.rounding_loss_allowance
},
callback: function (r) {
callback: function(r){
$.extend(row, r.message);
refresh_field("accounts");
frm.events.get_total_gain_loss(frm);
},
}
});
};

View File

@@ -192,7 +192,7 @@ class ExchangeRateRevaluation(Document):
# round off balance based on currency precision
# and consider debit-credit difference allowance
currency_precision = get_currency_precision()
rounding_loss_allowance = float(rounding_loss_allowance)
rounding_loss_allowance = float(rounding_loss_allowance) or 0.05
for acc in account_details:
acc.balance_in_account_currency = flt(acc.balance_in_account_currency, currency_precision)
if abs(acc.balance_in_account_currency) <= rounding_loss_allowance:
@@ -606,21 +606,21 @@ def get_account_details(
if account_balance and (
account_balance[0].balance or account_balance[0].balance_in_account_currency
):
if account_with_new_balance := ExchangeRateRevaluation.calculate_new_account_balance(
account_with_new_balance = ExchangeRateRevaluation.calculate_new_account_balance(
company, posting_date, account_balance
):
row = account_with_new_balance[0]
account_details.update(
{
"balance_in_base_currency": row["balance_in_base_currency"],
"balance_in_account_currency": row["balance_in_account_currency"],
"current_exchange_rate": row["current_exchange_rate"],
"new_exchange_rate": row["new_exchange_rate"],
"new_balance_in_base_currency": row["new_balance_in_base_currency"],
"new_balance_in_account_currency": row["new_balance_in_account_currency"],
"zero_balance": row["zero_balance"],
"gain_loss": row["gain_loss"],
}
)
)
row = account_with_new_balance[0]
account_details.update(
{
"balance_in_base_currency": row["balance_in_base_currency"],
"balance_in_account_currency": row["balance_in_account_currency"],
"current_exchange_rate": row["current_exchange_rate"],
"new_exchange_rate": row["new_exchange_rate"],
"new_balance_in_base_currency": row["new_balance_in_base_currency"],
"new_balance_in_account_currency": row["new_balance_in_account_currency"],
"zero_balance": row["zero_balance"],
"gain_loss": row["gain_loss"],
}
)
return account_details

View File

@@ -1,6 +1,8 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Finance Book", {
refresh: function (frm) {},
frappe.ui.form.on('Finance Book', {
refresh: function(frm) {
}
});

View File

@@ -1,21 +1,17 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on("Fiscal Year", {
onload: function (frm) {
if (frm.doc.__islocal) {
frm.set_value(
"year_start_date",
frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)
);
frappe.ui.form.on('Fiscal Year', {
onload: function(frm) {
if(frm.doc.__islocal) {
frm.set_value("year_start_date",
frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1));
}
},
year_start_date: function (frm) {
year_start_date: function(frm) {
if (!frm.doc.is_short_year) {
let year_end_date = frappe.datetime.add_days(
frappe.datetime.add_months(frm.doc.year_start_date, 12),
-1
);
let year_end_date =
frappe.datetime.add_days(frappe.datetime.add_months(frm.doc.year_start_date, 12), -1);
frm.set_value("year_end_date", year_end_date);
}
},

View File

@@ -41,7 +41,7 @@ def test_record_generator():
]
start = 2012
end = now_datetime().year + 25
end = now_datetime().year + 5
for year in range(start, end):
test_records.append(
{

View File

@@ -1,8 +1,8 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("GL Entry", {
refresh: function (frm) {
frm.page.btn_secondary.hide();
},
frappe.ui.form.on('GL Entry', {
refresh: function(frm) {
frm.page.btn_secondary.hide()
}
});

View File

@@ -138,7 +138,8 @@
"label": "Against Voucher Type",
"oldfieldname": "against_voucher_type",
"oldfieldtype": "Data",
"options": "DocType"
"options": "DocType",
"search_index": 1
},
{
"fieldname": "against_voucher",
@@ -157,7 +158,8 @@
"label": "Voucher Type",
"oldfieldname": "voucher_type",
"oldfieldtype": "Select",
"options": "DocType"
"options": "DocType",
"search_index": 1
},
{
"fieldname": "voucher_no",
@@ -174,8 +176,7 @@
"fieldname": "voucher_detail_no",
"fieldtype": "Data",
"label": "Voucher Detail No",
"read_only": 1,
"search_index": 1
"read_only": 1
},
{
"fieldname": "project",
@@ -257,8 +258,7 @@
"icon": "fa fa-list",
"idx": 1,
"in_create": 1,
"links": [],
"modified": "2024-03-19 18:30:49.613401",
"modified": "2020-04-07 16:22:33.766994",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",
@@ -290,6 +290,5 @@
"quick_entry": 1,
"search_fields": "voucher_no,account,posting_date,against_voucher",
"sort_field": "modified",
"sort_order": "DESC",
"states": []
"sort_order": "DESC"
}

View File

@@ -13,9 +13,16 @@ import erpnext
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_checks_for_pl_and_bs_accounts,
)
from erpnext.accounts.doctype.accounting_dimension_filter.accounting_dimension_filter import (
get_dimension_filter_map,
)
from erpnext.accounts.party import validate_party_frozen_disabled, validate_party_gle_currency
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
from erpnext.exceptions import InvalidAccountCurrency
from erpnext.exceptions import (
InvalidAccountCurrency,
InvalidAccountDimensionError,
MandatoryAccountDimensionError,
)
exclude_from_linked_with = True
@@ -47,6 +54,7 @@ class GLEntry(Document):
if not self.flags.from_repost and self.voucher_type != "Period Closing Voucher":
self.validate_account_details(adv_adj)
self.validate_dimensions_for_pl_and_bs()
self.validate_allowed_dimensions()
validate_balance_type(self.account, adv_adj)
validate_frozen_account(self.account, adv_adj)
@@ -127,7 +135,7 @@ class GLEntry(Document):
frappe.throw(msg, title=_("Missing Cost Center"))
def validate_dimensions_for_pl_and_bs(self):
account_type = frappe.get_cached_value("Account", self.account, "report_type")
account_type = frappe.db.get_value("Account", self.account, "report_type")
for dimension in get_checks_for_pl_and_bs_accounts():
if (
@@ -156,10 +164,46 @@ class GLEntry(Document):
)
)
def validate_allowed_dimensions(self):
dimension_filter_map = get_dimension_filter_map()
for key, value in dimension_filter_map.items():
dimension = key[0]
account = key[1]
if self.account == account:
if value["is_mandatory"] and not self.get(dimension):
frappe.throw(
_("{0} is mandatory for account {1}").format(
frappe.bold(frappe.unscrub(dimension)), frappe.bold(self.account)
),
MandatoryAccountDimensionError,
)
if value["allow_or_restrict"] == "Allow":
if self.get(dimension) and self.get(dimension) not in value["allowed_dimensions"]:
frappe.throw(
_("Invalid value {0} for {1} against account {2}").format(
frappe.bold(self.get(dimension)),
frappe.bold(frappe.unscrub(dimension)),
frappe.bold(self.account),
),
InvalidAccountDimensionError,
)
else:
if self.get(dimension) and self.get(dimension) in value["allowed_dimensions"]:
frappe.throw(
_("Invalid value {0} for {1} against account {2}").format(
frappe.bold(self.get(dimension)),
frappe.bold(frappe.unscrub(dimension)),
frappe.bold(self.account),
),
InvalidAccountDimensionError,
)
def check_pl_account(self):
if (
self.is_opening == "Yes"
and frappe.get_cached_value("Account", self.account, "report_type") == "Profit and Loss"
and frappe.db.get_value("Account", self.account, "report_type") == "Profit and Loss"
and not self.is_cancelled
):
frappe.throw(
@@ -252,7 +296,7 @@ class GLEntry(Document):
def validate_balance_type(account, adv_adj=False):
if not adv_adj and account:
balance_must_be = frappe.get_cached_value("Account", account, "balance_must_be")
balance_must_be = frappe.db.get_value("Account", account, "balance_must_be")
if balance_must_be:
balance = frappe.db.sql(
"""select sum(debit) - sum(credit)
@@ -279,7 +323,7 @@ def update_outstanding_amt(
party_condition = ""
if against_voucher_type == "Sales Invoice":
party_account = frappe.get_cached_value(against_voucher_type, against_voucher, "debit_to")
party_account = frappe.db.get_value(against_voucher_type, against_voucher, "debit_to")
account_condition = "and account in ({0}, {1})".format(
frappe.db.escape(account), frappe.db.escape(party_account)
)
@@ -347,7 +391,7 @@ def update_outstanding_amt(
def validate_frozen_account(account, adv_adj=None):
frozen_account = frappe.get_cached_value("Account", account, "freeze_account")
if frozen_account == "Yes" and not adv_adj:
frozen_accounts_modifier = frappe.get_cached_value(
frozen_accounts_modifier = frappe.db.get_value(
"Accounts Settings", None, "frozen_accounts_modifier"
)

View File

@@ -1,49 +1,47 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Invoice Discounting", {
frappe.ui.form.on('Invoice Discounting', {
setup: (frm) => {
frm.set_query("sales_invoice", "invoices", (doc) => {
return {
filters: {
docstatus: 1,
company: doc.company,
outstanding_amount: [">", 0],
"filters": {
"docstatus": 1,
"company": doc.company,
"outstanding_amount": [">", 0]
},
};
});
frm.events.filter_accounts("bank_account", frm, [["account_type", "=", "Bank"]]);
frm.events.filter_accounts("bank_charges_account", frm, [["root_type", "=", "Expense"]]);
frm.events.filter_accounts("short_term_loan", frm, [["root_type", "=", "Liability"]]);
frm.events.filter_accounts("accounts_receivable_discounted", frm, [
["account_type", "=", "Receivable"],
]);
frm.events.filter_accounts("accounts_receivable_discounted", frm, [["account_type", "=", "Receivable"]]);
frm.events.filter_accounts("accounts_receivable_credit", frm, [["account_type", "=", "Receivable"]]);
frm.events.filter_accounts("accounts_receivable_unpaid", frm, [["account_type", "=", "Receivable"]]);
},
filter_accounts: (fieldname, frm, addl_filters) => {
let filters = [
["company", "=", frm.doc.company],
["is_group", "=", 0],
["is_group", "=", 0]
];
if (addl_filters) {
filters = $.merge(filters, addl_filters);
if(addl_filters){
filters = $.merge(filters , addl_filters);
}
frm.set_query(fieldname, () => {
return { filters: filters };
});
frm.set_query(fieldname, () => { return { "filters": filters }; });
},
refresh_filters: (frm) => {
let invoice_accounts = Object.keys(frm.doc.invoices).map(function (key) {
refresh_filters: (frm) =>{
let invoice_accounts = Object.keys(frm.doc.invoices).map(function(key) {
return frm.doc.invoices[key].debit_to;
});
let filters = [
["account_type", "=", "Receivable"],
["name", "not in", invoice_accounts],
["name", "not in", invoice_accounts]
];
frm.events.filter_accounts("accounts_receivable_credit", frm, filters);
frm.events.filter_accounts("accounts_receivable_discounted", frm, filters);
@@ -54,19 +52,19 @@ frappe.ui.form.on("Invoice Discounting", {
frm.events.show_general_ledger(frm);
if (frm.doc.docstatus === 0) {
frm.add_custom_button(__("Get Invoices"), function () {
frm.add_custom_button(__('Get Invoices'), function() {
frm.events.get_invoices(frm);
});
}
if (frm.doc.docstatus === 1 && frm.doc.status !== "Settled") {
if (frm.doc.status == "Sanctioned") {
frm.add_custom_button(__("Disburse Loan"), function () {
frm.add_custom_button(__('Disburse Loan'), function() {
frm.events.create_disbursement_entry(frm);
}).addClass("btn-primary");
}
if (frm.doc.status == "Disbursed") {
frm.add_custom_button(__("Close Loan"), function () {
frm.add_custom_button(__('Close Loan'), function() {
frm.events.close_loan(frm);
}).addClass("btn-primary");
}
@@ -94,121 +92,119 @@ frappe.ui.form.on("Invoice Discounting", {
calculate_total_amount: (frm) => {
let total_amount = 0.0;
for (let row of frm.doc.invoices || []) {
for (let row of (frm.doc.invoices || [])) {
total_amount += flt(row.outstanding_amount);
}
frm.set_value("total_amount", total_amount);
},
get_invoices: (frm) => {
var d = new frappe.ui.Dialog({
title: __("Get Invoices based on Filters"),
title: __('Get Invoices based on Filters'),
fields: [
{
label: "Customer",
fieldname: "customer",
fieldtype: "Link",
options: "Customer",
"label": "Customer",
"fieldname": "customer",
"fieldtype": "Link",
"options": "Customer"
},
{
label: "From Date",
fieldname: "from_date",
fieldtype: "Date",
"label": "From Date",
"fieldname": "from_date",
"fieldtype": "Date"
},
{
label: "To Date",
fieldname: "to_date",
fieldtype: "Date",
"label": "To Date",
"fieldname": "to_date",
"fieldtype": "Date"
},
{
fieldname: "col_break",
fieldtype: "Column Break",
"fieldname": "col_break",
"fieldtype": "Column Break",
},
{
label: "Min Amount",
fieldname: "min_amount",
fieldtype: "Currency",
"label": "Min Amount",
"fieldname": "min_amount",
"fieldtype": "Currency"
},
{
label: "Max Amount",
fieldname: "max_amount",
fieldtype: "Currency",
},
"label": "Max Amount",
"fieldname": "max_amount",
"fieldtype": "Currency"
}
],
primary_action: function () {
primary_action: function() {
var data = d.get_values();
frappe.call({
method: "erpnext.accounts.doctype.invoice_discounting.invoice_discounting.get_invoices",
args: {
filters: data,
filters: data
},
callback: function (r) {
if (!r.exc) {
callback: function(r) {
if(!r.exc) {
d.hide();
$.each(r.message, function (i, v) {
frm.doc.invoices = frm.doc.invoices.filter((row) => row.sales_invoice);
$.each(r.message, function(i, v) {
frm.doc.invoices = frm.doc.invoices.filter(row => row.sales_invoice);
let row = frm.add_child("invoices");
$.extend(row, v);
frm.events.refresh_filters(frm);
});
refresh_field("invoices");
}
},
}
});
},
primary_action_label: __("Get Invocies"),
primary_action_label: __('Get Invocies')
});
d.show();
},
create_disbursement_entry: (frm) => {
frappe.call({
method: "create_disbursement_entry",
method:"create_disbursement_entry",
doc: frm.doc,
callback: function (r) {
if (!r.exc) {
callback: function(r) {
if(!r.exc){
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
},
}
});
},
close_loan: (frm) => {
frappe.call({
method: "close_loan",
method:"close_loan",
doc: frm.doc,
callback: function (r) {
if (!r.exc) {
callback: function(r) {
if(!r.exc){
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
},
}
});
},
show_general_ledger: (frm) => {
if (frm.doc.docstatus > 0) {
cur_frm.add_custom_button(
__("Accounting Ledger"),
function () {
frappe.route_options = {
voucher_no: frm.doc.name,
from_date: frm.doc.posting_date,
to_date: moment(frm.doc.modified).format("YYYY-MM-DD"),
company: frm.doc.company,
group_by: "Group by Voucher (Consolidated)",
show_cancelled_entries: frm.doc.docstatus === 2,
};
frappe.set_route("query-report", "General Ledger");
},
__("View")
);
if(frm.doc.docstatus > 0) {
cur_frm.add_custom_button(__('Accounting Ledger'), function() {
frappe.route_options = {
voucher_no: frm.doc.name,
from_date: frm.doc.posting_date,
to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
company: frm.doc.company,
group_by: "Group by Voucher (Consolidated)",
show_cancelled_entries: frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, __("View"));
}
},
}
});
frappe.ui.form.on("Discounted Invoice", {
frappe.ui.form.on('Discounted Invoice', {
sales_invoice: (frm) => {
frm.events.calculate_total_amount(frm);
frm.events.refresh_filters(frm);
@@ -216,5 +212,5 @@ frappe.ui.form.on("Discounted Invoice", {
invoices_remove: (frm) => {
frm.events.calculate_total_amount(frm);
frm.events.refresh_filters(frm);
},
}
});

View File

@@ -1,16 +1,21 @@
frappe.listview_settings["Invoice Discounting"] = {
frappe.listview_settings['Invoice Discounting'] = {
add_fields: ["status"],
get_indicator: function (doc) {
if (doc.status == "Draft") {
get_indicator: function(doc)
{
if(doc.status == "Draft") {
return [__("Draft"), "red", "status,=,Draft"];
} else if (doc.status == "Sanctioned") {
}
else if(doc.status == "Sanctioned") {
return [__("Sanctioned"), "green", "status,=,Sanctioned"];
} else if (doc.status == "Disbursed") {
}
else if(doc.status == "Disbursed") {
return [__("Disbursed"), "blue", "status,=,Disbursed"];
} else if (doc.status == "Settled") {
}
else if(doc.status == "Settled") {
return [__("Settled"), "orange", "status,=,Settled"];
} else if (doc.status == "Canceled") {
}
else if(doc.status == "Canceled") {
return [__("Canceled"), "red", "status,=,Canceled"];
}
},
}
};

View File

@@ -1,49 +1,27 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Item Tax Template", {
setup: function (frm) {
frm.set_query("tax_type", "taxes", function (doc) {
frappe.ui.form.on('Item Tax Template', {
setup: function(frm) {
frm.set_query("tax_type", "taxes", function(doc) {
return {
filters: [
["Account", "company", "=", frm.doc.company],
["Account", "is_group", "=", 0],
[
"Account",
"account_type",
"in",
[
"Tax",
"Chargeable",
"Income Account",
"Expense Account",
"Expenses Included In Valuation",
],
],
],
};
['Account', 'company', '=', frm.doc.company],
['Account', 'is_group', '=', 0],
['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']]
]
}
});
},
company: function (frm) {
frm.set_query("tax_type", "taxes", function (doc) {
frm.set_query("tax_type", "taxes", function(doc) {
return {
filters: [
["Account", "company", "=", frm.doc.company],
["Account", "is_group", "=", 0],
[
"Account",
"account_type",
"in",
[
"Tax",
"Chargeable",
"Income Account",
"Expense Account",
"Expenses Included In Valuation",
],
],
],
};
['Account', 'company', '=', frm.doc.company],
['Account', 'is_group', '=', 0],
['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']]
]
}
});
},
}
});

View File

@@ -4,57 +4,39 @@
frappe.provide("erpnext.accounts");
frappe.provide("erpnext.journal_entry");
frappe.ui.form.on("Journal Entry", {
setup: function (frm) {
setup: function(frm) {
frm.add_fetch("bank_account", "account", "account");
frm.ignore_doctypes_on_cancel_all = [
"Sales Invoice",
"Purchase Invoice",
"Journal Entry",
"Repost Payment Ledger",
"Asset",
"Asset Movement",
"Repost Accounting Ledger",
"Unreconcile Payment",
"Unreconcile Payment Entries",
"Bank Transaction",
];
frm.ignore_doctypes_on_cancel_all = ['Sales Invoice', 'Purchase Invoice', 'Journal Entry', 'Repost Payment Ledger', 'Asset', 'Asset Movement', 'Repost Accounting Ledger'];
},
refresh: function (frm) {
refresh: function(frm) {
erpnext.toggle_naming_series();
if (frm.doc.docstatus > 0) {
frm.add_custom_button(
__("Ledger"),
function () {
frappe.route_options = {
voucher_no: frm.doc.name,
from_date: frm.doc.posting_date,
to_date: moment(frm.doc.modified).format("YYYY-MM-DD"),
company: frm.doc.company,
finance_book: frm.doc.finance_book,
group_by: "",
show_cancelled_entries: frm.doc.docstatus === 2,
};
frappe.set_route("query-report", "General Ledger");
},
__("View")
);
if(frm.doc.docstatus > 0) {
frm.add_custom_button(__('Ledger'), function() {
frappe.route_options = {
"voucher_no": frm.doc.name,
"from_date": frm.doc.posting_date,
"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'),
"company": frm.doc.company,
"finance_book": frm.doc.finance_book,
"group_by": '',
"show_cancelled_entries": frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, __('View'));
}
if (frm.doc.docstatus == 1) {
frm.add_custom_button(
__("Reverse Journal Entry"),
function () {
return erpnext.journal_entry.reverse_journal_entry(frm);
},
__("Actions")
);
if(frm.doc.docstatus==1) {
frm.add_custom_button(__('Reverse Journal Entry'), function() {
return erpnext.journal_entry.reverse_journal_entry(frm);
}, __('Actions'));
}
if (frm.doc.__islocal) {
frm.add_custom_button(__("Quick Entry"), function () {
frm.add_custom_button(__('Quick Entry'), function() {
return erpnext.journal_entry.quick_entry(frm);
});
}
@@ -62,63 +44,42 @@ frappe.ui.form.on("Journal Entry", {
// hide /unhide fields based on currency
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
if (
frm.doc.voucher_type == "Inter Company Journal Entry" &&
frm.doc.docstatus == 1 &&
!frm.doc.inter_company_journal_entry_reference
) {
frm.add_custom_button(
__("Create Inter Company Journal Entry"),
function () {
if ((frm.doc.voucher_type == "Inter Company Journal Entry") && (frm.doc.docstatus == 1) && (!frm.doc.inter_company_journal_entry_reference)) {
frm.add_custom_button(__("Create Inter Company Journal Entry"),
function() {
frm.trigger("make_inter_company_journal_entry");
},
__("Make")
);
}, __('Make'));
}
},
erpnext.accounts.unreconcile_payment.add_unreconcile_btn(frm);
},
before_save: function (frm) {
if (frm.doc.docstatus == 0 && !frm.doc.is_system_generated) {
let payment_entry_references = frm.doc.accounts.filter(
(elem) => elem.reference_type == "Payment Entry"
);
if (payment_entry_references.length > 0) {
let rows = payment_entry_references.map((x) => "#" + x.idx);
frappe.throw(
__("Rows: {0} have 'Payment Entry' as reference_type. This should not be set manually.", [
frappe.utils.comma_and(rows),
])
);
}
}
},
make_inter_company_journal_entry: function (frm) {
make_inter_company_journal_entry: function(frm) {
var d = new frappe.ui.Dialog({
title: __("Select Company"),
fields: [
{
fieldname: "company",
fieldtype: "Link",
label: __("Company"),
options: "Company",
get_query: function () {
'fieldname': 'company',
'fieldtype': 'Link',
'label': __('Company'),
'options': 'Company',
"get_query": function () {
return {
filters: [["Company", "name", "!=", frm.doc.company]],
filters: [
["Company", "name", "!=", frm.doc.company]
]
};
},
reqd: 1,
},
'reqd': 1
}
],
});
d.set_primary_action(__("Create"), function () {
d.set_primary_action(__('Create'), function() {
d.hide();
var args = d.get_values();
frappe.call({
args: {
name: frm.doc.name,
voucher_type: frm.doc.voucher_type,
company: args.company,
"name": frm.doc.name,
"voucher_type": frm.doc.voucher_type,
"company": args.company
},
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_inter_company_journal_entry",
callback: function (r) {
@@ -126,106 +87,103 @@ frappe.ui.form.on("Journal Entry", {
var doc = frappe.model.sync(r.message)[0];
frappe.set_route("Form", doc.doctype, doc.name);
}
},
}
});
});
d.show();
},
multi_currency: function (frm) {
multi_currency: function(frm) {
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
},
posting_date: function (frm) {
if (!frm.doc.multi_currency || !frm.doc.posting_date) return;
posting_date: function(frm) {
if(!frm.doc.multi_currency || !frm.doc.posting_date) return;
$.each(frm.doc.accounts || [], function (i, row) {
$.each(frm.doc.accounts || [], function(i, row) {
erpnext.journal_entry.set_exchange_rate(frm, row.doctype, row.name);
});
})
},
company: function (frm) {
company: function(frm) {
frappe.call({
method: "frappe.client.get_value",
args: {
doctype: "Company",
filters: { name: frm.doc.company },
fieldname: "cost_center",
filters: {"name": frm.doc.company},
fieldname: "cost_center"
},
callback: function (r) {
if (r.message) {
$.each(frm.doc.accounts || [], function (i, jvd) {
callback: function(r){
if(r.message){
$.each(frm.doc.accounts || [], function(i, jvd) {
frappe.model.set_value(jvd.doctype, jvd.name, "cost_center", r.message.cost_center);
});
}
},
}
});
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
},
voucher_type: function (frm) {
if (!frm.doc.company) return null;
voucher_type: function(frm){
if (
!(frm.doc.accounts || []).length ||
((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)
) {
if (in_list(["Bank Entry", "Cash Entry"], frm.doc.voucher_type)) {
if(!frm.doc.company) return null;
if((!(frm.doc.accounts || []).length) || ((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)) {
if(in_list(["Bank Entry", "Cash Entry"], frm.doc.voucher_type)) {
return frappe.call({
type: "GET",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
args: {
account_type:
frm.doc.voucher_type == "Bank Entry"
? "Bank"
: frm.doc.voucher_type == "Cash Entry"
? "Cash"
: null,
company: frm.doc.company,
"account_type": (frm.doc.voucher_type=="Bank Entry" ?
"Bank" : (frm.doc.voucher_type=="Cash Entry" ? "Cash" : null)),
"company": frm.doc.company
},
callback: function (r) {
if (r.message) {
callback: function(r) {
if(r.message) {
// If default company bank account not set
if (!$.isEmptyObject(r.message)) {
if(!$.isEmptyObject(r.message)){
update_jv_details(frm.doc, [r.message]);
}
}
},
}
});
}
}
},
from_template: function (frm) {
if (frm.doc.from_template) {
frappe.db.get_doc("Journal Entry Template", frm.doc.from_template).then((doc) => {
frappe.model.clear_table(frm.doc, "accounts");
frm.set_value({
company: doc.company,
voucher_type: doc.voucher_type,
naming_series: doc.naming_series,
is_opening: doc.is_opening,
multi_currency: doc.multi_currency,
from_template: function(frm){
if (frm.doc.from_template){
frappe.db.get_doc("Journal Entry Template", frm.doc.from_template)
.then((doc) => {
frappe.model.clear_table(frm.doc, "accounts");
frm.set_value({
"company": doc.company,
"voucher_type": doc.voucher_type,
"naming_series": doc.naming_series,
"is_opening": doc.is_opening,
"multi_currency": doc.multi_currency
})
update_jv_details(frm.doc, doc.accounts);
});
update_jv_details(frm.doc, doc.accounts);
});
}
},
}
});
var update_jv_details = function (doc, r) {
$.each(r, function (i, d) {
var update_jv_details = function(doc, r) {
$.each(r, function(i, d) {
var row = frappe.model.add_child(doc, "Journal Entry Account", "accounts");
frappe.model.set_value(row.doctype, row.name, "account", d.account);
frappe.model.set_value(row.doctype, row.name, "account", d.account)
frappe.model.set_value(row.doctype, row.name, "balance", d.balance)
});
refresh_field("accounts");
};
}
erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Controller {
onload() {
this.load_defaults();
this.setup_queries();
this.setup_balance_formatter();
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
}
@@ -235,67 +193,69 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
load_defaults() {
//this.frm.show_print_first = true;
if (this.frm.doc.__islocal && this.frm.doc.company) {
if(this.frm.doc.__islocal && this.frm.doc.company) {
frappe.model.set_default_values(this.frm.doc);
$.each(this.frm.doc.accounts || [], function (i, jvd) {
$.each(this.frm.doc.accounts || [], function(i, jvd) {
frappe.model.set_default_values(jvd);
});
var posting_date = this.frm.doc.posting_date;
if (!this.frm.doc.amended_from)
this.frm.set_value("posting_date", posting_date || frappe.datetime.get_today());
if(!this.frm.doc.amended_from) this.frm.set_value('posting_date', posting_date || frappe.datetime.get_today());
}
}
setup_queries() {
var me = this;
me.frm.set_query("account", "accounts", function (doc, cdt, cdn) {
me.frm.set_query("account", "accounts", function(doc, cdt, cdn) {
return erpnext.journal_entry.account_query(me.frm);
});
me.frm.set_query("party_type", "accounts", function (doc, cdt, cdn) {
me.frm.set_query("party_type", "accounts", function(doc, cdt, cdn) {
const row = locals[cdt][cdn];
return {
query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
filters: {
account: row.account,
},
};
'account': row.account
}
}
});
me.frm.set_query("reference_name", "accounts", function (doc, cdt, cdn) {
me.frm.set_query("reference_name", "accounts", function(doc, cdt, cdn) {
var jvd = frappe.get_doc(cdt, cdn);
// journal entry
if (jvd.reference_type === "Journal Entry") {
if(jvd.reference_type==="Journal Entry") {
frappe.model.validate_missing(jvd, "account");
return {
query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_jv",
filters: {
account: jvd.account,
party: jvd.party,
},
party: jvd.party
}
};
}
var out = {
filters: [[jvd.reference_type, "docstatus", "=", 1]],
filters: [
[jvd.reference_type, "docstatus", "=", 1]
]
};
if (in_list(["Sales Invoice", "Purchase Invoice"], jvd.reference_type)) {
if(in_list(["Sales Invoice", "Purchase Invoice"], jvd.reference_type)) {
out.filters.push([jvd.reference_type, "outstanding_amount", "!=", 0]);
// Filter by cost center
if (jvd.cost_center) {
if(jvd.cost_center) {
out.filters.push([jvd.reference_type, "cost_center", "in", ["", jvd.cost_center]]);
}
// account filter
frappe.model.validate_missing(jvd, "account");
var party_account_field = jvd.reference_type === "Sales Invoice" ? "debit_to" : "credit_to";
var party_account_field = jvd.reference_type==="Sales Invoice" ? "debit_to": "credit_to";
out.filters.push([jvd.reference_type, party_account_field, "=", jvd.account]);
}
if (in_list(["Sales Order", "Purchase Order"], jvd.reference_type)) {
if(in_list(["Sales Order", "Purchase Order"], jvd.reference_type)) {
// party_type and party mandatory
frappe.model.validate_missing(jvd, "party_type");
frappe.model.validate_missing(jvd, "party");
@@ -303,11 +263,11 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
out.filters.push([jvd.reference_type, "per_billed", "<", 100]);
}
if (jvd.party_type && jvd.party) {
if(jvd.party_type && jvd.party) {
var party_field = "";
if (jvd.reference_type.indexOf("Sales") === 0) {
if(jvd.reference_type.indexOf("Sales")===0) {
var party_field = "customer";
} else if (jvd.reference_type.indexOf("Purchase") === 0) {
} else if (jvd.reference_type.indexOf("Purchase")===0) {
var party_field = "supplier";
}
@@ -318,49 +278,64 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
return out;
});
}
setup_balance_formatter() {
const formatter = function(value, df, options, doc) {
var currency = frappe.meta.get_field_currency(df, doc);
var dr_or_cr = value ? ('<label>' + (value > 0.0 ? __("Dr") : __("Cr")) + '</label>') : "";
return "<div style='text-align: right'>"
+ ((value==null || value==="") ? "" : format_currency(Math.abs(value), currency))
+ " " + dr_or_cr
+ "</div>";
};
this.frm.fields_dict.accounts.grid.update_docfield_property('balance', 'formatter', formatter);
this.frm.fields_dict.accounts.grid.update_docfield_property('party_balance', 'formatter', formatter);
}
reference_name(doc, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn);
if (d.reference_name) {
if (d.reference_type === "Purchase Invoice" && !flt(d.debit)) {
this.get_outstanding("Purchase Invoice", d.reference_name, doc.company, d);
} else if (d.reference_type === "Sales Invoice" && !flt(d.credit)) {
this.get_outstanding("Sales Invoice", d.reference_name, doc.company, d);
} else if (d.reference_type === "Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
this.get_outstanding("Journal Entry", d.reference_name, doc.company, d);
if(d.reference_name) {
if (d.reference_type==="Purchase Invoice" && !flt(d.debit)) {
this.get_outstanding('Purchase Invoice', d.reference_name, doc.company, d);
} else if (d.reference_type==="Sales Invoice" && !flt(d.credit)) {
this.get_outstanding('Sales Invoice', d.reference_name, doc.company, d);
} else if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
this.get_outstanding('Journal Entry', d.reference_name, doc.company, d);
}
}
}
get_outstanding(doctype, docname, company, child) {
var args = {
doctype: doctype,
docname: docname,
party: child.party,
account: child.account,
account_currency: child.account_currency,
company: company,
};
"doctype": doctype,
"docname": docname,
"party": child.party,
"account": child.account,
"account_currency": child.account_currency,
"company": company
}
return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_outstanding",
args: { args: args },
callback: function (r) {
if (r.message) {
$.each(r.message, function (field, value) {
args: { args: args},
callback: function(r) {
if(r.message) {
$.each(r.message, function(field, value) {
frappe.model.set_value(child.doctype, child.name, field, value);
});
})
}
},
}
});
}
accounts_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
$.each(doc.accounts, function (i, d) {
if (d.account && d.party && d.party_type) {
$.each(doc.accounts, function(i, d) {
if(d.account && d.party && d.party_type) {
row.account = d.account;
row.party = d.party;
row.party_type = d.party_type;
@@ -368,8 +343,8 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
});
// set difference
if (doc.difference) {
if (doc.difference > 0) {
if(doc.difference) {
if(doc.difference > 0) {
row.credit_in_account_currency = doc.difference;
row.credit = doc.difference;
} else {
@@ -379,141 +354,132 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
}
cur_frm.cscript.update_totals(doc);
erpnext.accounts.dimensions.copy_dimension_from_first_row(this.frm, cdt, cdn, "accounts");
erpnext.accounts.dimensions.copy_dimension_from_first_row(this.frm, cdt, cdn, 'accounts');
}
};
cur_frm.script_manager.make(erpnext.accounts.JournalEntry);
cur_frm.cscript.update_totals = function (doc) {
var td = 0.0;
var tc = 0.0;
cur_frm.cscript.update_totals = function(doc) {
var td=0.0; var tc =0.0;
var accounts = doc.accounts || [];
for (var i in accounts) {
for(var i in accounts) {
td += flt(accounts[i].debit, precision("debit", accounts[i]));
tc += flt(accounts[i].credit, precision("credit", accounts[i]));
}
var doc = locals[doc.doctype][doc.name];
doc.total_debit = td;
doc.total_credit = tc;
doc.difference = flt(td - tc, precision("difference"));
refresh_many(["total_debit", "total_credit", "difference"]);
};
doc.difference = flt((td - tc), precision("difference"));
refresh_many(['total_debit','total_credit','difference']);
}
cur_frm.cscript.get_balance = function (doc, dt, dn) {
cur_frm.cscript.get_balance = function(doc,dt,dn) {
cur_frm.cscript.update_totals(doc);
cur_frm.call("get_balance", null, () => {
cur_frm.refresh();
});
};
cur_frm.call('get_balance', null, () => { cur_frm.refresh(); });
}
cur_frm.cscript.validate = function (doc, cdt, cdn) {
cur_frm.cscript.validate = function(doc,cdt,cdn) {
cur_frm.cscript.update_totals(doc);
};
}
frappe.ui.form.on("Journal Entry Account", {
party: function (frm, cdt, cdn) {
party: function(frm, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn);
if (!d.account && d.party_type && d.party) {
if (!frm.doc.company) frappe.throw(__("Please select Company"));
if(!d.account && d.party_type && d.party) {
if(!frm.doc.company) frappe.throw(__("Please select Company"));
return frm.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_party_account_and_currency",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_party_account_and_balance",
child: d,
args: {
company: frm.doc.company,
party_type: d.party_type,
party: d.party,
},
cost_center: d.cost_center
}
});
}
},
cost_center: function (frm, dt, dn) {
erpnext.journal_entry.set_account_details(frm, dt, dn);
cost_center: function(frm, dt, dn) {
erpnext.journal_entry.set_account_balance(frm, dt, dn);
},
account: function (frm, dt, dn) {
erpnext.journal_entry.set_account_details(frm, dt, dn);
account: function(frm, dt, dn) {
erpnext.journal_entry.set_account_balance(frm, dt, dn);
},
debit_in_account_currency: function (frm, cdt, cdn) {
debit_in_account_currency: function(frm, cdt, cdn) {
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
},
credit_in_account_currency: function (frm, cdt, cdn) {
credit_in_account_currency: function(frm, cdt, cdn) {
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
},
debit: function (frm, dt, dn) {
debit: function(frm, dt, dn) {
cur_frm.cscript.update_totals(frm.doc);
},
credit: function (frm, dt, dn) {
credit: function(frm, dt, dn) {
cur_frm.cscript.update_totals(frm.doc);
},
exchange_rate: function (frm, cdt, cdn) {
exchange_rate: function(frm, cdt, cdn) {
var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
var row = locals[cdt][cdn];
if (row.account_currency == company_currency || !frm.doc.multi_currency) {
if(row.account_currency == company_currency || !frm.doc.multi_currency) {
frappe.model.set_value(cdt, cdn, "exchange_rate", 1);
}
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
},
});
}
})
frappe.ui.form.on("Journal Entry Account", "accounts_remove", function (frm) {
frappe.ui.form.on("Journal Entry Account", "accounts_remove", function(frm) {
cur_frm.cscript.update_totals(frm.doc);
});
$.extend(erpnext.journal_entry, {
toggle_fields_based_on_currency: function (frm) {
toggle_fields_based_on_currency: function(frm) {
var fields = ["currency_section", "account_currency", "exchange_rate", "debit", "credit"];
var grid = frm.get_field("accounts").grid;
if (grid) grid.set_column_disp(fields, frm.doc.multi_currency);
if(grid) grid.set_column_disp(fields, frm.doc.multi_currency);
// dynamic label
var field_label_map = {
debit_in_account_currency: "Debit",
credit_in_account_currency: "Credit",
"debit_in_account_currency": "Debit",
"credit_in_account_currency": "Credit"
};
$.each(field_label_map, function (fieldname, label) {
frm.fields_dict.accounts.grid.update_docfield_property(
fieldname,
"label",
frm.doc.multi_currency ? label + " in Account Currency" : label
'label',
frm.doc.multi_currency ? (label + " in Account Currency") : label
);
});
})
},
set_debit_credit_in_company_currency: function (frm, cdt, cdn) {
set_debit_credit_in_company_currency: function(frm, cdt, cdn) {
var row = locals[cdt][cdn];
frappe.model.set_value(
cdt,
cdn,
"debit",
flt(flt(row.debit_in_account_currency) * row.exchange_rate, precision("debit", row))
);
frappe.model.set_value(cdt, cdn, "debit",
flt(flt(row.debit_in_account_currency)*row.exchange_rate, precision("debit", row)));
frappe.model.set_value(
cdt,
cdn,
"credit",
flt(flt(row.credit_in_account_currency) * row.exchange_rate, precision("credit", row))
);
frappe.model.set_value(cdt, cdn, "credit",
flt(flt(row.credit_in_account_currency)*row.exchange_rate, precision("credit", row)));
cur_frm.cscript.update_totals(frm.doc);
},
set_exchange_rate: function (frm, cdt, cdn) {
set_exchange_rate: function(frm, cdt, cdn) {
var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
var row = locals[cdt][cdn];
if (row.account_currency == company_currency || !frm.doc.multi_currency) {
if(row.account_currency == company_currency || !frm.doc.multi_currency) {
row.exchange_rate = 1;
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
} else if (!row.exchange_rate || row.exchange_rate == 1 || row.account_type == "Bank") {
@@ -528,70 +494,50 @@ $.extend(erpnext.journal_entry, {
reference_name: cstr(row.reference_name),
debit: flt(row.debit_in_account_currency),
credit: flt(row.credit_in_account_currency),
exchange_rate: row.exchange_rate,
exchange_rate: row.exchange_rate
},
callback: function (r) {
if (r.message) {
callback: function(r) {
if(r.message) {
row.exchange_rate = r.message;
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
}
},
});
}
})
} else {
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
}
refresh_field("exchange_rate", cdn, "accounts");
},
quick_entry: function (frm) {
quick_entry: function(frm) {
var naming_series_options = frm.fields_dict.naming_series.df.options;
var naming_series_default =
frm.fields_dict.naming_series.df.default || naming_series_options.split("\n")[0];
var naming_series_default = frm.fields_dict.naming_series.df.default || naming_series_options.split("\n")[0];
var dialog = new frappe.ui.Dialog({
title: __("Quick Journal Entry"),
fields: [
{ fieldtype: "Currency", fieldname: "debit", label: __("Amount"), reqd: 1 },
{
fieldtype: "Link",
fieldname: "debit_account",
label: __("Debit Account"),
reqd: 1,
{fieldtype: "Currency", fieldname: "debit", label: __("Amount"), reqd: 1},
{fieldtype: "Link", fieldname: "debit_account", label: __("Debit Account"), reqd: 1,
options: "Account",
get_query: function () {
get_query: function() {
return erpnext.journal_entry.account_query(frm);
},
}
},
{
fieldtype: "Link",
fieldname: "credit_account",
label: __("Credit Account"),
reqd: 1,
{fieldtype: "Link", fieldname: "credit_account", label: __("Credit Account"), reqd: 1,
options: "Account",
get_query: function () {
get_query: function() {
return erpnext.journal_entry.account_query(frm);
},
}
},
{
fieldtype: "Date",
fieldname: "posting_date",
label: __("Date"),
reqd: 1,
default: frm.doc.posting_date,
},
{ fieldtype: "Small Text", fieldname: "user_remark", label: __("User Remark") },
{
fieldtype: "Select",
fieldname: "naming_series",
label: __("Series"),
reqd: 1,
options: naming_series_options,
default: naming_series_default,
},
],
{fieldtype: "Date", fieldname: "posting_date", label: __("Date"), reqd: 1,
default: frm.doc.posting_date},
{fieldtype: "Small Text", fieldname: "user_remark", label: __("User Remark")},
{fieldtype: "Select", fieldname: "naming_series", label: __("Series"), reqd: 1,
options: naming_series_options, default: naming_series_default},
]
});
dialog.set_primary_action(__("Save"), function () {
dialog.set_primary_action(__("Save"), function() {
var btn = this;
var values = dialog.get_values();
@@ -608,21 +554,11 @@ $.extend(erpnext.journal_entry, {
var debit_row = frm.fields_dict.accounts.grid.add_new_row();
frappe.model.set_value(debit_row.doctype, debit_row.name, "account", values.debit_account);
frappe.model.set_value(
debit_row.doctype,
debit_row.name,
"debit_in_account_currency",
values.debit
);
frappe.model.set_value(debit_row.doctype, debit_row.name, "debit_in_account_currency", values.debit);
var credit_row = frm.fields_dict.accounts.grid.add_new_row();
frappe.model.set_value(credit_row.doctype, credit_row.name, "account", values.credit_account);
frappe.model.set_value(
credit_row.doctype,
credit_row.name,
"credit_in_account_currency",
values.debit
);
frappe.model.set_value(credit_row.doctype, credit_row.name, "credit_in_account_currency", values.debit);
frm.save();
@@ -632,36 +568,36 @@ $.extend(erpnext.journal_entry, {
dialog.show();
},
account_query: function (frm) {
account_query: function(frm) {
var filters = {
company: frm.doc.company,
is_group: 0,
is_group: 0
};
if (!frm.doc.multi_currency) {
if(!frm.doc.multi_currency) {
$.extend(filters, {
account_currency: frappe.get_doc(":Company", frm.doc.company).default_currency,
account_currency: frappe.get_doc(":Company", frm.doc.company).default_currency
});
}
return { filters: filters };
},
reverse_journal_entry: function () {
reverse_journal_entry: function() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_reverse_journal_entry",
frm: cur_frm,
});
frm: cur_frm
})
},
});
$.extend(erpnext.journal_entry, {
set_account_details: function (frm, dt, dn) {
set_account_balance: function(frm, dt, dn) {
var d = locals[dt][dn];
if (d.account) {
if (!frm.doc.company) frappe.throw(__("Please select Company first"));
if (!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
if(d.account) {
if(!frm.doc.company) frappe.throw(__("Please select Company first"));
if(!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_details_and_party_type",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_balance_and_party_type",
args: {
account: d.account,
date: frm.doc.posting_date,
@@ -669,14 +605,15 @@ $.extend(erpnext.journal_entry, {
debit: flt(d.debit_in_account_currency),
credit: flt(d.credit_in_account_currency),
exchange_rate: d.exchange_rate,
cost_center: d.cost_center
},
callback: function (r) {
if (r.message) {
callback: function(r) {
if(r.message) {
$.extend(d, r.message);
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, dt, dn);
refresh_field("accounts");
refresh_field('accounts');
}
},
}
});
}
},

View File

@@ -548,16 +548,8 @@
"icon": "fa fa-file-text",
"idx": 176,
"is_submittable": 1,
"links": [
{
"is_child_table": 1,
"link_doctype": "Bank Transaction Payments",
"link_fieldname": "payment_entry",
"parent_doctype": "Bank Transaction",
"table_fieldname": "payment_entries"
}
],
"modified": "2023-11-23 12:11:04.128015",
"links": [],
"modified": "2023-08-10 14:32:22.366895",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry",

View File

@@ -68,6 +68,7 @@ class JournalEntry(AccountsController):
self.set_print_format_fields()
self.validate_credit_debit_note()
self.validate_empty_accounts_table()
self.set_account_and_party_balance()
self.validate_inter_company_accounts()
self.validate_depr_entry_voucher_type()
@@ -77,20 +78,6 @@ class JournalEntry(AccountsController):
if not self.title:
self.title = self.get_title()
def submit(self):
if len(self.accounts) > 100:
msgprint(_("The task has been enqueued as a background job."), alert=True)
self.queue_action("submit", timeout=4600)
else:
return self._submit()
def cancel(self):
if len(self.accounts) > 100:
msgprint(_("The task has been enqueued as a background job."), alert=True)
self.queue_action("cancel", timeout=4600)
else:
return self._cancel()
def on_submit(self):
self.validate_cheque_info()
self.check_credit_limit()
@@ -111,8 +98,6 @@ class JournalEntry(AccountsController):
"Repost Payment Ledger Items",
"Repost Accounting Ledger",
"Repost Accounting Ledger Items",
"Unreconcile Payment",
"Unreconcile Payment Entries",
)
self.make_gl_entries(1)
self.update_advance_paid()
@@ -474,28 +459,17 @@ class JournalEntry(AccountsController):
elif d.party_type == "Supplier" and flt(d.credit) > 0:
frappe.throw(_("Row {0}: Advance against Supplier must be debit").format(d.idx))
def system_generated_gain_loss(self):
return (
self.voucher_type == "Exchange Gain Or Loss"
and self.multi_currency
and self.is_system_generated
)
def validate_against_jv(self):
for d in self.get("accounts"):
if d.reference_type == "Journal Entry":
account_root_type = frappe.get_cached_value("Account", d.account, "root_type")
if account_root_type == "Asset" and flt(d.debit) > 0 and not self.system_generated_gain_loss():
account_root_type = frappe.db.get_value("Account", d.account, "root_type")
if account_root_type == "Asset" and flt(d.debit) > 0:
frappe.throw(
_(
"Row #{0}: For {1}, you can select reference document only if account gets credited"
).format(d.idx, d.account)
)
elif (
account_root_type == "Liability"
and flt(d.credit) > 0
and not self.system_generated_gain_loss()
):
elif account_root_type == "Liability" and flt(d.credit) > 0:
frappe.throw(
_(
"Row #{0}: For {1}, you can select reference document only if account gets debited"
@@ -522,12 +496,12 @@ class JournalEntry(AccountsController):
).format(d.reference_name, d.account)
)
else:
dr_or_cr = "debit" if flt(d.credit) > 0 else "credit"
dr_or_cr = "debit" if d.credit > 0 else "credit"
valid = False
for jvd in against_entries:
if flt(jvd[dr_or_cr]) > 0:
valid = True
if not valid and not self.system_generated_gain_loss():
if not valid:
frappe.throw(
_("Against Journal Entry {0} does not have any unmatched {1} entry").format(
d.reference_name, dr_or_cr
@@ -1075,6 +1049,21 @@ class JournalEntry(AccountsController):
if not self.get("accounts"):
frappe.throw(_("Accounts table cannot be blank."))
def set_account_and_party_balance(self):
account_balance = {}
party_balance = {}
for d in self.get("accounts"):
if d.account not in account_balance:
account_balance[d.account] = get_balance_on(account=d.account, date=self.posting_date)
if (d.party_type, d.party) not in party_balance:
party_balance[(d.party_type, d.party)] = get_balance_on(
party_type=d.party_type, party=d.party, date=self.posting_date, company=self.company
)
d.account_balance = account_balance[d.account]
d.party_balance = party_balance[(d.party_type, d.party)]
@frappe.whitelist()
def get_default_bank_cash_account(company, account_type=None, mode_of_payment=None, account=None):
@@ -1240,6 +1229,8 @@ def get_payment_entry(ref_doc, args):
"account_type": frappe.db.get_value("Account", args.get("party_account"), "account_type"),
"account_currency": args.get("party_account_currency")
or get_account_currency(args.get("party_account")),
"balance": get_balance_on(args.get("party_account")),
"party_balance": get_balance_on(party=args.get("party"), party_type=args.get("party_type")),
"exchange_rate": exchange_rate,
args.get("amount_field_party"): args.get("amount"),
"is_advance": args.get("is_advance"),
@@ -1387,23 +1378,30 @@ def get_outstanding(args):
@frappe.whitelist()
def get_party_account_and_currency(company, party_type, party):
def get_party_account_and_balance(company, party_type, party, cost_center=None):
if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1)
account = get_party_account(party_type, party, company)
account_balance = get_balance_on(account=account, cost_center=cost_center)
party_balance = get_balance_on(
party_type=party_type, party=party, company=company, cost_center=cost_center
)
return {
"account": account,
"account_currency": frappe.get_cached_value("Account", account, "account_currency"),
"balance": account_balance,
"party_balance": party_balance,
"account_currency": frappe.db.get_value("Account", account, "account_currency"),
}
@frappe.whitelist()
def get_account_details_and_party_type(
account, date, company, debit=None, credit=None, exchange_rate=None
def get_account_balance_and_party_type(
account, date, company, debit=None, credit=None, exchange_rate=None, cost_center=None
):
"""Returns dict of account details and party type to be set in Journal Entry on selection of account."""
"""Returns dict of account balance and party type to be set in Journal Entry on selection of account."""
if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1)
@@ -1423,6 +1421,7 @@ def get_account_details_and_party_type(
party_type = ""
grid_values = {
"balance": get_balance_on(account, date, cost_center=cost_center),
"party_type": party_type,
"account_type": account_details.account_type,
"account_currency": account_details.account_currency or company_currency,

View File

@@ -1,12 +1,12 @@
frappe.listview_settings["Journal Entry"] = {
frappe.listview_settings['Journal Entry'] = {
add_fields: ["voucher_type", "posting_date", "total_debit", "company", "user_remark"],
get_indicator: function (doc) {
if (doc.docstatus == 0) {
return [__("Draft", "red", "docstatus,=,0")];
} else if (doc.docstatus == 2) {
return [__("Cancelled", "grey", "docstatus,=,2")];
get_indicator: function(doc) {
if(doc.docstatus==0) {
return [__("Draft", "red", "docstatus,=,0")]
} else if(doc.docstatus==2) {
return [__("Cancelled", "grey", "docstatus,=,2")]
} else {
return [__(doc.voucher_type), "blue", "voucher_type,=," + doc.voucher_type];
return [__(doc.voucher_type), "blue", "voucher_type,=," + doc.voucher_type]
}
},
}
};

View File

@@ -81,6 +81,7 @@
},
{
"account": "Sales - _TC",
"cost_center": "_Test Cost Center - _TC",
"credit_in_account_currency": 400.0,
"debit_in_account_currency": 0.0,
"doctype": "Journal Entry Account",

View File

@@ -9,10 +9,12 @@
"field_order": [
"account",
"account_type",
"balance",
"col_break1",
"bank_account",
"party_type",
"party",
"party_balance",
"accounting_dimensions_section",
"cost_center",
"dimension_col_break",
@@ -61,6 +63,17 @@
"label": "Account Type",
"print_hide": 1
},
{
"fieldname": "balance",
"fieldtype": "Currency",
"label": "Account Balance",
"no_copy": 1,
"oldfieldname": "balance",
"oldfieldtype": "Data",
"options": "account_currency",
"print_hide": 1,
"read_only": 1
},
{
"default": ":Company",
"description": "If Income or Expense",
@@ -94,6 +107,14 @@
"label": "Party",
"options": "party_type"
},
{
"fieldname": "party_balance",
"fieldtype": "Currency",
"label": "Party Balance",
"options": "account_currency",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "currency_section",
"fieldtype": "Section Break",
@@ -182,8 +203,7 @@
"fieldtype": "Select",
"label": "Reference Type",
"no_copy": 1,
"options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset\nLoan\nPayroll Entry\nEmployee Advance\nExchange Rate Revaluation\nInvoice Discounting\nFees\nFull and Final Statement\nPayment Entry",
"search_index": 1
"options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset\nLoan\nPayroll Entry\nEmployee Advance\nExchange Rate Revaluation\nInvoice Discounting\nFees\nFull and Final Statement\nPayment Entry"
},
{
"fieldname": "reference_name",
@@ -191,8 +211,7 @@
"in_list_view": 1,
"label": "Reference Name",
"no_copy": 1,
"options": "reference_type",
"search_index": 1
"options": "reference_type"
},
{
"depends_on": "eval:doc.reference_type&&!in_list(doc.reference_type, ['Expense Claim', 'Asset', 'Employee Loan', 'Employee Advance'])",
@@ -259,14 +278,13 @@
"fieldtype": "Data",
"hidden": 1,
"label": "Reference Detail No",
"no_copy": 1,
"search_index": 1
"no_copy": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2023-11-23 11:44:25.841187",
"modified": "2023-06-16 14:11:13.507807",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry Account",

View File

@@ -2,82 +2,78 @@
// For license information, please see license.txt
frappe.ui.form.on("Journal Entry Template", {
onload: function (frm) {
if (frm.is_new()) {
onload: function(frm) {
if(frm.is_new()) {
frappe.call({
type: "GET",
method: "erpnext.accounts.doctype.journal_entry_template.journal_entry_template.get_naming_series",
callback: function (r) {
if (r.message) {
callback: function(r){
if(r.message) {
frm.set_df_property("naming_series", "options", r.message.split("\n"));
frm.set_value("naming_series", r.message.split("\n")[0]);
frm.refresh_field("naming_series");
}
},
}
});
}
},
refresh: function (frm) {
refresh: function(frm) {
frappe.model.set_default_values(frm.doc);
frm.set_query("account", "accounts", function () {
frm.set_query("account" ,"accounts", function(){
var filters = {
company: frm.doc.company,
is_group: 0,
is_group: 0
};
if (!frm.doc.multi_currency) {
if(!frm.doc.multi_currency) {
$.extend(filters, {
account_currency: frappe.get_doc(":Company", frm.doc.company).default_currency,
account_currency: frappe.get_doc(":Company", frm.doc.company).default_currency
});
}
return { filters: filters };
});
},
voucher_type: function (frm) {
var add_accounts = function (doc, r) {
$.each(r, function (i, d) {
voucher_type: function(frm) {
var add_accounts = function(doc, r) {
$.each(r, function(i, d) {
var row = frappe.model.add_child(doc, "Journal Entry Template Account", "accounts");
row.account = d.account;
});
refresh_field("accounts");
};
if (!frm.doc.company) return;
if(!frm.doc.company) return;
frm.trigger("clear_child");
switch (frm.doc.voucher_type) {
switch(frm.doc.voucher_type){
case "Bank Entry":
case "Cash Entry":
frappe.call({
type: "GET",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
args: {
account_type:
frm.doc.voucher_type == "Bank Entry"
? "Bank"
: frm.doc.voucher_type == "Cash Entry"
? "Cash"
: null,
company: frm.doc.company,
"account_type": (frm.doc.voucher_type=="Bank Entry" ?
"Bank" : (frm.doc.voucher_type=="Cash Entry" ? "Cash" : null)),
"company": frm.doc.company
},
callback: function (r) {
if (r.message) {
callback: function(r) {
if(r.message) {
// If default company bank account not set
if (!$.isEmptyObject(r.message)) {
if(!$.isEmptyObject(r.message)){
add_accounts(frm.doc, [r.message]);
}
}
},
}
});
break;
default:
frm.trigger("clear_child");
}
},
clear_child: function (frm) {
clear_child: function(frm){
frappe.model.clear_table(frm.doc, "accounts");
frm.refresh_field("accounts");
},
}
});

View File

@@ -1,9 +1,9 @@
// Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Ledger Merge", {
setup: function (frm) {
frappe.realtime.on("ledger_merge_refresh", ({ ledger_merge }) => {
frappe.ui.form.on('Ledger Merge', {
setup: function(frm) {
frappe.realtime.on('ledger_merge_refresh', ({ ledger_merge }) => {
if (ledger_merge !== frm.doc.name) return;
frappe.model.clear_doc(frm.doc.doctype, frm.doc.name);
frappe.model.with_doc(frm.doc.doctype, frm.doc.name).then(() => {
@@ -11,29 +11,29 @@ frappe.ui.form.on("Ledger Merge", {
});
});
frappe.realtime.on("ledger_merge_progress", (data) => {
frappe.realtime.on('ledger_merge_progress', data => {
if (data.ledger_merge !== frm.doc.name) return;
let message = __("Merging {0} of {1}", [data.current, data.total]);
let message = __('Merging {0} of {1}', [data.current, data.total]);
let percent = Math.floor((data.current * 100) / data.total);
frm.dashboard.show_progress(__("Merge Progress"), percent, message);
frm.page.set_indicator(__("In Progress"), "orange");
frm.dashboard.show_progress(__('Merge Progress'), percent, message);
frm.page.set_indicator(__('In Progress'), 'orange');
});
frm.set_query("account", function (doc) {
if (!doc.company) frappe.throw(__("Please set Company"));
if (!doc.root_type) frappe.throw(__("Please set Root Type"));
frm.set_query("account", function(doc) {
if (!doc.company) frappe.throw(__('Please set Company'));
if (!doc.root_type) frappe.throw(__('Please set Root Type'));
return {
filters: {
root_type: doc.root_type,
company: doc.company,
},
company: doc.company
}
};
});
frm.set_query("account", "merge_accounts", function (doc) {
if (!doc.company) frappe.throw(__("Please set Company"));
if (!doc.root_type) frappe.throw(__("Please set Root Type"));
if (!doc.account) frappe.throw(__("Please set Account"));
frm.set_query('account', 'merge_accounts', function(doc) {
if (!doc.company) frappe.throw(__('Please set Company'));
if (!doc.root_type) frappe.throw(__('Please set Root Type'));
if (!doc.account) frappe.throw(__('Please set Account'));
let acc = [doc.account];
frm.doc.merge_accounts.forEach((row) => {
acc.push(row.account);
@@ -43,86 +43,86 @@ frappe.ui.form.on("Ledger Merge", {
is_group: doc.is_group,
root_type: doc.root_type,
name: ["not in", acc],
company: doc.company,
},
company: doc.company
}
};
});
},
refresh: function (frm) {
refresh: function(frm) {
frm.page.hide_icon_group();
frm.trigger("set_merge_status");
frm.trigger("update_primary_action");
frm.trigger('set_merge_status');
frm.trigger('update_primary_action');
},
after_save: function (frm) {
after_save: function(frm) {
setTimeout(() => {
frm.trigger("update_primary_action");
frm.trigger('update_primary_action');
}, 500);
},
update_primary_action: function (frm) {
update_primary_action: function(frm) {
if (frm.is_dirty()) {
frm.enable_save();
return;
}
frm.disable_save();
if (frm.doc.status !== "Success") {
if (frm.doc.status !== 'Success') {
if (!frm.is_new()) {
let label = frm.doc.status === "Pending" ? __("Start Merge") : __("Retry");
let label = frm.doc.status === 'Pending' ? __('Start Merge') : __('Retry');
frm.page.set_primary_action(label, () => frm.events.start_merge(frm));
} else {
frm.page.set_primary_action(__("Save"), () => frm.save());
frm.page.set_primary_action(__('Save'), () => frm.save());
}
}
},
start_merge: function (frm) {
start_merge: function(frm) {
frm.call({
method: "form_start_merge",
method: 'form_start_merge',
args: { docname: frm.doc.name },
btn: frm.page.btn_primary,
}).then((r) => {
btn: frm.page.btn_primary
}).then(r => {
if (r.message === true) {
frm.disable_save();
}
});
},
set_merge_status: function (frm) {
set_merge_status: function(frm) {
if (frm.doc.status == "Pending") return;
let successful_records = 0;
frm.doc.merge_accounts.forEach((row) => {
if (row.merged) successful_records += 1;
});
let message_args = [successful_records, frm.doc.merge_accounts.length];
frm.dashboard.set_headline(__("Successfully merged {0} out of {1}.", message_args));
frm.dashboard.set_headline(__('Successfully merged {0} out of {1}.', message_args));
},
root_type: function (frm) {
frm.set_value("account", "");
frm.set_value("merge_accounts", []);
root_type: function(frm) {
frm.set_value('account', '');
frm.set_value('merge_accounts', []);
},
company: function (frm) {
frm.set_value("account", "");
frm.set_value("merge_accounts", []);
},
company: function(frm) {
frm.set_value('account', '');
frm.set_value('merge_accounts', []);
}
});
frappe.ui.form.on("Ledger Merge Accounts", {
merge_accounts_add: function (frm) {
frm.trigger("update_primary_action");
frappe.ui.form.on('Ledger Merge Accounts', {
merge_accounts_add: function(frm) {
frm.trigger('update_primary_action');
},
merge_accounts_remove: function (frm) {
frm.trigger("update_primary_action");
merge_accounts_remove: function(frm) {
frm.trigger('update_primary_action');
},
account: function (frm, cdt, cdn) {
account: function(frm, cdt, cdn) {
let row = frappe.get_doc(cdt, cdn);
row.account_name = row.account;
frm.refresh_field("merge_accounts");
frm.trigger("update_primary_action");
},
frm.refresh_field('merge_accounts');
frm.trigger('update_primary_action');
}
});

View File

@@ -1,6 +1,8 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Loyalty Point Entry", {
refresh: function (frm) {},
frappe.ui.form.on('Loyalty Point Entry', {
refresh: function(frm) {
}
});

View File

@@ -3,37 +3,30 @@
frappe.provide("erpnext.accounts.dimensions");
frappe.ui.form.on("Loyalty Program", {
setup: function (frm) {
var help_content = `<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
frappe.ui.form.on('Loyalty Program', {
setup: function(frm) {
var help_content =
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
<tr><td>
<h4>
<i class="fa fa-hand-right"></i>
${__("Notes")}
${__('Notes')}
</h4>
<ul>
<li>
${__(
"Loyalty Points will be calculated from the spent done (via the Sales Invoice), based on collection factor mentioned."
)}
${__("Loyalty Points will be calculated from the spent done (via the Sales Invoice), based on collection factor mentioned.")}
</li>
<li>
${__(
"There can be multiple tiered collection factor based on the total spent. But the conversion factor for redemption will always be same for all the tier."
)}
${__("There can be multiple tiered collection factor based on the total spent. But the conversion factor for redemption will always be same for all the tier.")}
</li>
<li>
${__(
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent"
)}
${__("In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent")}
</li>
<li>
${__("If unlimited expiry for the Loyalty Points, keep the Expiry Duration empty or 0.")}
</li>
<li>
${__(
"If Auto Opt In is checked, then the customers will be automatically linked with the concerned Loyalty Program (on save)"
)}
${__("If Auto Opt In is checked, then the customers will be automatically linked with the concerned Loyalty Program (on save)")}
</li>
<li>
${__("One customer can be part of only single Loyalty Program.")}
@@ -44,14 +37,14 @@ frappe.ui.form.on("Loyalty Program", {
set_field_options("loyalty_program_help", help_content);
},
onload: function (frm) {
frm.set_query("expense_account", function (doc) {
onload: function(frm) {
frm.set_query("expense_account", function(doc) {
return {
filters: {
root_type: "Expense",
is_group: 0,
company: doc.company,
},
"root_type": "Expense",
'is_group': 0,
'company': doc.company
}
};
});
@@ -59,15 +52,13 @@ frappe.ui.form.on("Loyalty Program", {
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
},
refresh: function (frm) {
refresh: function(frm) {
if (frm.doc.loyalty_program_type === "Single Tier Program" && frm.doc.collection_rules.length > 1) {
frappe.throw(
__("Please select the Multiple Tier Program type for more than one collection rules.")
);
frappe.throw(__("Please select the Multiple Tier Program type for more than one collection rules."));
}
},
company: function (frm) {
company: function(frm) {
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
},
}
});

View File

@@ -1,16 +1,16 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on("Mode of Payment", {
setup: function (frm) {
frm.set_query("default_account", "accounts", function (doc, cdt, cdn) {
frappe.ui.form.on('Mode of Payment', {
setup: function(frm) {
frm.set_query("default_account", "accounts", function(doc, cdt, cdn) {
let d = locals[cdt][cdn];
return {
filters: [
["Account", "account_type", "in", "Bank, Cash, Receivable"],
["Account", "is_group", "=", 0],
["Account", "company", "=", d.company],
],
['Account', 'account_type', 'in', 'Bank, Cash, Receivable'],
['Account', 'is_group', '=', 0],
['Account', 'company', '=', d.company]
]
};
});
},

View File

@@ -1,16 +1,16 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on("Monthly Distribution", {
frappe.ui.form.on('Monthly Distribution', {
onload(frm) {
if (frm.doc.__islocal) {
return frm.call("get_months").then(() => {
frm.refresh_field("percentages");
if(frm.doc.__islocal) {
return frm.call('get_months').then(() => {
frm.refresh_field('percentages');
});
}
},
refresh(frm) {
frm.toggle_display("distribution_id", frm.doc.__islocal);
},
frm.toggle_display('distribution_id', frm.doc.__islocal);
}
});

View File

@@ -1,52 +1,48 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Opening Invoice Creation Tool", {
setup: function (frm) {
frm.set_query("party_type", "invoices", function (doc, cdt, cdn) {
frappe.ui.form.on('Opening Invoice Creation Tool', {
setup: function(frm) {
frm.set_query('party_type', 'invoices', function(doc, cdt, cdn) {
return {
filters: {
name: ["in", "Customer, Supplier"],
},
'name': ['in', 'Customer, Supplier']
}
};
});
if (frm.doc.company) {
frm.trigger("setup_company_filters");
frm.trigger('setup_company_filters');
}
frappe.realtime.on("opening_invoice_creation_progress", (data) => {
frappe.realtime.on('opening_invoice_creation_progress', data => {
if (!frm.doc.import_in_progress) {
frm.dashboard.reset();
frm.doc.import_in_progress = true;
}
if (data.count == data.total) {
setTimeout(
() => {
frm.doc.import_in_progress = false;
frm.clear_table("invoices");
frm.refresh_fields();
frm.page.clear_indicator();
frm.dashboard.hide_progress();
frappe.msgprint(__("Opening {0} Invoices created", [frm.doc.invoice_type]));
},
1500,
data.title
);
setTimeout(() => {
frm.doc.import_in_progress = false;
frm.clear_table("invoices");
frm.refresh_fields();
frm.page.clear_indicator();
frm.dashboard.hide_progress();
frappe.msgprint(__("Opening {0} Invoices created", [frm.doc.invoice_type]));
}, 1500, data.title);
return;
}
frm.dashboard.show_progress(data.title, (data.count / data.total) * 100, data.message);
frm.page.set_indicator(__("In Progress"), "orange");
frm.page.set_indicator(__('In Progress'), 'orange');
});
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
},
refresh: function (frm) {
refresh: function(frm) {
frm.disable_save();
!frm.doc.import_in_progress && frm.trigger("make_dashboard");
frm.page.set_primary_action(__("Create Invoices"), () => {
frm.page.set_primary_action(__('Create Invoices'), () => {
let btn_primary = frm.page.btn_primary.get(0);
return frm.call({
doc: frm.doc,
@@ -62,98 +58,100 @@ frappe.ui.form.on("Opening Invoice Creation Tool", {
}
},
setup_company_filters: function (frm) {
frm.set_query("cost_center", "invoices", function (doc, cdt, cdn) {
setup_company_filters: function(frm) {
frm.set_query('cost_center', 'invoices', function(doc, cdt, cdn) {
return {
filters: {
company: doc.company,
},
'company': doc.company
}
};
});
frm.set_query("cost_center", function (doc) {
frm.set_query('cost_center', function(doc) {
return {
filters: {
company: doc.company,
},
'company': doc.company
}
};
});
frm.set_query("temporary_opening_account", "invoices", function (doc, cdt, cdn) {
frm.set_query('temporary_opening_account', 'invoices', function(doc, cdt, cdn) {
return {
filters: {
company: doc.company,
},
};
'company': doc.company
}
}
});
},
company: function (frm) {
company: function(frm) {
if (frm.doc.company) {
frm.trigger("setup_company_filters");
frm.trigger('setup_company_filters');
frappe.call({
method: "erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool.get_temporary_opening_account",
method: 'erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool.get_temporary_opening_account',
args: {
company: frm.doc.company,
company: frm.doc.company
},
callback: (r) => {
if (r.message) {
frm.doc.__onload.temporary_opening_account = r.message;
frm.trigger("update_invoice_table");
frm.trigger('update_invoice_table');
}
},
});
}
})
}
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
},
invoice_type: function (frm) {
invoice_type: function(frm) {
$.each(frm.doc.invoices, (idx, row) => {
row.party_type = frm.doc.invoice_type == "Sales" ? "Customer" : "Supplier";
row.party_type = frm.doc.invoice_type == "Sales"? "Customer": "Supplier";
row.party = "";
});
frm.refresh_fields();
},
make_dashboard: function (frm) {
make_dashboard: function(frm) {
let max_count = frm.doc.__onload.max_count;
let opening_invoices_summary = frm.doc.__onload.opening_invoices_summary;
if (!$.isEmptyObject(opening_invoices_summary)) {
if(!$.isEmptyObject(opening_invoices_summary)) {
let section = frm.dashboard.add_section(
frappe.render_template("opening_invoice_creation_tool_dashboard", {
frappe.render_template('opening_invoice_creation_tool_dashboard', {
data: opening_invoices_summary,
max_count: max_count,
max_count: max_count
}),
__("Opening Invoices Summary")
);
section.on("click", ".invoice-link", function () {
let doctype = $(this).attr("data-type");
let company = $(this).attr("data-company");
frappe.set_route("List", doctype, { is_opening: "Yes", company: company, docstatus: 1 });
section.on('click', '.invoice-link', function() {
let doctype = $(this).attr('data-type');
let company = $(this).attr('data-company');
frappe.set_route('List', doctype,
{'is_opening': 'Yes', 'company': company, 'docstatus': 1});
});
frm.dashboard.show();
}
},
update_invoice_table: function (frm) {
update_invoice_table: function(frm) {
$.each(frm.doc.invoices, (idx, row) => {
if (!row.temporary_opening_account) {
row.temporary_opening_account = frm.doc.__onload.temporary_opening_account;
}
if (!row.cost_center) {
if(!row.cost_center) {
row.cost_center = frm.doc.cost_center;
}
row.party_type = frm.doc.invoice_type == "Sales" ? "Customer" : "Supplier";
row.party_type = frm.doc.invoice_type == "Sales"? "Customer": "Supplier";
});
},
}
});
frappe.ui.form.on("Opening Invoice Creation Tool Item", {
frappe.ui.form.on('Opening Invoice Creation Tool Item', {
invoices_add: (frm) => {
frm.trigger("update_invoice_table");
},
frm.trigger('update_invoice_table');
}
});

View File

@@ -1,34 +1,33 @@
// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Party Link", {
refresh: function (frm) {
frm.set_query("primary_role", () => {
frappe.ui.form.on('Party Link', {
refresh: function(frm) {
frm.set_query('primary_role', () => {
return {
filters: {
name: ["in", ["Customer", "Supplier"]],
},
name: ['in', ['Customer', 'Supplier']]
}
};
});
frm.set_query("secondary_role", () => {
let party_types = Object.keys(frappe.boot.party_account_types).filter(
(p) => p != frm.doc.primary_role
);
frm.set_query('secondary_role', () => {
let party_types = Object.keys(frappe.boot.party_account_types)
.filter(p => p != frm.doc.primary_role);
return {
filters: {
name: ["in", party_types],
},
name: ['in', party_types]
}
};
});
},
primary_role(frm) {
frm.set_value("primary_party", "");
frm.set_value("secondary_role", "");
frm.set_value('primary_party', '');
frm.set_value('secondary_role', '');
},
secondary_role(frm) {
frm.set_value("secondary_party", "");
},
frm.set_value('secondary_party', '');
}
});

View File

@@ -7,7 +7,7 @@ cur_frm.cscript.tax_table = "Advance Taxes and Charges";
frappe.ui.form.on('Payment Entry', {
onload: function(frm) {
frm.ignore_doctypes_on_cancel_all = ['Sales Invoice', 'Purchase Invoice', 'Journal Entry', 'Repost Payment Ledger', 'Repost Accounting Ledger', 'Unreconcile Payment', 'Unreconcile Payment Entries', 'Bank Transaction'];
frm.ignore_doctypes_on_cancel_all = ['Sales Invoice', 'Purchase Invoice', 'Journal Entry', 'Repost Payment Ledger','Repost Accounting Ledger'];
if(frm.doc.__islocal) {
if (!frm.doc.paid_from) frm.set_value("paid_from_account_currency", null);
@@ -152,13 +152,6 @@ frappe.ui.form.on('Payment Entry', {
frm.events.hide_unhide_fields(frm);
frm.events.set_dynamic_labels(frm);
frm.events.show_general_ledger(frm);
if((frm.doc.references) && (frm.doc.references.find((elem) => {return elem.exchange_gain_loss != 0}))) {
frm.add_custom_button(__("View Exchange Gain/Loss Journals"), function() {
frappe.set_route("List", "Journal Entry", {"voucher_type": "Exchange Gain Or Loss", "reference_name": frm.doc.name});
}, __('Actions'));
}
erpnext.accounts.unreconcile_payment.add_unreconcile_btn(frm);
},
validate_company: (frm) => {
@@ -631,7 +624,7 @@ frappe.ui.form.on('Payment Entry', {
get_outstanding_invoices_or_orders: function(frm, get_outstanding_invoices, get_orders_to_be_billed) {
const today = frappe.datetime.get_today();
let fields = [
const fields = [
{fieldtype:"Section Break", label: __("Posting Date")},
{fieldtype:"Date", label: __("From Date"),
fieldname:"from_posting_date", default:frappe.datetime.add_days(today, -30)},
@@ -646,29 +639,18 @@ frappe.ui.form.on('Payment Entry', {
fieldname:"outstanding_amt_greater_than", default: 0},
{fieldtype:"Column Break"},
{fieldtype:"Float", label: __("Less Than Amount"), fieldname:"outstanding_amt_less_than"},
];
if (frm.dimension_filters) {
let column_break_insertion_point = Math.ceil((frm.dimension_filters.length)/2);
fields.push({fieldtype:"Section Break"});
frm.dimension_filters.map((elem, idx)=>{
fields.push({
fieldtype: "Link",
label: elem.document_type == "Cost Center" ? "Cost Center" : elem.label,
options: elem.document_type,
fieldname: elem.fieldname || elem.document_type
});
if(idx+1 == column_break_insertion_point) {
fields.push({fieldtype:"Column Break"});
{fieldtype:"Section Break"},
{fieldtype:"Link", label:__("Cost Center"), fieldname:"cost_center", options:"Cost Center",
"get_query": function() {
return {
"filters": {"company": frm.doc.company}
}
}
});
}
fields = fields.concat([
},
{fieldtype:"Column Break"},
{fieldtype:"Section Break"},
{fieldtype:"Check", label: __("Allocate Payment Amount"), fieldname:"allocate_payment_amount", default:1},
]);
];
let btn_text = "";
@@ -840,6 +822,7 @@ frappe.ui.form.on('Payment Entry', {
else
total_negative_outstanding += Math.abs(flt(row.outstanding_amount));
})
var allocated_negative_outstanding = 0;
if (
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
@@ -854,7 +837,6 @@ frappe.ui.form.on('Payment Entry', {
var allocated_positive_outstanding = paid_amount + allocated_negative_outstanding;
} else if (in_list(["Customer", "Supplier"], frm.doc.party_type)) {
total_negative_outstanding = flt(total_negative_outstanding, precision("outstanding_amount"))
if(paid_amount > total_negative_outstanding) {
if(total_negative_outstanding == 0) {
frappe.msgprint(
@@ -930,7 +912,7 @@ frappe.ui.form.on('Payment Entry', {
if(frm.doc.payment_type == "Receive"
&& frm.doc.base_total_allocated_amount < frm.doc.base_received_amount + total_deductions
&& frm.doc.total_allocated_amount < frm.doc.paid_amount + (total_deductions / frm.doc.source_exchange_rate)) {
unallocated_amount = (frm.doc.base_received_amount + total_deductions - flt(frm.doc.base_total_taxes_and_charges)
unallocated_amount = (frm.doc.base_received_amount + total_deductions + flt(frm.doc.base_total_taxes_and_charges)
- frm.doc.base_total_allocated_amount) / frm.doc.source_exchange_rate;
} else if (frm.doc.payment_type == "Pay"
&& frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount - total_deductions

Some files were not shown because too many files have changed in this diff Show More