Compare commits

...

39 Commits

Author SHA1 Message Date
Ankush Menat
b189fc46b0 fix: submit JVs synchronously if in background job 2024-03-11 13:17:00 +05:30
Deepesh Garg
58e1548640 Merge pull request #40248 from ernestoruiz89/patch-5
chore: Add translate function to text "after"
2024-03-10 22:33:28 +05:30
Deepesh Garg
b660d98f20 Merge pull request #40349 from pps190/fix-rename-tax-rule
fix: allow tax rule to be renamed
2024-03-10 21:14:38 +05:30
Deepesh Garg
dee49e6078 Merge pull request #40344 from pps190/fix-get-default-company
fix: get_user_default_as_list args order
2024-03-10 21:14:08 +05:30
Ankush Menat
f4d69f16c0 Merge pull request #40206 from barredterra/bulk-format-js
ci: add prettier to pre-commit
2024-03-10 20:01:49 +05:30
Deepesh Garg
c5b94df188 Merge pull request #40195 from Nihantra-Patel/fix_timesheet_invoice
fix: skip timesheet on return time
2024-03-10 19:59:03 +05:30
Ankush Menat
0b100782e2 chore: update blame ignore 2024-03-10 19:46:53 +05:30
Ankush Menat
ec74a5e566 style: format js files 2024-03-10 19:45:40 +05:30
barredterra
2c16036ef3 ci: add prettier to pre-commit 2024-03-10 19:45:18 +05:30
Deepesh Garg
1f4c86136f Merge pull request #39886 from barredterra/refactor-sales-invoice-item
refactor(Sales Invoice): move methods into child row controller
2024-03-10 19:44:16 +05:30
Deepesh Garg
b0fcb014c1 Merge pull request #40294 from barredterra/fix-bisect-accounting-statements
fix: define dates before usage
2024-03-10 19:30:29 +05:30
Deepesh Garg
65c8605b88 Merge pull request #40325 from deepeshgarg007/psoa_sender_email
fix: Sender email in process statements of accounts
2024-03-10 19:26:05 +05:30
Deepesh Garg
4c6d28a299 Merge pull request #40323 from deepeshgarg007/project_sales_filter
fix: Filter for projects in Sales Cycle
2024-03-10 19:25:48 +05:30
Deepesh Garg
962b51d6d5 Merge pull request #40355 from deepeshgarg007/blanket_order_rate
fix: Blanket order rate getting changed on converting to order
2024-03-10 18:44:11 +05:30
Deepesh Garg
9702a65a0f fix: Blanket order rate getting changed on converting to order 2024-03-10 17:39:20 +05:30
ruthra kumar
d69c593f93 Merge pull request #39681 from ruthra-kumar/fix_gl_logic_in_advance_as_liability
fix: incorrect advance paid in Sales/Purchase Order
2024-03-10 16:38:43 +05:30
Devin Slauenwhite
0d6afda6b8 fix: allow tax rule to be renamed 2024-03-09 08:09:16 -05:00
Devin Slauenwhite
ac1961b687 fix: get_user_default_as_list args order 2024-03-08 18:09:11 -05:00
Deepesh Garg
65a2f3d12c fix: Sender email in process statements of accounts 2024-03-07 10:08:51 +05:30
Deepesh Garg
d0e0b66b2f fix: Filter for projects in Sales Cycle 2024-03-07 09:14:56 +05:30
barredterra
171b8af3ee fix: define dates before usage 2024-03-05 15:56:42 +01:00
ruthra kumar
e52c4c8f22 refactor(test): make sure party has USD account
1. Don't reset 'party_account_currency' of SO/PO  upon Payment Entry
cancellation. This happens when there are no payments against a SO/PO
2024-03-05 14:56:29 +05:30
ruthra kumar
d9a0494fc3 fix: advance paid amount and ledger entries against SO/PO 2024-03-05 14:56:29 +05:30
ruthra kumar
cb2529cec8 refactor(test): use get_party_account for reference details section 2024-03-05 14:56:29 +05:30
ruthra kumar
158112896e refactor(test): reference details will have account 2024-03-05 14:56:29 +05:30
ruthra kumar
9d9b83362a fix: incorrect advance paid in Sales/Purchase Order 2024-03-05 14:56:29 +05:30
Ernesto Ruiz
d0140412cd chore: Add translate function to text "after" 2024-03-02 15:46:43 -06:00
Nihantra Patel
79c492cc4b fix: skip timesheet on return time and revert code 2024-03-01 09:26:49 +05:30
Nihantra C. Patel
a8eb5e5c85 Merge branch 'frappe:develop' into fix_timesheet_invoice 2024-03-01 09:17:34 +05:30
Nihantra Patel
dd70fb5f7e fix: skip timesheet link on return time 2024-02-29 15:31:53 +05:30
barredterra
0bbf45cd8b refactor: make_gle_for_change_amount 2024-02-17 20:46:52 +01:00
barredterra
2ff06af154 refactor: validate_serial_numbers 2024-02-17 20:29:38 +01:00
barredterra
9c0755d3de refactor: set_income_account_for_fixed_assets 2024-02-17 20:08:49 +01:00
barredterra
701671b2bd refactor: validate_dropship_item 2024-02-17 19:50:34 +01:00
barredterra
4d7d7dac01 refactor(Sales Invoice): validate_delivery_note 2024-02-17 19:40:02 +01:00
barredterra
75230ece9a refactor: set actual and projected qty in Packed Item and Sales Invoice Item 2024-02-16 23:50:32 +01:00
barredterra
f99f7fd2cf refactor(Sales Invoice): convert to guard clause 2024-02-16 23:17:41 +01:00
barredterra
cc83af0dd4 refactor: move code for unlinking sales invoice to Timesheet 2024-02-16 23:14:50 +01:00
barredterra
76023f1fdc refactor(Sales Invoice Item): validate cost center 2024-02-14 01:14:42 +01:00
589 changed files with 24694 additions and 21569 deletions

View File

@@ -9,6 +9,13 @@ trim_trailing_whitespace = true
charset = utf-8
# python, js indentation settings
[{*.py,*.js}]
[{*.py,*.js,*.vue,*.css,*.scss,*.html}]
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

@@ -124,6 +124,7 @@
"beforeEach": true,
"onScan": true,
"extend_cscript": true,
"localforage": true
"localforage": true,
"Plaid": true
}
}

View File

@@ -32,3 +32,6 @@ baec607ff5905b1c67531096a9cf50ec7ff00a5d
# bulk refactor with sourcery
eb9ee3f79b94e594fc6dfa4f6514580e125eee8c
# js formatting
ec74a5e56617bbd76ac402451468fd4668af543d

View File

@@ -20,6 +20,23 @@ repos:
- 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/.*
)$
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.44.0
hooks:

View File

@@ -1,25 +1,13 @@
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

@@ -13,7 +13,7 @@ def get_default_company(user=None):
if not user:
user = frappe.session.user
companies = get_user_default_as_list(user, "company")
companies = get_user_default_as_list("company", user)
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

@@ -26,19 +26,14 @@ frappe.ui.form.on("Account", {
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
if (!frm.is_new()) {
if (!frm.doc.parent_account) {
frm.set_read_only();
frm.set_intro(
__("This is a root account and cannot be edited.")
);
frm.set_intro(__("This is a root account and cannot be edited."));
} else {
// credit days and type if customer or supplier
frm.set_intro(null);
@@ -80,27 +75,33 @@ frappe.ui.form.on("Account", {
);
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": erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
"to_date": erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
"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")
);
} 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: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
to_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
company: frm.doc.company,
};
frappe.set_route("query-report", "General Ledger");
},
__("View")
);
frm.add_custom_button(
__("Convert to Group"),
@@ -193,14 +194,8 @@ frappe.ui.form.on("Account", {
if (r.message) {
frappe.set_route("Form", "Account", r.message);
} else {
frm.set_value(
"account_number",
data.account_number
);
frm.set_value(
"account_name",
data.account_name
);
frm.set_value("account_number", data.account_number);
frm.set_value("account_name", data.account_name);
}
d.hide();
}

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,30 +22,36 @@ 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 = [];
@@ -57,151 +63,231 @@ 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: "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:'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();
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");
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": erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
"to_date": erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
"company": frappe.treeview_settings['Account'].treeview.page.fields_dict.company.get_value()
account: node.label,
from_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
to_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
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

@@ -1,74 +1,86 @@
// 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) {
document_type: function (frm) {
frm.set_value("label", frm.doc.document_type);
frm.set_value("fieldname", frappe.model.scrub(frm.doc.document_type));
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.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

@@ -1,10 +1,9 @@
// 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>
@@ -13,77 +12,80 @@ 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");
},
apply_restriction_on_values: function(frm) {
apply_restriction_on_values: function (frm) {
/** If restriction on values is not applied, we should set "allow_or_restrict" to "Restrict" with an empty allowed dimension table.
* Hence it's not "restricted" on any value.
*/
*/
if (!frm.doc.apply_restriction_on_values) {
frm.set_value("allow_or_restrict", "Restrict");
frm.clear_table("dimensions");
frm.refresh_field("dimensions");
}
}
},
});
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

@@ -1,30 +1,33 @@
// 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,8 +1,6 @@
// 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

@@ -1,8 +1,11 @@
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

@@ -1,38 +1,36 @@
// 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);
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);
}
@@ -40,30 +38,32 @@ 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;
}
@@ -90,35 +90,45 @@ 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);
});
}
onScriptLoaded(me) {
me.linkHandler = Plaid.create({ // eslint-disable-line no-undef
me.linkHandler = Plaid.create({
// eslint-disable-line no-undef
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,45 +1,49 @@
// 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

@@ -1,8 +1,6 @@
// 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,8 +1,7 @@
// 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,80 +2,76 @@
// 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() {
return {
filters: {
company: frm.doc.company
}
};
});
frm.set_query("bank_account", function() {
frappe.ui.form.on("Bank Guarantee", {
setup: function (frm) {
frm.set_query("bank", function () {
return {
filters: {
company: frm.doc.company,
bank: frm.doc.bank
}
}
},
};
});
frm.set_query("project", function() {
frm.set_query("bank_account", function () {
return {
filters: {
customer: frm.doc.customer
}
company: frm.doc.company,
bank: frm.doc.bank,
},
};
});
frm.set_query("project", function () {
return {
filters: {
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,34 +41,33 @@ 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,21 +8,22 @@ 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) {
@@ -37,34 +38,27 @@ 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")
);
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.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() {
frm.add_custom_button(__("Auto Reconcile"), function () {
frappe.call({
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.auto_reconcile_vouchers",
args: {
@@ -75,33 +69,22 @@ 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");
},
@@ -120,11 +103,7 @@ 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);
}
});
}
@@ -133,11 +112,10 @@ 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: frappe.datetime.add_days(frm.doc.bank_statement_from_date, -1),
},
callback: (response) => {
frm.set_value("account_opening_balance", response.message);
@@ -149,8 +127,7 @@ 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,
@@ -163,41 +140,30 @@ 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,11 +17,9 @@ frappe.ui.form.on("Bank Statement 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;
@@ -48,20 +46,9 @@ 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
@@ -103,15 +90,12 @@ 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)
);
}
},
@@ -128,13 +112,8 @@ 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());
}
@@ -176,24 +155,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);
@@ -236,8 +215,7 @@ 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",
@@ -250,7 +228,7 @@ frappe.ui.form.on("Bank Statement Import", {
"description",
"reference_number",
"bank_account",
"currency"
"currency",
],
},
});
@@ -321,10 +299,7 @@ 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();
@@ -340,19 +315,10 @@ 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"));
},
},
@@ -386,8 +352,7 @@ 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);
@@ -402,9 +367,7 @@ 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>`;
@@ -423,10 +386,9 @@ 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})`;
}
@@ -465,36 +427,28 @@ 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,36 +1,34 @@
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

@@ -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,16 +33,10 @@ 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", {
@@ -54,10 +48,11 @@ 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

@@ -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

@@ -6,18 +6,18 @@ frappe.ui.form.on("Bisect Accounting Statements", {
frm.trigger("render_heatmap");
},
refresh(frm) {
frm.add_custom_button(__('Bisect Left'), () => {
frm.add_custom_button(__("Bisect Left"), () => {
frm.trigger("bisect_left");
});
frm.add_custom_button(__('Bisect Right'), () => {
frm.add_custom_button(__("Bisect Right"), () => {
frm.trigger("bisect_right");
});
frm.add_custom_button(__('Up'), () => {
frm.add_custom_button(__("Up"), () => {
frm.trigger("move_up");
});
frm.add_custom_button(__('Build Tree'), () => {
frm.add_custom_button(__("Build Tree"), () => {
frm.trigger("build_tree");
});
},
@@ -26,16 +26,16 @@ frappe.ui.form.on("Bisect Accounting Statements", {
bisect_heatmap.addClass("bisect_heatmap_location");
// milliseconds in a day
let msiad=24*60*60*1000;
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 )) {
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;
@@ -49,19 +49,19 @@ frappe.ui.form.on("Bisect Accounting Statements", {
start: new Date(frm.doc.from_date),
end: new Date(frm.doc.to_date),
},
countLabel: 'Bisecting',
countLabel: "Bisecting",
discreteDomains: 1,
});
},
bisect_left(frm) {
frm.call({
doc: frm.doc,
method: 'bisect_left',
method: "bisect_left",
freeze: true,
freeze_message: __("Bisecting Left ..."),
callback: (r) => {
frm.trigger("render_heatmap");
}
},
});
},
bisect_right(frm) {
@@ -69,10 +69,10 @@ frappe.ui.form.on("Bisect Accounting Statements", {
doc: frm.doc,
freeze: true,
freeze_message: __("Bisecting Right ..."),
method: 'bisect_right',
method: "bisect_right",
callback: (r) => {
frm.trigger("render_heatmap");
}
},
});
},
move_up(frm) {
@@ -80,10 +80,10 @@ frappe.ui.form.on("Bisect Accounting Statements", {
doc: frm.doc,
freeze: true,
freeze_message: __("Moving up in tree ..."),
method: 'move_up',
method: "move_up",
callback: (r) => {
frm.trigger("render_heatmap");
}
},
});
},
build_tree(frm) {
@@ -91,10 +91,10 @@ frappe.ui.form.on("Bisect Accounting Statements", {
doc: frm.doc,
freeze: true,
freeze_message: __("Rebuilding BTree for period ..."),
method: 'build_tree',
method: "build_tree",
callback: (r) => {
frm.trigger("render_heatmap");
}
},
});
},
});

View File

@@ -138,10 +138,11 @@ class BisectAccountingStatements(Document):
# 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.get_report_summary()
self.save()
def get_report_summary(self):

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

@@ -1,11 +1,10 @@
// 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,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,31 +8,34 @@ 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",
@@ -41,21 +44,27 @@ 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",
label: "Company",
fieldname: "company",
fieldtype: "Link",
reqd: 1,
@@ -63,25 +72,25 @@ frappe.ui.form.on('Chart of Accounts Importer', {
default: frm.doc.company,
},
],
primary_action: function() {
primary_action: function () {
let 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
company: data.company,
}
);
d.hide();
},
primary_action_label: __('Download')
primary_action_label: __("Download"),
});
d.show();
},
@@ -89,7 +98,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
}
},
@@ -99,89 +108,97 @@ 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 () {
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");
return frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_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');
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',
doctype: "Chart of Accounts Importer",
file_type: frm.doc.file_type,
for_validate: 1
for_validate: 1,
},
callback: function(r) {
if (r.message['show_import_button']) {
frm.page['show_import_button'] = Boolean(r.message['show_import_button']);
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

@@ -3,18 +3,20 @@
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;\
@@ -48,30 +50,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,75 +3,80 @@
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 () {
let 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;
}
@@ -83,12 +88,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 {
frm.set_value("cost_center_name", data.cost_center_name);
@@ -96,44 +101,42 @@ 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,54 +1,84 @@
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")
}],
root_label: "Cost Centers",
get_tree_nodes: 'erpnext.accounts.utils.get_children',
add_tree_node: 'erpnext.accounts.utils.add_cc',
menu_items:[
filters: [
{
label: __('New Company'),
action: function() { frappe.new_doc("Company", true) },
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1'
}
fieldname: "company",
fieldtype: "Select",
options: erpnext.utils.get_tree_options("company"),
label: __("Company"),
default: erpnext.utils.get_tree_default("company"),
},
],
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")}
root_label: "Cost Centers",
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',
},
],
ignore_fields:["parent_cost_center"],
onload: function(treeview) {
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) {
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,24 @@
// 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() {
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
}
is_group: 0,
},
};
});
frm.set_query('cost_center', 'allocation_percentages', function() {
frm.set_query("cost_center", "allocation_percentages", function () {
return {
filters: {
company: frm.doc.company,
is_group: 0
}
is_group: 0,
},
};
});
}
},
});

View File

@@ -1,44 +1,41 @@
// 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();
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);
}
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');
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,28 +1,27 @@
// 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) {
frappe.ui.form.on("Currency Exchange Settings", {
service_provider: function (frm) {
if (frm.doc.service_provider == "exchangerate.host") {
let result = ['result'];
let result = ["result"];
let params = {
date: '{transaction_date}',
from: '{from_currency}',
to: '{to_currency}'
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 result = ["rates", "{to_currency}"];
let params = {
base: '{from_currency}',
symbols: '{to_currency}'
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");
@@ -30,13 +29,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

@@ -10,7 +10,7 @@ frappe.ui.form.on("Dunning", {
company: frm.doc.company,
customer: frm.doc.customer,
outstanding_amount: [">", 0],
status: "Overdue"
status: "Overdue",
},
};
});
@@ -19,16 +19,16 @@ frappe.ui.form.on("Dunning", {
filters: {
company: frm.doc.company,
root_type: "Income",
is_group: 0
}
is_group: 0,
},
};
});
frm.set_query("cost_center", () => {
return {
filters: {
company: frm.doc.company,
is_group: 0
}
is_group: 0,
},
};
});
@@ -51,7 +51,8 @@ frappe.ui.form.on("Dunning", {
__("Payment"),
function () {
frm.events.make_payment_entry(frm);
}, __("Create")
},
__("Create")
);
frm.page.set_inner_btn_group_as_primary(__("Create"));
}
@@ -69,7 +70,7 @@ frappe.ui.form.on("Dunning", {
get_query_filters: {
docstatus: 1,
status: "Overdue",
company: frm.doc.company
company: frm.doc.company,
},
allow_child_item_selection: true,
child_fieldname: "payment_schedule",
@@ -78,9 +79,12 @@ frappe.ui.form.on("Dunning", {
});
}
frappe.dynamic_link = { doc: frm.doc, fieldname: 'customer', doctype: 'Customer' };
frappe.dynamic_link = { doc: frm.doc, fieldname: "customer", doctype: "Customer" };
frm.toggle_display("customer_name", (frm.doc.customer_name && frm.doc.customer_name !== frm.doc.customer));
frm.toggle_display(
"customer_name",
frm.doc.customer_name && frm.doc.customer_name !== frm.doc.customer
);
},
// When multiple companies are set up. in case company name is changed set default company address
company: function (frm) {
@@ -90,8 +94,8 @@ frappe.ui.form.on("Dunning", {
args: { name: frm.doc.company, existing_address: frm.doc.company_address || "" },
debounce: 2000,
callback: function (r) {
frm.set_value("company_address", r && r.message || "");
}
frm.set_value("company_address", (r && r.message) || "");
},
});
if (frm.fields_dict.currency) {
@@ -125,16 +129,16 @@ frappe.ui.form.on("Dunning", {
transaction_date: frm.doc.posting_date,
from_currency: frm.doc.currency,
to_currency: company_currency,
args: "for_selling"
args: "for_selling",
},
freeze: true,
freeze_message: __("Fetching exchange rates ..."),
callback: function(r) {
callback: function (r) {
const exchange_rate = flt(r.message);
if (exchange_rate != frm.doc.conversion_rate) {
frm.set_value("conversion_rate", exchange_rate);
}
}
},
});
} else {
frm.trigger("conversion_rate");
@@ -166,8 +170,7 @@ 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,
@@ -204,10 +207,7 @@ frappe.ui.form.on("Dunning", {
calculate_overdue_days: function (frm) {
frm.doc.overdue_payments.forEach((row) => {
if (frm.doc.posting_date && row.due_date) {
const overdue_days = moment(frm.doc.posting_date).diff(
row.due_date,
"days"
);
const overdue_days = moment(frm.doc.posting_date).diff(row.due_date, "days");
frappe.model.set_value(row.doctype, row.name, "overdue_days", overdue_days);
}
});
@@ -215,15 +215,16 @@ frappe.ui.form.on("Dunning", {
calculate_interest: function (frm) {
frm.doc.overdue_payments.forEach((row) => {
const interest_per_day = frm.doc.rate_of_interest / 100 / 365;
const interest = flt((interest_per_day * row.overdue_days * row.outstanding), precision("interest", row));
const interest = flt(
interest_per_day * row.overdue_days * row.outstanding,
precision("interest", row)
);
frappe.model.set_value(row.doctype, row.name, "interest", interest);
});
},
calculate_totals: function (frm) {
const total_interest = frm.doc.overdue_payments
.reduce((prev, cur) => prev + cur.interest, 0);
const total_outstanding = frm.doc.overdue_payments
.reduce((prev, cur) => prev + cur.outstanding, 0);
const total_interest = frm.doc.overdue_payments.reduce((prev, cur) => prev + cur.interest, 0);
const total_outstanding = frm.doc.overdue_payments.reduce((prev, cur) => prev + cur.outstanding, 0);
const dunning_amount = total_interest + frm.doc.dunning_fee;
const base_dunning_amount = dunning_amount * frm.doc.conversion_rate;
const grand_total = total_outstanding + dunning_amount;
@@ -240,8 +241,7 @@ frappe.ui.form.on("Dunning", {
},
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,
@@ -257,5 +257,5 @@ frappe.ui.form.on("Dunning", {
frappe.ui.form.on("Overdue Payment", {
interest: function (frm) {
frm.trigger("calculate_totals");
}
});
},
});

View File

@@ -1,75 +1,79 @@
// 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) => {
@@ -80,7 +84,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({
@@ -88,66 +92,68 @@ 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

@@ -1,8 +1,6 @@
// 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,17 +1,21 @@
// 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

@@ -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

@@ -1,47 +1,49 @@
// 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);
@@ -52,19 +54,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");
}
@@ -92,119 +94,121 @@ 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 Invoices')
primary_action_label: __("Get Invoices"),
});
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);
@@ -212,5 +216,5 @@ frappe.ui.form.on('Discounted Invoice', {
invoices_remove: (frm) => {
frm.events.calculate_total_amount(frm);
frm.events.refresh_filters(frm);
}
},
});

View File

@@ -1,21 +1,16 @@
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,27 +1,49 @@
// 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,58 +4,82 @@
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', 'Asset Depreciation Schedule', "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",
"Asset Depreciation Schedule",
"Repost Accounting Ledger",
"Unreconcile Payment",
"Unreconcile Payment Entries",
"Bank Transaction",
];
},
refresh: function(frm) {
refresh: function (frm) {
erpnext.toggle_naming_series();
if (frm.doc.repost_required && frm.doc.docstatus===1) {
frm.set_intro(__("Accounting entries for this Journal Entry need to be reposted. Please click on 'Repost' button to update."));
frm.add_custom_button(__('Repost Accounting Entries'),
() => {
frm.call({
doc: frm.doc,
method: 'repost_accounting_entries',
freeze: true,
freeze_message: __('Reposting...'),
callback: (r) => {
if (!r.exc) {
frappe.msgprint(__('Accounting Entries are reposted.'));
frm.refresh();
}
if (frm.doc.repost_required && frm.doc.docstatus === 1) {
frm.set_intro(
__(
"Accounting entries for this Journal Entry need to be reposted. Please click on 'Repost' button to update."
)
);
frm.add_custom_button(__("Repost Accounting Entries"), () => {
frm.call({
doc: frm.doc,
method: "repost_accounting_entries",
freeze: true,
freeze_message: __("Reposting..."),
callback: (r) => {
if (!r.exc) {
frappe.msgprint(__("Accounting Entries are reposted."));
frm.refresh();
}
});
}).removeClass('btn-default').addClass('btn-warning');
},
});
})
.removeClass("btn-default")
.addClass("btn-warning");
}
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);
});
}
@@ -63,52 +87,63 @@ 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"));
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)]));
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) {
@@ -116,96 +151,101 @@ 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){
voucher_type: function (frm) {
if (!frm.doc.company) return null;
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)) {
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
})
update_jv_details(frm.doc, doc.accounts);
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);
});
}
}
},
});
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);
});
refresh_field("accounts");
}
};
erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Controller {
onload() {
@@ -220,69 +260,67 @@ 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");
@@ -290,11 +328,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) {
let party_field = "";
if(jvd.reference_type.indexOf("Sales")===0) {
if (jvd.reference_type.indexOf("Sales") === 0) {
party_field = "customer";
} else if (jvd.reference_type.indexOf("Purchase")===0) {
} else if (jvd.reference_type.indexOf("Purchase") === 0) {
party_field = "supplier";
}
@@ -305,51 +343,49 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
return out;
});
}
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;
@@ -357,8 +393,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 {
@@ -368,41 +404,43 @@ 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]));
}
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",
child: d,
@@ -410,89 +448,97 @@ frappe.ui.form.on("Journal Entry Account", {
company: frm.doc.company,
party_type: d.party_type,
party: d.party,
}
},
});
}
},
cost_center: function(frm, dt, dn) {
cost_center: function (frm, dt, dn) {
erpnext.journal_entry.set_account_details(frm, dt, dn);
},
account: function(frm, dt, dn) {
account: function (frm, dt, dn) {
erpnext.journal_entry.set_account_details(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") {
@@ -507,50 +553,70 @@ $.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();
@@ -567,11 +633,21 @@ $.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();
@@ -581,33 +657,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: ['in', [frappe.get_doc(":Company", frm.doc.company).default_currency, null]]
account_currency: [
"in",
[frappe.get_doc(":Company", frm.doc.company).default_currency, null],
],
});
}
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_details: 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",
@@ -619,13 +698,13 @@ $.extend(erpnext.journal_entry, {
credit: flt(d.credit_in_account_currency),
exchange_rate: d.exchange_rate,
},
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

@@ -158,14 +158,14 @@ class JournalEntry(AccountsController):
validate_docs_for_deferred_accounting([self.name], [])
def submit(self):
if len(self.accounts) > 100:
if len(self.accounts) > 100 and not frappe.job:
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:
if len(self.accounts) > 100 and not frappe.job:
msgprint(_("The task has been enqueued as a background job."), alert=True)
self.queue_action("cancel", timeout=4600)
else:

View File

@@ -1,18 +1,8 @@
frappe.listview_settings["Journal Entry"] = {
add_fields: [
"voucher_type",
"posting_date",
"total_debit",
"company",
"user_remark",
],
add_fields: ["voucher_type", "posting_date", "total_debit", "company", "user_remark"],
get_indicator: function (doc) {
if (doc.docstatus === 1) {
return [
__(doc.voucher_type),
"blue",
`voucher_type,=,${doc.voucher_type}`,
];
return [__(doc.voucher_type), "blue", `voucher_type,=,${doc.voucher_type}`];
}
},
};

View File

@@ -2,78 +2,85 @@
// 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: ['in', [frappe.get_doc(":Company", frm.doc.company).default_currency, null]]
account_currency: [
"in",
[frappe.get_doc(":Company", frm.doc.company).default_currency, null],
],
});
}
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,8 +1,6 @@
// 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,30 +3,37 @@
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.")}
@@ -37,14 +44,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,
},
};
});
@@ -52,13 +59,15 @@ 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,48 +1,52 @@
// 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,
@@ -58,100 +62,98 @@ 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,33 +1,34 @@
// 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", "");
},
});

File diff suppressed because it is too large Load Diff

View File

@@ -1271,7 +1271,13 @@ class PaymentEntry(AccountsController):
references = [x for x in self.get("references") if x.name == entry.name]
for ref in references:
if ref.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Journal Entry"):
if ref.reference_doctype in (
"Sales Invoice",
"Purchase Invoice",
"Journal Entry",
"Sales Order",
"Purchase Order",
):
self.add_advance_gl_for_reference(gl_entries, ref)
def add_advance_gl_for_reference(self, gl_entries, invoice):
@@ -1285,14 +1291,15 @@ class PaymentEntry(AccountsController):
"voucher_detail_no": invoice.name,
}
posting_date = frappe.db.get_value(
invoice.reference_doctype, invoice.reference_name, "posting_date"
)
date_field = "posting_date"
if invoice.reference_doctype in ["Sales Order", "Purchase Order"]:
date_field = "transaction_date"
posting_date = frappe.db.get_value(invoice.reference_doctype, invoice.reference_name, date_field)
if getdate(posting_date) < getdate(self.posting_date):
posting_date = self.posting_date
dr_or_cr = "credit" if invoice.reference_doctype == "Sales Invoice" else "debit"
dr_or_cr = "credit" if invoice.reference_doctype in ["Sales Invoice", "Sales Order"] else "debit"
args_dict["account"] = invoice.account
args_dict[dr_or_cr] = invoice.allocated_amount
args_dict[dr_or_cr + "_in_account_currency"] = invoice.allocated_amount
@@ -2197,6 +2204,11 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
else:
outstanding_amount = flt(total_amount) - flt(ref_doc.get("advance_paid"))
if reference_doctype in ["Sales Order", "Purchase Order"]:
party_type = "Customer" if reference_doctype == "Sales Order" else "Supplier"
party_field = "customer" if reference_doctype == "Sales Order" else "supplier"
party = ref_doc.get(party_field)
account = get_party_account(party_type, party, ref_doc.company)
else:
# Get the exchange rate based on the posting date of the ref doc.
exchange_rate = get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date)

View File

@@ -1,14 +1,13 @@
frappe.listview_settings['Payment Entry'] = {
onload: function(listview) {
frappe.listview_settings["Payment Entry"] = {
onload: function (listview) {
if (listview.page.fields_dict.party_type) {
listview.page.fields_dict.party_type.get_query = function() {
listview.page.fields_dict.party_type.get_query = function () {
return {
"filters": {
"name": ["in", Object.keys(frappe.boot.party_account_types)],
}
filters: {
name: ["in", Object.keys(frappe.boot.party_account_types)],
},
};
};
}
}
},
};

View File

@@ -1070,6 +1070,8 @@ class TestPaymentEntry(FrappeTestCase):
self.assertRaises(frappe.ValidationError, pe_draft.submit)
def test_details_update_on_reference_table(self):
from erpnext.accounts.party import get_party_account
so = make_sales_order(
customer="_Test Customer USD", currency="USD", qty=1, rate=100, do_not_submit=True
)
@@ -1084,6 +1086,7 @@ class TestPaymentEntry(FrappeTestCase):
ref_details = get_reference_details(so.doctype, so.name, pe.paid_from_account_currency)
expected_response = {
"account": get_party_account("Customer", so.customer, so.company),
"total_amount": 5000.0,
"outstanding_amount": 5000.0,
"exchange_rate": 1.0,

View File

@@ -1,11 +1,11 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Payment Gateway Account', {
frappe.ui.form.on("Payment Gateway Account", {
refresh(frm) {
erpnext.utils.check_payments_app();
if(!frm.doc.__islocal) {
frm.set_df_property('payment_gateway', 'read_only', 1);
if (!frm.doc.__islocal) {
frm.set_df_property("payment_gateway", "read_only", 1);
}
}
},
});

View File

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

View File

@@ -1,61 +1,69 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Payment Order', {
setup: function(frm) {
frm.set_query("company_bank_account", function() {
frappe.ui.form.on("Payment Order", {
setup: function (frm) {
frm.set_query("company_bank_account", function () {
return {
filters: {
"is_company_account":1
}
}
is_company_account: 1,
},
};
});
frm.set_df_property('references', 'cannot_add_rows', true);
frm.set_df_property("references", "cannot_add_rows", true);
},
refresh: function(frm) {
refresh: function (frm) {
if (frm.doc.docstatus == 0) {
frm.add_custom_button(__('Payment Request'), function() {
frm.trigger("get_from_payment_request");
}, __("Get Payments from"));
frm.add_custom_button(
__("Payment Request"),
function () {
frm.trigger("get_from_payment_request");
},
__("Get Payments from")
);
frm.add_custom_button(__('Payment Entry'), function() {
frm.trigger("get_from_payment_entry");
}, __("Get Payments from"));
frm.add_custom_button(
__("Payment Entry"),
function () {
frm.trigger("get_from_payment_entry");
},
__("Get Payments from")
);
frm.trigger('remove_button');
frm.trigger("remove_button");
}
// payment Entry
if (frm.doc.docstatus===1 && frm.doc.payment_order_type==='Payment Request') {
frm.add_custom_button(__('Create Payment Entries'), function() {
if (frm.doc.docstatus === 1 && frm.doc.payment_order_type === "Payment Request") {
frm.add_custom_button(__("Create Payment Entries"), function () {
frm.trigger("make_payment_records");
});
}
},
remove_row_if_empty: function(frm) {
remove_row_if_empty: function (frm) {
// remove if first row is empty
if (frm.doc.references.length > 0 && !frm.doc.references[0].reference_name) {
frm.doc.references = [];
}
},
remove_button: function(frm) {
remove_button: function (frm) {
// remove custom button of order type that is not imported
let label = ["Payment Request", "Payment Entry"];
if (frm.doc.references.length > 0 && frm.doc.payment_order_type) {
label = label.reduce(x => {
x!= frm.doc.payment_order_type;
label = label.reduce((x) => {
x != frm.doc.payment_order_type;
return x;
});
frm.remove_custom_button(label, "Get from");
}
},
get_from_payment_entry: function(frm) {
get_from_payment_entry: function (frm) {
frm.trigger("remove_row_if_empty");
erpnext.utils.map_current_doc({
method: "erpnext.accounts.doctype.payment_entry.payment_entry.make_payment_order",
@@ -63,7 +71,7 @@ frappe.ui.form.on('Payment Order', {
target: frm,
date_field: "posting_date",
setters: {
party: frm.doc.supplier || ""
party: frm.doc.supplier || "",
},
get_query_filters: {
bank: frm.doc.bank,
@@ -71,70 +79,79 @@ frappe.ui.form.on('Payment Order', {
payment_type: ["!=", "Receive"],
bank_account: frm.doc.company_bank_account,
paid_from: frm.doc.account,
payment_order_status: ["=", "Initiated"]
}
payment_order_status: ["=", "Initiated"],
},
});
},
get_from_payment_request: function(frm) {
get_from_payment_request: function (frm) {
frm.trigger("remove_row_if_empty");
erpnext.utils.map_current_doc({
method: "erpnext.accounts.doctype.payment_request.payment_request.make_payment_order",
source_doctype: "Payment Request",
target: frm,
setters: {
party: frm.doc.supplier || ""
party: frm.doc.supplier || "",
},
get_query_filters: {
bank: frm.doc.bank,
docstatus: 1,
status: ["=", "Initiated"],
}
},
});
},
make_payment_records: function(frm){
make_payment_records: function (frm) {
var dialog = new frappe.ui.Dialog({
title: __("For Supplier"),
fields: [
{"fieldtype": "Link", "label": __("Supplier"), "fieldname": "supplier", "options":"Supplier",
"get_query": function () {
{
fieldtype: "Link",
label: __("Supplier"),
fieldname: "supplier",
options: "Supplier",
get_query: function () {
return {
query:"erpnext.accounts.doctype.payment_order.payment_order.get_supplier_query",
filters: {'parent': frm.doc.name}
}
}, "reqd": 1
query: "erpnext.accounts.doctype.payment_order.payment_order.get_supplier_query",
filters: { parent: frm.doc.name },
};
},
reqd: 1,
},
{"fieldtype": "Link", "label": __("Mode of Payment"), "fieldname": "mode_of_payment", "options":"Mode of Payment",
"get_query": function () {
{
fieldtype: "Link",
label: __("Mode of Payment"),
fieldname: "mode_of_payment",
options: "Mode of Payment",
get_query: function () {
return {
query:"erpnext.accounts.doctype.payment_order.payment_order.get_mop_query",
filters: {'parent': frm.doc.name}
}
}
}
]
query: "erpnext.accounts.doctype.payment_order.payment_order.get_mop_query",
filters: { parent: frm.doc.name },
};
},
},
],
});
dialog.set_primary_action(__("Submit"), function() {
dialog.set_primary_action(__("Submit"), function () {
var args = dialog.get_values();
if(!args) return;
if (!args) return;
return frappe.call({
method: "erpnext.accounts.doctype.payment_order.payment_order.make_payment_records",
args: {
"name": frm.doc.name,
"supplier": args.supplier,
"mode_of_payment": args.mode_of_payment
name: frm.doc.name,
supplier: args.supplier,
mode_of_payment: args.mode_of_payment,
},
freeze: true,
callback: function(r) {
callback: function (r) {
dialog.hide();
frm.refresh();
}
})
})
},
});
});
dialog.show();
},

View File

@@ -2,97 +2,94 @@
// For license information, please see license.txt
frappe.provide("erpnext.accounts");
erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationController extends frappe.ui.form.Controller {
erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationController extends (
frappe.ui.form.Controller
) {
onload() {
const default_company = frappe.defaults.get_default('company');
this.frm.set_value('company', default_company);
const default_company = frappe.defaults.get_default("company");
this.frm.set_value("company", default_company);
this.frm.set_value('party_type', '');
this.frm.set_value('party', '');
this.frm.set_value('receivable_payable_account', '');
this.frm.set_value("party_type", "");
this.frm.set_value("party", "");
this.frm.set_value("receivable_payable_account", "");
this.frm.set_query("party_type", () => {
return {
"filters": {
"name": ["in", Object.keys(frappe.boot.party_account_types)],
}
}
});
this.frm.set_query('receivable_payable_account', () => {
return {
filters: {
"company": this.frm.doc.company,
"is_group": 0,
"account_type": frappe.boot.party_account_types[this.frm.doc.party_type],
"root_type": this.frm.doc.party_type == 'Customer' ? "Asset" : "Liability"
}
name: ["in", Object.keys(frappe.boot.party_account_types)],
},
};
});
this.frm.set_query('default_advance_account', () => {
this.frm.set_query("receivable_payable_account", () => {
return {
filters: {
"company": this.frm.doc.company,
"is_group": 0,
"account_type": this.frm.doc.party_type == 'Customer' ? "Receivable": "Payable",
"root_type": this.frm.doc.party_type == 'Customer' ? "Liability": "Asset"
}
company: this.frm.doc.company,
is_group: 0,
account_type: frappe.boot.party_account_types[this.frm.doc.party_type],
root_type: this.frm.doc.party_type == "Customer" ? "Asset" : "Liability",
},
};
});
this.frm.set_query('bank_cash_account', () => {
this.frm.set_query("default_advance_account", () => {
return {
filters:[
['Account', 'company', '=', this.frm.doc.company],
['Account', 'is_group', '=', 0],
['Account', 'account_type', 'in', ['Bank', 'Cash']]
]
filters: {
company: this.frm.doc.company,
is_group: 0,
account_type: this.frm.doc.party_type == "Customer" ? "Receivable" : "Payable",
root_type: this.frm.doc.party_type == "Customer" ? "Liability" : "Asset",
},
};
});
this.frm.set_query("bank_cash_account", () => {
return {
filters: [
["Account", "company", "=", this.frm.doc.company],
["Account", "is_group", "=", 0],
["Account", "account_type", "in", ["Bank", "Cash"]],
],
};
});
this.frm.set_query("cost_center", () => {
return {
"filters": {
"company": this.frm.doc.company,
"is_group": 0
}
}
filters: {
company: this.frm.doc.company,
is_group: 0,
},
};
});
}
refresh() {
this.frm.disable_save();
this.frm.set_df_property('invoices', 'cannot_delete_rows', true);
this.frm.set_df_property('payments', 'cannot_delete_rows', true);
this.frm.set_df_property('allocation', 'cannot_delete_rows', true);
this.frm.set_df_property('invoices', 'cannot_add_rows', true);
this.frm.set_df_property('payments', 'cannot_add_rows', true);
this.frm.set_df_property('allocation', 'cannot_add_rows', true);
this.frm.set_df_property("invoices", "cannot_delete_rows", true);
this.frm.set_df_property("payments", "cannot_delete_rows", true);
this.frm.set_df_property("allocation", "cannot_delete_rows", true);
this.frm.set_df_property("invoices", "cannot_add_rows", true);
this.frm.set_df_property("payments", "cannot_add_rows", true);
this.frm.set_df_property("allocation", "cannot_add_rows", true);
if (this.frm.doc.receivable_payable_account) {
this.frm.add_custom_button(__('Get Unreconciled Entries'), () =>
this.frm.add_custom_button(__("Get Unreconciled Entries"), () =>
this.frm.trigger("get_unreconciled_entries")
);
this.frm.change_custom_button_type(__('Get Unreconciled Entries'), null, 'primary');
this.frm.change_custom_button_type(__("Get Unreconciled Entries"), null, "primary");
}
if (this.frm.doc.invoices.length && this.frm.doc.payments.length) {
this.frm.add_custom_button(__('Allocate'), () =>
this.frm.trigger("allocate")
);
this.frm.change_custom_button_type(__('Allocate'), null, 'primary');
this.frm.change_custom_button_type(__('Get Unreconciled Entries'), null, 'default');
this.frm.add_custom_button(__("Allocate"), () => this.frm.trigger("allocate"));
this.frm.change_custom_button_type(__("Allocate"), null, "primary");
this.frm.change_custom_button_type(__("Get Unreconciled Entries"), null, "default");
}
if (this.frm.doc.allocation.length) {
this.frm.add_custom_button(__('Reconcile'), () =>
this.frm.trigger("reconcile")
);
this.frm.change_custom_button_type(__('Reconcile'), null, 'primary');
this.frm.change_custom_button_type(__('Get Unreconciled Entries'), null, 'default');
this.frm.change_custom_button_type(__('Allocate'), null, 'default');
this.frm.add_custom_button(__("Reconcile"), () => this.frm.trigger("reconcile"));
this.frm.change_custom_button_type(__("Reconcile"), null, "primary");
this.frm.change_custom_button_type(__("Get Unreconciled Entries"), null, "default");
this.frm.change_custom_button_type(__("Allocate"), null, "default");
}
this.frm.trigger("set_query_for_dimension_filters");
@@ -101,31 +98,39 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
if (this.frm.doc.receivable_payable_account) {
this.frm.call({
doc: this.frm.doc,
method: 'is_auto_process_enabled',
method: "is_auto_process_enabled",
callback: (r) => {
if (r.message) {
this.frm.call({
'method': "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.is_any_doc_running",
"args": {
for_filter: {
company: this.frm.doc.company,
party_type: this.frm.doc.party_type,
party: this.frm.doc.party,
receivable_payable_account: this.frm.doc.receivable_payable_account
this.frm
.call({
method: "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.is_any_doc_running",
args: {
for_filter: {
company: this.frm.doc.company,
party_type: this.frm.doc.party_type,
party: this.frm.doc.party,
receivable_payable_account: this.frm.doc.receivable_payable_account,
},
},
})
.then((r) => {
if (r.message) {
let doc_link = frappe.utils.get_form_link(
"Process Payment Reconciliation",
r.message,
true
);
let msg = __(
"Payment Reconciliation Job: {0} is running for this party. Can't reconcile now.",
[doc_link]
);
this.frm.dashboard.add_comment(msg, "yellow");
}
}
}).then(r => {
if (r.message) {
let doc_link = frappe.utils.get_form_link("Process Payment Reconciliation", r.message, true);
let msg = __("Payment Reconciliation Job: {0} is running for this party. Can't reconcile now.", [doc_link]);
this.frm.dashboard.add_comment(msg, "yellow");
}
});
});
}
}
},
});
}
}
set_query_for_dimension_filters() {
frappe.call({
@@ -135,29 +140,29 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
},
callback: (r) => {
if (!r.exc && r.message) {
r.message.forEach(x => {
r.message.forEach((x) => {
this.frm.set_query(x.fieldname, () => {
return {
'filters': x.filters
filters: x.filters,
};
});
});
}
}
},
});
}
company() {
this.frm.set_value('party', '');
this.frm.set_value('receivable_payable_account', '');
this.frm.set_value("party", "");
this.frm.set_value("receivable_payable_account", "");
}
party_type() {
this.frm.set_value('party', '');
this.frm.set_value("party", "");
}
party() {
this.frm.set_value('receivable_payable_account', '');
this.frm.set_value("receivable_payable_account", "");
this.frm.trigger("clear_child_tables");
if (!this.frm.doc.receivable_payable_account && this.frm.doc.party_type && this.frm.doc.party) {
@@ -167,7 +172,7 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
company: this.frm.doc.company,
party_type: this.frm.doc.party_type,
party: this.frm.doc.party,
include_advance: 1
include_advance: 1,
},
callback: (r) => {
if (!r.exc && r.message) {
@@ -175,7 +180,7 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
this.frm.set_value("default_advance_account", r.message[1]);
}
this.frm.refresh();
}
},
});
}
}
@@ -193,7 +198,6 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
this.frm.trigger("get_unreconciled_entries");
}
clear_child_tables() {
this.frm.clear_table("invoices");
this.frm.clear_table("payments");
@@ -205,52 +209,52 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
this.frm.clear_table("allocation");
return this.frm.call({
doc: this.frm.doc,
method: 'get_unreconciled_entries',
method: "get_unreconciled_entries",
callback: () => {
if (!(this.frm.doc.payments.length || this.frm.doc.invoices.length)) {
frappe.throw({message: __("No Unreconciled Invoices and Payments found for this party and account")});
} else if (!(this.frm.doc.invoices.length)) {
frappe.throw({message: __("No Outstanding Invoices found for this party")});
} else if (!(this.frm.doc.payments.length)) {
frappe.throw({message: __("No Unreconciled Payments found for this party")});
frappe.throw({
message: __("No Unreconciled Invoices and Payments found for this party and account"),
});
} else if (!this.frm.doc.invoices.length) {
frappe.throw({ message: __("No Outstanding Invoices found for this party") });
} else if (!this.frm.doc.payments.length) {
frappe.throw({ message: __("No Unreconciled Payments found for this party") });
}
this.frm.refresh();
}
},
});
}
allocate() {
let payments = this.frm.fields_dict.payments.grid.get_selected_children();
if (!(payments.length)) {
if (!payments.length) {
payments = this.frm.doc.payments;
}
let invoices = this.frm.fields_dict.invoices.grid.get_selected_children();
if (!(invoices.length)) {
if (!invoices.length) {
invoices = this.frm.doc.invoices;
}
return this.frm.call({
doc: this.frm.doc,
method: 'allocate_entries',
method: "allocate_entries",
args: {
payments: payments,
invoices: invoices
invoices: invoices,
},
callback: () => {
this.frm.refresh();
}
},
});
}
reconcile() {
var show_dialog = this.frm.doc.allocation.filter(d => d.difference_amount);
var show_dialog = this.frm.doc.allocation.filter((d) => d.difference_amount);
if (show_dialog && show_dialog.length) {
this.data = [];
const dialog = new frappe.ui.Dialog({
title: __("Select Difference Account"),
size: 'extra-large',
size: "extra-large",
fields: [
{
fieldname: "allocation",
@@ -262,77 +266,89 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
get_data: () => {
return this.data;
},
fields: [{
fieldtype:'Data',
fieldname:"docname",
in_list_view: 1,
hidden: 1
}, {
fieldtype:'Data',
fieldname:"reference_name",
label: __("Voucher No"),
in_list_view: 1,
read_only: 1
}, {
fieldtype:'Date',
fieldname:"gain_loss_posting_date",
label: __("Posting Date"),
in_list_view: 1,
reqd: 1,
}, {
fieldtype:'Link',
options: 'Account',
in_list_view: 1,
label: __("Difference Account"),
fieldname: 'difference_account',
reqd: 1,
get_query: () => {
return {
filters: {
company: this.frm.doc.company,
is_group: 0
}
}
}
}, {
fieldtype:'Currency',
in_list_view: 1,
label: __("Difference Amount"),
fieldname: 'difference_amount',
read_only: 1
}]
fields: [
{
fieldtype: "Data",
fieldname: "docname",
in_list_view: 1,
hidden: 1,
},
{
fieldtype: "Data",
fieldname: "reference_name",
label: __("Voucher No"),
in_list_view: 1,
read_only: 1,
},
{
fieldtype: "Date",
fieldname: "gain_loss_posting_date",
label: __("Posting Date"),
in_list_view: 1,
reqd: 1,
},
{
fieldtype: "Link",
options: "Account",
in_list_view: 1,
label: __("Difference Account"),
fieldname: "difference_account",
reqd: 1,
get_query: () => {
return {
filters: {
company: this.frm.doc.company,
is_group: 0,
},
};
},
},
{
fieldtype: "Currency",
in_list_view: 1,
label: __("Difference Amount"),
fieldname: "difference_amount",
read_only: 1,
},
],
},
{
fieldtype: 'HTML',
options: "<b> New Journal Entry will be posted for the difference amount </b>"
}
fieldtype: "HTML",
options: "<b> New Journal Entry will be posted for the difference amount </b>",
},
],
primary_action: () => {
const args = dialog.get_values()["allocation"];
args.forEach(d => {
frappe.model.set_value("Payment Reconciliation Allocation", d.docname,
"difference_account", d.difference_account);
frappe.model.set_value("Payment Reconciliation Allocation", d.docname,
"gain_loss_posting_date", d.gain_loss_posting_date);
args.forEach((d) => {
frappe.model.set_value(
"Payment Reconciliation Allocation",
d.docname,
"difference_account",
d.difference_account
);
frappe.model.set_value(
"Payment Reconciliation Allocation",
d.docname,
"gain_loss_posting_date",
d.gain_loss_posting_date
);
});
this.reconcile_payment_entries();
dialog.hide();
},
primary_action_label: __('Reconcile Entries')
primary_action_label: __("Reconcile Entries"),
});
this.frm.doc.allocation.forEach(d => {
this.frm.doc.allocation.forEach((d) => {
if (d.difference_amount) {
dialog.fields_dict.allocation.df.data.push({
'docname': d.name,
'reference_name': d.reference_name,
'difference_amount': d.difference_amount,
'difference_account': d.difference_account,
'gain_loss_posting_date': d.gain_loss_posting_date
docname: d.name,
reference_name: d.reference_name,
difference_amount: d.difference_amount,
difference_account: d.difference_account,
gain_loss_posting_date: d.gain_loss_posting_date,
});
}
});
@@ -348,41 +364,39 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
reconcile_payment_entries() {
return this.frm.call({
doc: this.frm.doc,
method: 'reconcile',
method: "reconcile",
callback: () => {
this.frm.clear_table("allocation");
this.frm.refresh();
}
},
});
}
};
frappe.ui.form.on('Payment Reconciliation Allocation', {
allocated_amount: function(frm, cdt, cdn) {
frappe.ui.form.on("Payment Reconciliation Allocation", {
allocated_amount: function (frm, cdt, cdn) {
let row = locals[cdt][cdn];
// filter invoice
let invoice = frm.doc.invoices.filter((x) => (x.invoice_number == row.invoice_number));
let invoice = frm.doc.invoices.filter((x) => x.invoice_number == row.invoice_number);
// filter payment
let payment = frm.doc.payments.filter((x) => (x.reference_name == row.reference_name));
let payment = frm.doc.payments.filter((x) => x.reference_name == row.reference_name);
frm.call({
doc: frm.doc,
method: 'calculate_difference_on_allocation_change',
method: "calculate_difference_on_allocation_change",
args: {
payment_entry: payment,
invoice: invoice,
allocated_amount: row.allocated_amount
allocated_amount: row.allocated_amount,
},
callback: (r) => {
if (r.message) {
row.difference_amount = r.message;
frm.refresh();
}
}
},
});
}
},
});
extend_cscript(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({frm: cur_frm}));
extend_cscript(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({ frm: cur_frm }));

View File

@@ -1,87 +1,99 @@
cur_frm.add_fetch("payment_gateway_account", "payment_account", "payment_account")
cur_frm.add_fetch("payment_gateway_account", "payment_gateway", "payment_gateway")
cur_frm.add_fetch("payment_gateway_account", "message", "message")
cur_frm.add_fetch("payment_gateway_account", "payment_account", "payment_account");
cur_frm.add_fetch("payment_gateway_account", "payment_gateway", "payment_gateway");
cur_frm.add_fetch("payment_gateway_account", "message", "message");
frappe.ui.form.on("Payment Request", {
setup: function(frm) {
frm.set_query("party_type", function() {
setup: function (frm) {
frm.set_query("party_type", function () {
return {
query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
};
});
}
})
},
});
frappe.ui.form.on("Payment Request", "onload", function(frm, dt, dn){
frappe.ui.form.on("Payment Request", "onload", function (frm, dt, dn) {
if (frm.doc.reference_doctype) {
frappe.call({
method:"erpnext.accounts.doctype.payment_request.payment_request.get_print_format_list",
args: {"ref_doctype": frm.doc.reference_doctype},
callback:function(r){
set_field_options("print_format", r.message["print_format"])
}
})
method: "erpnext.accounts.doctype.payment_request.payment_request.get_print_format_list",
args: { ref_doctype: frm.doc.reference_doctype },
callback: function (r) {
set_field_options("print_format", r.message["print_format"]);
},
});
}
})
});
frappe.ui.form.on("Payment Request", "refresh", function(frm) {
if(frm.doc.status == 'Failed'){
frappe.ui.form.on("Payment Request", "refresh", function (frm) {
if (frm.doc.status == "Failed") {
frm.set_intro(__("Failure: {0}", [frm.doc.failed_reason]), "red");
}
if(frm.doc.payment_request_type == 'Inward' && frm.doc.payment_channel !== "Phone" &&
!in_list(["Initiated", "Paid"], frm.doc.status) && !frm.doc.__islocal && frm.doc.docstatus==1){
frm.add_custom_button(__('Resend Payment Email'), function(){
if (
frm.doc.payment_request_type == "Inward" &&
frm.doc.payment_channel !== "Phone" &&
!in_list(["Initiated", "Paid"], frm.doc.status) &&
!frm.doc.__islocal &&
frm.doc.docstatus == 1
) {
frm.add_custom_button(__("Resend Payment Email"), function () {
frappe.call({
method: "erpnext.accounts.doctype.payment_request.payment_request.resend_payment_email",
args: {"docname": frm.doc.name},
args: { docname: frm.doc.name },
freeze: true,
freeze_message: __("Sending"),
callback: function(r){
if(!r.exc) {
callback: function (r) {
if (!r.exc) {
frappe.msgprint(__("Message Sent"));
}
}
},
});
});
}
if((!frm.doc.payment_gateway_account || frm.doc.payment_request_type == "Outward") && frm.doc.status == "Initiated") {
frm.add_custom_button(__('Create Payment Entry'), function(){
if (
(!frm.doc.payment_gateway_account || frm.doc.payment_request_type == "Outward") &&
frm.doc.status == "Initiated"
) {
frm.add_custom_button(__("Create Payment Entry"), function () {
frappe.call({
method: "erpnext.accounts.doctype.payment_request.payment_request.make_payment_entry",
args: {"docname": frm.doc.name},
args: { docname: frm.doc.name },
freeze: true,
callback: function(r){
if(!r.exc) {
callback: function (r) {
if (!r.exc) {
var doc = frappe.model.sync(r.message);
frappe.set_route("Form", r.message.doctype, r.message.name);
}
}
},
});
}).addClass("btn-primary");
}
});
frappe.ui.form.on("Payment Request", "is_a_subscription", function(frm) {
frappe.ui.form.on("Payment Request", "is_a_subscription", function (frm) {
frm.toggle_reqd("payment_gateway_account", frm.doc.is_a_subscription);
frm.toggle_reqd("subscription_plans", frm.doc.is_a_subscription);
if (frm.doc.is_a_subscription && frm.doc.reference_doctype && frm.doc.reference_name) {
frappe.call({
method: "erpnext.accounts.doctype.payment_request.payment_request.get_subscription_details",
args: {"reference_doctype": frm.doc.reference_doctype, "reference_name": frm.doc.reference_name},
args: { reference_doctype: frm.doc.reference_doctype, reference_name: frm.doc.reference_name },
freeze: true,
callback: function(data){
if(!data.exc) {
$.each(data.message || [], function(i, v){
var d = frappe.model.add_child(frm.doc, "Subscription Plan Detail", "subscription_plans");
callback: function (data) {
if (!data.exc) {
$.each(data.message || [], function (i, v) {
var d = frappe.model.add_child(
frm.doc,
"Subscription Plan Detail",
"subscription_plans"
);
d.qty = v.qty;
d.plan = v.plan;
});
frm.refresh_field("subscription_plans");
}
}
},
});
}
});

View File

@@ -1,26 +1,21 @@
frappe.listview_settings['Payment Request'] = {
frappe.listview_settings["Payment Request"] = {
add_fields: ["status"],
get_indicator: function(doc) {
if(doc.status == "Draft") {
get_indicator: function (doc) {
if (doc.status == "Draft") {
return [__("Draft"), "gray", "status,=,Draft"];
}
if(doc.status == "Requested") {
if (doc.status == "Requested") {
return [__("Requested"), "green", "status,=,Requested"];
}
else if(doc.status == "Initiated") {
} else if (doc.status == "Initiated") {
return [__("Initiated"), "green", "status,=,Initiated"];
}
else if(doc.status == "Partially Paid") {
} else if (doc.status == "Partially Paid") {
return [__("Partially Paid"), "orange", "status,=,Partially Paid"];
}
else if(doc.status == "Paid") {
} else if (doc.status == "Paid") {
return [__("Paid"), "blue", "status,=,Paid"];
}
else if(doc.status == "Failed") {
} else if (doc.status == "Failed") {
return [__("Failed"), "red", "status,=,Failed"];
}
else if(doc.status == "Cancelled") {
} else if (doc.status == "Cancelled") {
return [__("Cancelled"), "red", "status,=,Cancelled"];
}
}
}
},
};

View File

@@ -1,22 +1,24 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Payment Term', {
frappe.ui.form.on("Payment Term", {
onload(frm) {
frm.trigger('set_dynamic_description');
frm.trigger("set_dynamic_description");
},
discount(frm) {
frm.trigger('set_dynamic_description');
frm.trigger("set_dynamic_description");
},
discount_type(frm) {
frm.trigger('set_dynamic_description');
frm.trigger("set_dynamic_description");
},
set_dynamic_description(frm) {
if (frm.doc.discount) {
let description = __("{0}% of total invoice value will be given as discount.", [frm.doc.discount]);
if (frm.doc.discount_type == 'Amount') {
let description = __("{0}% of total invoice value will be given as discount.", [
frm.doc.discount,
]);
if (frm.doc.discount_type == "Amount") {
description = __("{0} will be given as discount.", [frm.doc.discount]);
}
frm.set_df_property("discount", "description", description);
}
}
},
});

View File

@@ -1,12 +1,18 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Payment Terms Template', {
refresh: function(frm) {
frm.fields_dict.terms.grid.toggle_reqd("payment_term", frm.doc.allocate_payment_based_on_payment_terms);
frappe.ui.form.on("Payment Terms Template", {
refresh: function (frm) {
frm.fields_dict.terms.grid.toggle_reqd(
"payment_term",
frm.doc.allocate_payment_based_on_payment_terms
);
},
allocate_payment_based_on_payment_terms: function(frm) {
frm.fields_dict.terms.grid.toggle_reqd("payment_term", frm.doc.allocate_payment_based_on_payment_terms);
}
allocate_payment_based_on_payment_terms: function (frm) {
frm.fields_dict.terms.grid.toggle_reqd(
"payment_term",
frm.doc.allocate_payment_based_on_payment_terms
);
},
});

View File

@@ -1,38 +1,41 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Period Closing Voucher', {
onload: function(frm) {
frappe.ui.form.on("Period Closing Voucher", {
onload: function (frm) {
if (!frm.doc.transaction_date) frm.doc.transaction_date = frappe.datetime.obj_to_str(new Date());
},
setup: function(frm) {
frm.set_query("closing_account_head", function() {
setup: function (frm) {
frm.set_query("closing_account_head", function () {
return {
filters: [
['Account', 'company', '=', frm.doc.company],
['Account', 'is_group', '=', '0'],
['Account', 'freeze_account', '=', 'No'],
['Account', 'root_type', 'in', 'Liability, Equity']
]
}
["Account", "company", "=", frm.doc.company],
["Account", "is_group", "=", "0"],
["Account", "freeze_account", "=", "No"],
["Account", "root_type", "in", "Liability, Equity"],
],
};
});
},
refresh: function(frm) {
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,
"group_by": "",
"show_cancelled_entries": frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, "fa fa-table");
refresh: function (frm) {
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,
group_by: "",
show_cancelled_entries: frm.doc.docstatus === 2,
};
frappe.set_route("query-report", "General Ledger");
},
"fa fa-table"
);
}
}
})
},
});

View File

@@ -1,36 +1,37 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('POS Closing Entry', {
onload: function(frm) {
frm.ignore_doctypes_on_cancel_all = ['POS Invoice Merge Log'];
frm.set_query("pos_profile", function(doc) {
frappe.ui.form.on("POS Closing Entry", {
onload: function (frm) {
frm.ignore_doctypes_on_cancel_all = ["POS Invoice Merge Log"];
frm.set_query("pos_profile", function (doc) {
return {
filters: { 'user': doc.user }
filters: { user: doc.user },
};
});
frm.set_query("user", function(doc) {
frm.set_query("user", function (doc) {
return {
query: "erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_cashiers",
filters: { 'parent': doc.pos_profile }
filters: { parent: doc.pos_profile },
};
});
frm.set_query("pos_opening_entry", function(doc) {
return { filters: { 'status': 'Open', 'docstatus': 1 } };
frm.set_query("pos_opening_entry", function (doc) {
return { filters: { status: "Open", docstatus: 1 } };
});
if (frm.doc.docstatus === 0 && !frm.doc.amended_from) frm.set_value("period_end_date", frappe.datetime.now_datetime());
if (frm.doc.docstatus === 0 && !frm.doc.amended_from)
frm.set_value("period_end_date", frappe.datetime.now_datetime());
frappe.realtime.on('closing_process_complete', async function(data) {
frappe.realtime.on("closing_process_complete", async function (data) {
await frm.reload_doc();
if (frm.doc.status == 'Failed' && frm.doc.error_message) {
if (frm.doc.status == "Failed" && frm.doc.error_message) {
frappe.msgprint({
title: __('POS Closing Failed'),
title: __("POS Closing Failed"),
message: frm.doc.error_message,
indicator: 'orange',
clear: true
indicator: "orange",
clear: true,
});
}
});
@@ -47,23 +48,23 @@ frappe.ui.form.on('POS Closing Entry', {
}
},
refresh: function(frm) {
if (frm.doc.docstatus == 1 && frm.doc.status == 'Failed') {
refresh: function (frm) {
if (frm.doc.docstatus == 1 && frm.doc.status == "Failed") {
const issue = '<a id="jump_to_error" style="text-decoration: underline;">issue</a>';
frm.dashboard.set_headline(
__('POS Closing failed while running in a background process. You can resolve the {0} and retry the process again.', [issue]));
__(
"POS Closing failed while running in a background process. You can resolve the {0} and retry the process again.",
[issue]
)
);
$('#jump_to_error').on('click', (e) => {
$("#jump_to_error").on("click", (e) => {
e.preventDefault();
frappe.utils.scroll_to(
cur_frm.get_field("error_message").$wrapper,
true,
30
);
frappe.utils.scroll_to(cur_frm.get_field("error_message").$wrapper, true, 30);
});
frm.add_custom_button(__('Retry'), function () {
frm.call('retry', {}, () => {
frm.add_custom_button(__("Retry"), function () {
frm.call("retry", {}, () => {
frm.reload_doc();
});
});
@@ -71,48 +72,54 @@ frappe.ui.form.on('POS Closing Entry', {
},
pos_opening_entry(frm) {
if (frm.doc.pos_opening_entry && frm.doc.period_start_date && frm.doc.period_end_date && frm.doc.user) {
if (
frm.doc.pos_opening_entry &&
frm.doc.period_start_date &&
frm.doc.period_end_date &&
frm.doc.user
) {
reset_values(frm);
frappe.run_serially([
() => frm.trigger("set_opening_amounts"),
() => frm.trigger("get_pos_invoices")
() => frm.trigger("get_pos_invoices"),
]);
}
},
set_opening_amounts(frm) {
return frappe.db.get_doc("POS Opening Entry", frm.doc.pos_opening_entry)
return frappe.db
.get_doc("POS Opening Entry", frm.doc.pos_opening_entry)
.then(({ balance_details }) => {
balance_details.forEach(detail => {
balance_details.forEach((detail) => {
frm.add_child("payment_reconciliation", {
mode_of_payment: detail.mode_of_payment,
opening_amount: detail.opening_amount,
expected_amount: detail.opening_amount
expected_amount: detail.opening_amount,
});
})
});
});
},
get_pos_invoices(frm) {
return frappe.call({
method: 'erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_pos_invoices',
method: "erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_pos_invoices",
args: {
start: frappe.datetime.get_datetime_as_string(frm.doc.period_start_date),
end: frappe.datetime.get_datetime_as_string(frm.doc.period_end_date),
pos_profile: frm.doc.pos_profile,
user: frm.doc.user
user: frm.doc.user,
},
callback: (r) => {
let pos_docs = r.message;
set_form_data(pos_docs, frm);
refresh_fields(frm);
set_html_data(frm);
}
},
});
},
before_save: async function(frm) {
frappe.dom.freeze(__('Processing Sales! Please Wait...'));
before_save: async function (frm) {
frappe.dom.freeze(__("Processing Sales! Please Wait..."));
frm.set_value("grand_total", 0);
frm.set_value("net_total", 0);
@@ -125,12 +132,12 @@ frappe.ui.form.on('POS Closing Entry', {
await Promise.all([
frappe.call({
method: 'erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_pos_invoices',
method: "erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_pos_invoices",
args: {
start: frappe.datetime.get_datetime_as_string(frm.doc.period_start_date),
end: frappe.datetime.get_datetime_as_string(frm.doc.period_end_date),
pos_profile: frm.doc.pos_profile,
user: frm.doc.user
user: frm.doc.user,
},
callback: (r) => {
let pos_invoices = r.message;
@@ -143,22 +150,22 @@ frappe.ui.form.on('POS Closing Entry', {
refresh_fields(frm);
set_html_data(frm);
}
}
})
])
},
}),
]);
frappe.dom.unfreeze();
}
},
});
frappe.ui.form.on('POS Closing Entry Detail', {
frappe.ui.form.on("POS Closing Entry Detail", {
closing_amount: (frm, cdt, cdn) => {
const row = locals[cdt][cdn];
frappe.model.set_value(cdt, cdn, "difference", flt(row.closing_amount - row.expected_amount));
}
})
},
});
function set_form_data(data, frm) {
data.forEach(d => {
data.forEach((d) => {
add_to_pos_transaction(d, frm);
frm.doc.grand_total += flt(d.grand_total);
frm.doc.net_total += flt(d.net_total);
@@ -173,13 +180,15 @@ function add_to_pos_transaction(d, frm) {
pos_invoice: d.name,
posting_date: d.posting_date,
grand_total: d.grand_total,
customer: d.customer
})
customer: d.customer,
});
}
function refresh_payments(d, frm) {
d.payments.forEach(p => {
const payment = frm.doc.payment_reconciliation.find(pay => pay.mode_of_payment === p.mode_of_payment);
d.payments.forEach((p) => {
const payment = frm.doc.payment_reconciliation.find(
(pay) => pay.mode_of_payment === p.mode_of_payment
);
if (p.account == d.account_for_change_amount) {
p.amount -= flt(d.change_amount);
}
@@ -192,25 +201,25 @@ function refresh_payments(d, frm) {
mode_of_payment: p.mode_of_payment,
opening_amount: 0,
expected_amount: p.amount,
closing_amount: 0
})
closing_amount: 0,
});
}
})
});
}
function refresh_taxes(d, frm) {
d.taxes.forEach(t => {
const tax = frm.doc.taxes.find(tx => tx.account_head === t.account_head && tx.rate === t.rate);
d.taxes.forEach((t) => {
const tax = frm.doc.taxes.find((tx) => tx.account_head === t.account_head && tx.rate === t.rate);
if (tax) {
tax.amount += flt(t.tax_amount);
} else {
frm.add_child("taxes", {
account_head: t.account_head,
rate: t.rate,
amount: t.tax_amount
})
amount: t.tax_amount,
});
}
})
});
}
function reset_values(frm) {
@@ -232,13 +241,13 @@ function refresh_fields(frm) {
}
function set_html_data(frm) {
if (frm.doc.docstatus === 1 && frm.doc.status == 'Submitted') {
if (frm.doc.docstatus === 1 && frm.doc.status == "Submitted") {
frappe.call({
method: "get_payment_reconciliation_details",
doc: frm.doc,
callback: (r) => {
frm.get_field("payment_reconciliation_details").$wrapper.html(r.message);
}
},
});
}
}

View File

@@ -2,16 +2,15 @@
// License: GNU General Public License v3. See license.txt
// render
frappe.listview_settings['POS Closing Entry'] = {
get_indicator: function(doc) {
frappe.listview_settings["POS Closing Entry"] = {
get_indicator: function (doc) {
var status_color = {
"Draft": "red",
"Submitted": "blue",
"Queued": "orange",
"Failed": "red",
"Cancelled": "red"
Draft: "red",
Submitted: "blue",
Queued: "orange",
Failed: "red",
Cancelled: "red",
};
return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
}
return [__(doc.status), status_color[doc.status], "status,=," + doc.status];
},
};

View File

@@ -21,19 +21,23 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
onload(doc) {
super.onload();
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice Merge Log', 'POS Closing Entry', 'Serial and Batch Bundle'];
this.frm.ignore_doctypes_on_cancel_all = [
"POS Invoice Merge Log",
"POS Closing Entry",
"Serial and Batch Bundle",
];
if(doc.__islocal && doc.is_pos && frappe.get_route_str() !== 'point-of-sale') {
if (doc.__islocal && doc.is_pos && frappe.get_route_str() !== "point-of-sale") {
this.frm.script_manager.trigger("is_pos");
this.frm.refresh_fields();
}
this.frm.set_query("set_warehouse", function(doc) {
this.frm.set_query("set_warehouse", function (doc) {
return {
filters: {
company: doc.company ? doc.company : '',
}
}
company: doc.company ? doc.company : "",
},
};
});
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
@@ -47,26 +51,29 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
super.refresh();
if (doc.docstatus == 1 && !doc.is_return) {
this.frm.add_custom_button(__('Return'), this.make_sales_return, __('Create'));
this.frm.page.set_inner_btn_group_as_primary(__('Create'));
this.frm.add_custom_button(__("Return"), this.make_sales_return, __("Create"));
this.frm.page.set_inner_btn_group_as_primary(__("Create"));
}
if (doc.is_return && doc.__islocal) {
this.frm.return_print_format = "Sales Invoice Return";
this.frm.set_value('consolidated_invoice', '');
this.frm.set_value("consolidated_invoice", "");
}
this.frm.set_query("customer", (function () {
const customer_groups = this.settings?.customer_groups;
this.frm.set_query(
"customer",
function () {
const customer_groups = this.settings?.customer_groups;
if (!customer_groups?.length) return {};
if (!customer_groups?.length) return {};
return {
filters: {
customer_group: ["in", customer_groups],
}
}
}).bind(this));
return {
filters: {
customer_group: ["in", customer_groups],
},
};
}.bind(this)
);
}
is_pos() {
@@ -74,19 +81,19 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
}
async set_pos_data() {
if(this.frm.doc.is_pos) {
if (this.frm.doc.is_pos) {
this.frm.set_value("allocate_advances_automatically", 0);
if(!this.frm.doc.company) {
if (!this.frm.doc.company) {
this.frm.set_value("is_pos", 0);
frappe.msgprint(__("Please specify Company to proceed"));
} else {
const r = await this.frm.call({
doc: this.frm.doc,
method: "set_missing_values",
freeze: true
freeze: true,
});
if(!r.exc) {
if(r.message) {
if (!r.exc) {
if (r.message) {
this.frm.pos_print_format = r.message.print_format || "";
this.frm.meta.default_print_format = r.message.print_format || "";
this.frm.doc.campaign = r.message.campaign;
@@ -103,32 +110,36 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
}
customer() {
if (!this.frm.doc.customer) return
if (!this.frm.doc.customer) return;
const pos_profile = this.frm.doc.pos_profile;
if(this.frm.updating_party_details) return;
erpnext.utils.get_party_details(this.frm,
"erpnext.accounts.party.get_party_details", {
if (this.frm.updating_party_details) return;
erpnext.utils.get_party_details(
this.frm,
"erpnext.accounts.party.get_party_details",
{
posting_date: this.frm.doc.posting_date,
party: this.frm.doc.customer,
party_type: "Customer",
account: this.frm.doc.debit_to,
price_list: this.frm.doc.selling_price_list,
pos_profile: pos_profile,
company_address: this.frm.doc.company_address
}, () => {
company_address: this.frm.doc.company_address,
},
() => {
this.apply_pricing_rule();
});
}
);
}
pos_profile(frm) {
if (!frm.pos_profile || frm.pos_profile == '') {
if (!frm.pos_profile || frm.pos_profile == "") {
this.update_customer_groups_settings([]);
return;
}
frappe.call({
method: "erpnext.selling.page.point_of_sale.point_of_sale.get_pos_profile_data",
args: { "pos_profile": frm.pos_profile },
args: { pos_profile: frm.pos_profile },
callback: ({ message: profile }) => {
this.update_customer_groups_settings(profile?.customer_groups);
this.frm.set_value("company", profile?.company);
@@ -137,17 +148,17 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
}
update_customer_groups_settings(customer_groups) {
this.settings.customer_groups = customer_groups?.map((group) => group.name)
this.settings.customer_groups = customer_groups?.map((group) => group.name);
}
amount(){
this.write_off_outstanding_amount_automatically()
amount() {
this.write_off_outstanding_amount_automatically();
}
change_amount(){
if(this.frm.doc.paid_amount > this.frm.doc.grand_total){
change_amount() {
if (this.frm.doc.paid_amount > this.frm.doc.grand_total) {
this.calculate_write_off_amount();
}else {
} else {
this.frm.set_value("change_amount", 0.0);
this.frm.set_value("base_change_amount", 0.0);
}
@@ -155,7 +166,7 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
this.frm.refresh_fields();
}
loyalty_amount(){
loyalty_amount() {
this.calculate_outstanding_amount();
this.frm.refresh_field("outstanding_amount");
this.frm.refresh_field("paid_amount");
@@ -166,8 +177,12 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
if (cint(this.frm.doc.write_off_outstanding_amount_automatically)) {
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]);
// this will make outstanding amount 0
this.frm.set_value("write_off_amount",
flt(this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount"))
this.frm.set_value(
"write_off_amount",
flt(
this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance,
precision("write_off_amount")
)
);
}
@@ -178,65 +193,69 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
make_sales_return() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.pos_invoice.pos_invoice.make_sales_return",
frm: cur_frm
})
frm: cur_frm,
});
}
}
};
extend_cscript(cur_frm.cscript, new erpnext.selling.POSInvoiceController({ frm: cur_frm }))
extend_cscript(cur_frm.cscript, new erpnext.selling.POSInvoiceController({ frm: cur_frm }));
frappe.ui.form.on('POS Invoice', {
redeem_loyalty_points: function(frm) {
frappe.ui.form.on("POS Invoice", {
redeem_loyalty_points: function (frm) {
frm.events.get_loyalty_details(frm);
},
loyalty_points: function(frm) {
loyalty_points: function (frm) {
if (frm.redemption_conversion_factor) {
frm.events.set_loyalty_points(frm);
} else {
frappe.call({
method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_redeemption_factor",
args: {
"loyalty_program": frm.doc.loyalty_program
loyalty_program: frm.doc.loyalty_program,
},
callback: function(r) {
callback: function (r) {
if (r) {
frm.redemption_conversion_factor = r.message;
frm.events.set_loyalty_points(frm);
}
}
},
});
}
},
get_loyalty_details: function(frm) {
get_loyalty_details: function (frm) {
if (frm.doc.customer && frm.doc.redeem_loyalty_points) {
frappe.call({
method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_loyalty_program_details",
args: {
"customer": frm.doc.customer,
"loyalty_program": frm.doc.loyalty_program,
"expiry_date": frm.doc.posting_date,
"company": frm.doc.company
customer: frm.doc.customer,
loyalty_program: frm.doc.loyalty_program,
expiry_date: frm.doc.posting_date,
company: frm.doc.company,
},
callback: function(r) {
callback: function (r) {
if (r) {
frm.set_value("loyalty_redemption_account", r.message.expense_account);
frm.set_value("loyalty_redemption_cost_center", r.message.cost_center);
frm.redemption_conversion_factor = r.message.conversion_factor;
}
}
},
});
}
},
set_loyalty_points: function(frm) {
set_loyalty_points: function (frm) {
if (frm.redemption_conversion_factor) {
let loyalty_amount = flt(frm.redemption_conversion_factor*flt(frm.doc.loyalty_points), precision("loyalty_amount"));
var remaining_amount = flt(frm.doc.grand_total) - flt(frm.doc.total_advance) - flt(frm.doc.write_off_amount);
if (frm.doc.grand_total && (remaining_amount < loyalty_amount)) {
let redeemable_points = parseInt(remaining_amount/frm.redemption_conversion_factor);
frappe.throw(__("You can only redeem max {0} points in this order.",[redeemable_points]));
let loyalty_amount = flt(
frm.redemption_conversion_factor * flt(frm.doc.loyalty_points),
precision("loyalty_amount")
);
var remaining_amount =
flt(frm.doc.grand_total) - flt(frm.doc.total_advance) - flt(frm.doc.write_off_amount);
if (frm.doc.grand_total && remaining_amount < loyalty_amount) {
let redeemable_points = parseInt(remaining_amount / frm.redemption_conversion_factor);
frappe.throw(__("You can only redeem max {0} points in this order.", [redeemable_points]));
}
frm.set_value("loyalty_amount", loyalty_amount);
}
@@ -244,43 +263,49 @@ frappe.ui.form.on('POS Invoice', {
request_for_payment: function (frm) {
if (!frm.doc.contact_mobile) {
frappe.throw(__('Please enter mobile number first.'));
frappe.throw(__("Please enter mobile number first."));
}
frm.dirty();
frm.save().then(() => {
frappe.dom.freeze(__('Waiting for payment...'));
frappe.dom.freeze(__("Waiting for payment..."));
frappe
.call({
method: 'create_payment_request',
doc: frm.doc
method: "create_payment_request",
doc: frm.doc,
})
.fail(() => {
frappe.dom.unfreeze();
frappe.msgprint(__('Payment request failed'));
frappe.msgprint(__("Payment request failed"));
})
.then(({ message }) => {
const payment_request_name = message.name;
setTimeout(() => {
frappe.db.get_value('Payment Request', payment_request_name, ['status', 'grand_total']).then(({ message }) => {
if (message.status != 'Paid') {
frappe.dom.unfreeze();
frappe.msgprint({
message: __('Payment Request took too long to respond. Please try requesting for payment again.'),
title: __('Request Timeout')
});
} else if (frappe.dom.freeze_count != 0) {
frappe.dom.unfreeze();
cur_frm.reload_doc();
cur_pos.payment.events.submit_invoice();
frappe.db
.get_value("Payment Request", payment_request_name, ["status", "grand_total"])
.then(({ message }) => {
if (message.status != "Paid") {
frappe.dom.unfreeze();
frappe.msgprint({
message: __(
"Payment Request took too long to respond. Please try requesting for payment again."
),
title: __("Request Timeout"),
});
} else if (frappe.dom.freeze_count != 0) {
frappe.dom.unfreeze();
cur_frm.reload_doc();
cur_pos.payment.events.submit_invoice();
frappe.show_alert({
message: __("Payment of {0} received successfully.", [format_currency(message.grand_total, frm.doc.currency, 0)]),
indicator: 'green'
});
}
});
frappe.show_alert({
message: __("Payment of {0} received successfully.", [
format_currency(message.grand_total, frm.doc.currency, 0),
]),
indicator: "green",
});
}
});
}, 60000);
});
});
}
},
});

View File

@@ -2,40 +2,47 @@
// License: GNU General Public License v3. See license.txt
// render
frappe.listview_settings['POS Invoice'] = {
add_fields: ["customer", "customer_name", "base_grand_total", "outstanding_amount", "due_date", "company",
"currency", "is_return"],
get_indicator: function(doc) {
frappe.listview_settings["POS Invoice"] = {
add_fields: [
"customer",
"customer_name",
"base_grand_total",
"outstanding_amount",
"due_date",
"company",
"currency",
"is_return",
],
get_indicator: function (doc) {
var status_color = {
"Draft": "red",
"Unpaid": "orange",
"Paid": "green",
"Submitted": "blue",
"Consolidated": "green",
"Return": "darkgrey",
Draft: "red",
Unpaid: "orange",
Paid: "green",
Submitted: "blue",
Consolidated: "green",
Return: "darkgrey",
"Unpaid and Discounted": "orange",
"Overdue and Discounted": "red",
"Overdue": "red"
Overdue: "red",
};
return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
return [__(doc.status), status_color[doc.status], "status,=," + doc.status];
},
right_column: "grand_total",
onload: function(me) {
me.page.add_action_item('Make Merge Log', function() {
onload: function (me) {
me.page.add_action_item("Make Merge Log", function () {
const invoices = me.get_checked_items();
frappe.call({
method: "erpnext.accounts.doctype.pos_invoice.pos_invoice.make_merge_log",
freeze: true,
args:{
"invoices": invoices
args: {
invoices: invoices,
},
callback: function (r) {
if (r.message) {
var doc = frappe.model.sync(r.message)[0];
frappe.set_route("Form", doc.doctype, doc.name);
}
}
},
});
});
},

View File

@@ -3,10 +3,10 @@
# import frappe
from frappe.model.document import Document
from erpnext.accounts.doctype.sales_invoice_item.sales_invoice_item import SalesInvoiceItem
class POSInvoiceItem(Document):
class POSInvoiceItem(SalesInvoiceItem):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.

View File

@@ -1,21 +1,21 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('POS Invoice Merge Log', {
setup: function(frm) {
frm.set_query("pos_invoice", "pos_invoices", doc => {
frappe.ui.form.on("POS Invoice Merge Log", {
setup: function (frm) {
frm.set_query("pos_invoice", "pos_invoices", (doc) => {
return {
filters: {
'docstatus': 1,
'customer': doc.customer,
'consolidated_invoice': ''
}
}
docstatus: 1,
customer: doc.customer,
consolidated_invoice: "",
},
};
});
},
merge_invoices_based_on: function(frm) {
frm.set_value('customer', '');
frm.set_value('customer_group', '');
}
merge_invoices_based_on: function (frm) {
frm.set_value("customer", "");
frm.set_value("customer_group", "");
},
});

View File

@@ -1,56 +1,55 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('POS Opening Entry', {
frappe.ui.form.on("POS Opening Entry", {
setup(frm) {
if (frm.doc.docstatus == 0) {
frm.trigger('set_posting_date_read_only');
frm.set_value('period_start_date', frappe.datetime.now_datetime());
frm.set_value('user', frappe.session.user);
frm.trigger("set_posting_date_read_only");
frm.set_value("period_start_date", frappe.datetime.now_datetime());
frm.set_value("user", frappe.session.user);
}
frm.set_query("user", function(doc) {
frm.set_query("user", function (doc) {
return {
query: "erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_cashiers",
filters: { 'parent': doc.pos_profile }
filters: { parent: doc.pos_profile },
};
});
},
refresh(frm) {
// set default posting date / time
if(frm.doc.docstatus == 0) {
if(!frm.doc.posting_date) {
frm.set_value('posting_date', frappe.datetime.nowdate());
if (frm.doc.docstatus == 0) {
if (!frm.doc.posting_date) {
frm.set_value("posting_date", frappe.datetime.nowdate());
}
frm.trigger('set_posting_date_read_only');
frm.trigger("set_posting_date_read_only");
}
},
set_posting_date_read_only(frm) {
if(frm.doc.docstatus == 0 && frm.doc.set_posting_date) {
frm.set_df_property('posting_date', 'read_only', 0);
if (frm.doc.docstatus == 0 && frm.doc.set_posting_date) {
frm.set_df_property("posting_date", "read_only", 0);
} else {
frm.set_df_property('posting_date', 'read_only', 1);
frm.set_df_property("posting_date", "read_only", 1);
}
},
set_posting_date(frm) {
frm.trigger('set_posting_date_read_only');
frm.trigger("set_posting_date_read_only");
},
pos_profile: (frm) => {
if (frm.doc.pos_profile) {
frappe.db.get_doc("POS Profile", frm.doc.pos_profile)
.then(({ payments }) => {
if (payments.length) {
frm.doc.balance_details = [];
payments.forEach(({ mode_of_payment }) => {
frm.add_child("balance_details", { mode_of_payment });
})
frm.refresh_field("balance_details");
}
});
frappe.db.get_doc("POS Profile", frm.doc.pos_profile).then(({ payments }) => {
if (payments.length) {
frm.doc.balance_details = [];
payments.forEach(({ mode_of_payment }) => {
frm.add_child("balance_details", { mode_of_payment });
});
frm.refresh_field("balance_details");
}
});
}
}
},
});

View File

@@ -2,15 +2,14 @@
// License: GNU General Public License v3. See license.txt
// render
frappe.listview_settings['POS Opening Entry'] = {
get_indicator: function(doc) {
frappe.listview_settings["POS Opening Entry"] = {
get_indicator: function (doc) {
var status_color = {
"Draft": "red",
"Open": "orange",
"Closed": "green",
"Cancelled": "red"
Draft: "red",
Open: "orange",
Closed: "green",
Cancelled: "red",
};
return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
}
return [__(doc.status), status_color[doc.status], "status,=," + doc.status];
},
};

View File

@@ -1,149 +1,143 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on('POS Profile', {
setup: function(frm) {
frm.set_query("selling_price_list", function() {
frappe.ui.form.on("POS Profile", {
setup: function (frm) {
frm.set_query("selling_price_list", function () {
return { filters: { selling: 1 } };
});
frm.set_query("tc_name", function() {
frm.set_query("tc_name", function () {
return { filters: { selling: 1 } };
});
erpnext.queries.setup_queries(frm, "Warehouse", function() {
erpnext.queries.setup_queries(frm, "Warehouse", function () {
return erpnext.queries.warehouse(frm.doc);
});
frm.set_query("print_format", function() {
frm.set_query("print_format", function () {
return {
filters: [
['Print Format', 'doc_type', '=', 'POS Invoice']
]
filters: [["Print Format", "doc_type", "=", "POS Invoice"]],
};
});
frm.set_query("account_for_change_amount", function(doc) {
frm.set_query("account_for_change_amount", function (doc) {
if (!doc.company) {
frappe.throw(__('Please set Company'));
frappe.throw(__("Please set Company"));
}
return {
filters: {
account_type: ['in', ["Cash", "Bank"]],
account_type: ["in", ["Cash", "Bank"]],
is_group: 0,
company: doc.company
}
company: doc.company,
},
};
});
frm.set_query("taxes_and_charges", function() {
frm.set_query("taxes_and_charges", function () {
return {
filters: [
['Sales Taxes and Charges Template', 'company', '=', frm.doc.company],
['Sales Taxes and Charges Template', 'docstatus', '!=', 2]
]
["Sales Taxes and Charges Template", "company", "=", frm.doc.company],
["Sales Taxes and Charges Template", "docstatus", "!=", 2],
],
};
});
frm.set_query('company_address', function(doc) {
frm.set_query("company_address", function (doc) {
if (!doc.company) {
frappe.throw(__('Please set Company'));
frappe.throw(__("Please set Company"));
}
return {
query: 'frappe.contacts.doctype.address.address.address_query',
query: "frappe.contacts.doctype.address.address.address_query",
filters: {
link_doctype: 'Company',
link_name: doc.company
}
link_doctype: "Company",
link_name: doc.company,
},
};
});
frm.set_query('income_account', function(doc) {
frm.set_query("income_account", function (doc) {
if (!doc.company) {
frappe.throw(__('Please set Company'));
frappe.throw(__("Please set Company"));
}
return {
filters: {
'is_group': 0,
'company': doc.company,
'account_type': "Income Account"
}
is_group: 0,
company: doc.company,
account_type: "Income Account",
},
};
});
frm.set_query('cost_center', function(doc) {
frm.set_query("cost_center", function (doc) {
if (!doc.company) {
frappe.throw(__('Please set Company'));
frappe.throw(__("Please set Company"));
}
return {
filters: {
'company': doc.company,
'is_group': 0
}
company: doc.company,
is_group: 0,
},
};
});
frm.set_query('expense_account', function(doc) {
frm.set_query("expense_account", function (doc) {
if (!doc.company) {
frappe.throw(__('Please set Company'));
frappe.throw(__("Please set Company"));
}
return {
filters: {
"report_type": "Profit and Loss",
"company": doc.company,
"is_group": 0
}
report_type: "Profit and Loss",
company: doc.company,
is_group: 0,
},
};
});
frm.set_query("select_print_heading", function() {
frm.set_query("select_print_heading", function () {
return {
filters: [
['Print Heading', 'docstatus', '!=', 2]
]
filters: [["Print Heading", "docstatus", "!=", 2]],
};
});
frm.set_query("write_off_account", function(doc) {
frm.set_query("write_off_account", function (doc) {
return {
filters: {
'report_type': 'Profit and Loss',
'is_group': 0,
'company': doc.company
}
report_type: "Profit and Loss",
is_group: 0,
company: doc.company,
},
};
});
frm.set_query("write_off_cost_center", function(doc) {
frm.set_query("write_off_cost_center", function (doc) {
return {
filters: {
'is_group': 0,
'company': doc.company
}
is_group: 0,
company: doc.company,
},
};
});
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
},
refresh: function(frm) {
refresh: function (frm) {
if (frm.doc.company) {
frm.trigger("toggle_display_account_head");
}
},
company: function(frm) {
company: function (frm) {
frm.trigger("toggle_display_account_head");
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
},
toggle_display_account_head: function(frm) {
frm.toggle_display('expense_account',
erpnext.is_perpetual_inventory_enabled(frm.doc.company));
}
});
toggle_display_account_head: function (frm) {
frm.toggle_display("expense_account", erpnext.is_perpetual_inventory_enabled(frm.doc.company));
},
});

View File

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

View File

@@ -1,57 +1,91 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
let search_fields_datatypes = ['Data', 'Link', 'Dynamic Link', 'Long Text', 'Select', 'Small Text', 'Text', 'Text Editor'];
let do_not_include_fields = ["naming_series", "item_code", "item_name", "stock_uom", "asset_naming_series",
"default_material_request_type", "valuation_method", "warranty_period", "weight_uom", "batch_number_series",
"serial_no_series", "purchase_uom", "customs_tariff_number", "sales_uom", "deferred_revenue_account",
"deferred_expense_account", "quality_inspection_template", "route", "slideshow", "website_image_alt", "thumbnail",
"web_long_description"]
let search_fields_datatypes = [
"Data",
"Link",
"Dynamic Link",
"Long Text",
"Select",
"Small Text",
"Text",
"Text Editor",
];
let do_not_include_fields = [
"naming_series",
"item_code",
"item_name",
"stock_uom",
"asset_naming_series",
"default_material_request_type",
"valuation_method",
"warranty_period",
"weight_uom",
"batch_number_series",
"serial_no_series",
"purchase_uom",
"customs_tariff_number",
"sales_uom",
"deferred_revenue_account",
"deferred_expense_account",
"quality_inspection_template",
"route",
"slideshow",
"website_image_alt",
"thumbnail",
"web_long_description",
];
frappe.ui.form.on('POS Settings', {
onload: function(frm) {
frappe.ui.form.on("POS Settings", {
onload: function (frm) {
frm.trigger("get_invoice_fields");
frm.trigger("add_search_options");
},
get_invoice_fields: function(frm) {
get_invoice_fields: function (frm) {
frappe.model.with_doctype("POS Invoice", () => {
var fields = $.map(frappe.get_doc("DocType", "POS Invoice").fields, function(d) {
if (frappe.model.no_value_type.indexOf(d.fieldtype) === -1 || ['Button'].includes(d.fieldtype)) {
return { label: d.label + ' (' + d.fieldtype + ')', value: d.fieldname };
var fields = $.map(frappe.get_doc("DocType", "POS Invoice").fields, function (d) {
if (
frappe.model.no_value_type.indexOf(d.fieldtype) === -1 ||
["Button"].includes(d.fieldtype)
) {
return { label: d.label + " (" + d.fieldtype + ")", value: d.fieldname };
} else {
return null;
}
});
frm.fields_dict.invoice_fields.grid.update_docfield_property(
'fieldname', 'options', [""].concat(fields)
"fieldname",
"options",
[""].concat(fields)
);
});
},
add_search_options: function(frm) {
add_search_options: function (frm) {
frappe.model.with_doctype("Item", () => {
var fields = $.map(frappe.get_doc("DocType", "Item").fields, function(d) {
if (search_fields_datatypes.includes(d.fieldtype) && !(do_not_include_fields.includes(d.fieldname))) {
var fields = $.map(frappe.get_doc("DocType", "Item").fields, function (d) {
if (
search_fields_datatypes.includes(d.fieldtype) &&
!do_not_include_fields.includes(d.fieldname)
) {
return [d.label];
} else {
return null;
}
});
fields.unshift('');
frm.fields_dict.pos_search_fields.grid.update_docfield_property('field', 'options', fields);
fields.unshift("");
frm.fields_dict.pos_search_fields.grid.update_docfield_property("field", "options", fields);
});
}
},
});
frappe.ui.form.on("POS Search Fields", {
field: function(frm, doctype, name) {
field: function (frm, doctype, name) {
var doc = frappe.get_doc(doctype, name);
var df = $.map(frappe.get_doc("DocType", "Item").fields, function(d) {
var df = $.map(frappe.get_doc("DocType", "Item").fields, function (d) {
if (doc.field == d.label && search_fields_datatypes.includes(d.fieldtype)) {
return d;
} else {
@@ -61,13 +95,13 @@ frappe.ui.form.on("POS Search Fields", {
doc.fieldname = df.fieldname;
frm.refresh_field("fields");
}
},
});
frappe.ui.form.on("POS Field", {
fieldname: function(frm, doctype, name) {
fieldname: function (frm, doctype, name) {
var doc = frappe.get_doc(doctype, name);
var df = $.map(frappe.get_doc("DocType", "POS Invoice").fields, function(d) {
var df = $.map(frappe.get_doc("DocType", "POS Invoice").fields, function (d) {
return doc.fieldname == d.fieldname ? d : null;
})[0];
@@ -77,5 +111,5 @@ frappe.ui.form.on("POS Field", {
doc.fieldtype = df.fieldtype;
doc.default_value = df.default;
frm.refresh_field("fields");
}
},
});

View File

@@ -1,44 +1,43 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Pricing Rule', {
setup: function(frm) {
frm.fields_dict["for_price_list"].get_query = function(doc){
frappe.ui.form.on("Pricing Rule", {
setup: function (frm) {
frm.fields_dict["for_price_list"].get_query = function (doc) {
return {
filters: {
'selling': doc.selling,
'buying': doc.buying,
'currency': doc.currency
}
selling: doc.selling,
buying: doc.buying,
currency: doc.currency,
},
};
};
['items', 'item_groups', 'brands'].forEach(d => {
frm.fields_dict[d].grid.get_field('uom').get_query = function(doc, cdt, cdn){
["items", "item_groups", "brands"].forEach((d) => {
frm.fields_dict[d].grid.get_field("uom").get_query = function (doc, cdt, cdn) {
var row = locals[cdt][cdn];
return {
query:"erpnext.accounts.doctype.pricing_rule.pricing_rule.get_item_uoms",
filters: {'value': row[frappe.scrub(doc.apply_on)], apply_on: doc.apply_on}
}
query: "erpnext.accounts.doctype.pricing_rule.pricing_rule.get_item_uoms",
filters: { value: row[frappe.scrub(doc.apply_on)], apply_on: doc.apply_on },
};
};
})
});
},
onload: function(frm) {
if(frm.doc.__islocal && !frm.doc.applicable_for && (frm.doc.customer || frm.doc.supplier)) {
if(frm.doc.customer) {
onload: function (frm) {
if (frm.doc.__islocal && !frm.doc.applicable_for && (frm.doc.customer || frm.doc.supplier)) {
if (frm.doc.customer) {
frm.doc.applicable_for = "Customer";
frm.doc.selling = 1
frm.doc.selling = 1;
} else {
frm.doc.applicable_for = "Supplier";
frm.doc.buying = 1
frm.doc.buying = 1;
}
}
},
refresh: function(frm) {
var help_content =
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
refresh: 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>
@@ -97,61 +96,70 @@ frappe.ui.form.on('Pricing Rule', {
</td></tr>
</table>`;
frm.set_df_property('pricing_rule_help', 'options', help_content);
frm.set_df_property("pricing_rule_help", "options", help_content);
frm.events.set_options_for_applicable_for(frm);
frm.trigger("toggle_reqd_apply_on");
},
apply_on: function(frm) {
apply_on: function (frm) {
frm.trigger("toggle_reqd_apply_on");
},
toggle_reqd_apply_on: function(frm) {
toggle_reqd_apply_on: function (frm) {
const fields = {
'Item Code': 'items',
'Item Group': 'item_groups',
'Brand': 'brands'
}
"Item Code": "items",
"Item Group": "item_groups",
Brand: "brands",
};
for (var key in fields) {
frm.toggle_reqd(fields[key],
frm.doc.apply_on === key ? 1 : 0);
frm.toggle_reqd(fields[key], frm.doc.apply_on === key ? 1 : 0);
}
},
rate_or_discount: function(frm) {
if(frm.doc.rate_or_discount == 'Rate') {
frm.set_value('for_price_list', "");
rate_or_discount: function (frm) {
if (frm.doc.rate_or_discount == "Rate") {
frm.set_value("for_price_list", "");
}
},
selling: function(frm) {
selling: function (frm) {
frm.events.set_options_for_applicable_for(frm);
},
buying: function(frm) {
buying: function (frm) {
frm.events.set_options_for_applicable_for(frm);
},
//Dynamically change the description based on type of margin
margin_type: function(frm){
frm.set_df_property('margin_rate_or_amount', 'description', frm.doc.margin_type=='Percentage'?'In Percentage %':'In Amount');
margin_type: function (frm) {
frm.set_df_property(
"margin_rate_or_amount",
"description",
frm.doc.margin_type == "Percentage" ? "In Percentage %" : "In Amount"
);
},
set_options_for_applicable_for: function(frm) {
set_options_for_applicable_for: function (frm) {
var options = [""];
var applicable_for = frm.doc.applicable_for;
if(frm.doc.selling) {
options = $.merge(options, ["Customer", "Customer Group", "Territory", "Sales Partner", "Campaign"]);
if (frm.doc.selling) {
options = $.merge(options, [
"Customer",
"Customer Group",
"Territory",
"Sales Partner",
"Campaign",
]);
}
if(frm.doc.buying) {
if (frm.doc.buying) {
$.merge(options, ["Supplier", "Supplier Group"]);
}
set_field_options("applicable_for", options.join("\n"));
if(!in_list(options, applicable_for)) applicable_for = null;
if (!in_list(options, applicable_for)) applicable_for = null;
frm.set_value("applicable_for", applicable_for);
}
},
});

View File

@@ -1,53 +1,58 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Process Deferred Accounting', {
setup: function(frm) {
frm.set_query("document_type", function() {
frappe.ui.form.on("Process Deferred Accounting", {
setup: function (frm) {
frm.set_query("document_type", function () {
return {
filters: {
'name': ['in', ['Sales Invoice', 'Purchase Invoice']]
}
name: ["in", ["Sales Invoice", "Purchase Invoice"]],
},
};
});
},
type: function(frm) {
type: function (frm) {
if (frm.doc.company && frm.doc.type) {
frm.set_query("account", function() {
frm.set_query("account", function () {
return {
filters: {
'company': frm.doc.company,
'root_type': frm.doc.type === 'Income' ? 'Liability' : 'Asset',
'is_group': 0
}
company: frm.doc.company,
root_type: frm.doc.type === "Income" ? "Liability" : "Asset",
is_group: 0,
},
};
});
}
},
validate: function() {
validate: function () {
return new Promise((resolve) => {
return frappe.db.get_single_value('Accounts Settings', 'automatically_process_deferred_accounting_entry')
.then(value => {
if(value) {
frappe.throw(__('Manual entry cannot be created! Disable automatic entry for deferred accounting in accounts settings and try again'));
return frappe.db
.get_single_value("Accounts Settings", "automatically_process_deferred_accounting_entry")
.then((value) => {
if (value) {
frappe.throw(
__(
"Manual entry cannot be created! Disable automatic entry for deferred accounting in accounts settings and try again"
)
);
}
resolve(value);
});
});
},
end_date: function(frm) {
end_date: function (frm) {
if (frm.doc.end_date && frm.doc.end_date < frm.doc.start_date) {
frappe.throw(__("End date cannot be before start date"));
}
},
onload: function(frm) {
onload: function (frm) {
if (frm.doc.posting_date && frm.doc.docstatus === 0) {
frm.set_value('start_date', frappe.datetime.add_months(frm.doc.posting_date, -1));
frm.set_value('end_date', frm.doc.posting_date);
frm.set_value("start_date", frappe.datetime.add_months(frm.doc.posting_date, -1));
frm.set_value("end_date", frm.doc.posting_date);
}
}
},
});

View File

@@ -2,129 +2,128 @@
// For license information, please see license.txt
frappe.ui.form.on("Process Payment Reconciliation", {
onload: function(frm) {
onload: function (frm) {
// set queries
frm.set_query("party_type", function() {
return {
"filters": {
"name": ["in", Object.keys(frappe.boot.party_account_types)],
}
}
});
frm.set_query('receivable_payable_account', function(doc) {
frm.set_query("party_type", function () {
return {
filters: {
"company": doc.company,
"is_group": 0,
"account_type": frappe.boot.party_account_types[doc.party_type]
}
name: ["in", Object.keys(frappe.boot.party_account_types)],
},
};
});
frm.set_query('cost_center', function(doc) {
frm.set_query("receivable_payable_account", function (doc) {
return {
filters: {
"company": doc.company,
"is_group": 0,
}
company: doc.company,
is_group: 0,
account_type: frappe.boot.party_account_types[doc.party_type],
},
};
});
frm.set_query('bank_cash_account', function(doc) {
frm.set_query("cost_center", function (doc) {
return {
filters:[
['Account', 'company', '=', doc.company],
['Account', 'is_group', '=', 0],
['Account', 'account_type', 'in', ['Bank', 'Cash']]
]
filters: {
company: doc.company,
is_group: 0,
},
};
});
frm.set_query("bank_cash_account", function (doc) {
return {
filters: [
["Account", "company", "=", doc.company],
["Account", "is_group", "=", 0],
["Account", "account_type", "in", ["Bank", "Cash"]],
],
};
});
},
refresh: function(frm) {
if (frm.doc.docstatus==1 && ['Queued', 'Paused'].find(x => x == frm.doc.status)) {
let execute_btn = __("Start / Resume")
refresh: function (frm) {
if (frm.doc.docstatus == 1 && ["Queued", "Paused"].find((x) => x == frm.doc.status)) {
let execute_btn = __("Start / Resume");
frm.add_custom_button(execute_btn, () => {
frm.call({
method: 'erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.trigger_job_for_doc',
method: "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.trigger_job_for_doc",
args: {
docname: frm.doc.name
}
}).then(r => {
if(!r.exc) {
docname: frm.doc.name,
},
}).then((r) => {
if (!r.exc) {
frappe.show_alert(__("Job Started"));
frm.reload_doc();
}
});
});
}
if (frm.doc.docstatus==1 && ['Completed', 'Running', 'Paused', 'Partially Reconciled'].find(x => x == frm.doc.status)) {
if (
frm.doc.docstatus == 1 &&
["Completed", "Running", "Paused", "Partially Reconciled"].find((x) => x == frm.doc.status)
) {
frm.call({
'method': "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.get_reconciled_count",
method: "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.get_reconciled_count",
args: {
"docname": frm.docname,
}
}).then(r => {
docname: frm.docname,
},
}).then((r) => {
if (r.message) {
let progress = 0;
let description = "";
if (r.message.processed) {
progress = (r.message.processed/r.message.total) * 100;
description = r.message.processed + "/" + r.message.total + " processed";
progress = (r.message.processed / r.message.total) * 100;
description = r.message.processed + "/" + r.message.total + " processed";
} else if (r.message.total == 0 && frm.doc.status == "Completed") {
progress = 100;
}
frm.dashboard.add_progress('Reconciliation Progress', progress, description);
frm.dashboard.add_progress("Reconciliation Progress", progress, description);
}
})
});
}
if (frm.doc.docstatus==1 && frm.doc.status == 'Running') {
let execute_btn = __("Pause")
if (frm.doc.docstatus == 1 && frm.doc.status == "Running") {
let execute_btn = __("Pause");
frm.add_custom_button(execute_btn, () => {
frm.call({
'method': "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.pause_job_for_doc",
method: "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.pause_job_for_doc",
args: {
"docname": frm.docname,
}
}).then(r => {
docname: frm.docname,
},
}).then((r) => {
if (!r.exc) {
frappe.show_alert(__("Job Paused"));
frm.reload_doc()
frm.reload_doc();
}
});
});
}
},
company(frm) {
frm.set_value('party', '');
frm.set_value('receivable_payable_account', '');
frm.set_value("party", "");
frm.set_value("receivable_payable_account", "");
},
party_type(frm) {
frm.set_value('party', '');
frm.set_value("party", "");
},
party(frm) {
frm.set_value('receivable_payable_account', '');
frm.set_value("receivable_payable_account", "");
if (!frm.doc.receivable_payable_account && frm.doc.party_type && frm.doc.party) {
return frappe.call({
method: "erpnext.accounts.party.get_party_account",
args: {
company: frm.doc.company,
party_type: frm.doc.party_type,
party: frm.doc.party
party: frm.doc.party,
},
callback: (r) => {
if (!r.exc && r.message) {
frm.set_value("receivable_payable_account", r.message);
}
frm.refresh();
}
},
});
}
}
},
});

View File

@@ -1,15 +1,15 @@
frappe.listview_settings['Process Payment Reconciliation'] = {
frappe.listview_settings["Process Payment Reconciliation"] = {
add_fields: ["status"],
get_indicator: function(doc) {
get_indicator: function (doc) {
let colors = {
'Queued': 'orange',
'Paused': 'orange',
'Completed': 'green',
'Partially Reconciled': 'orange',
'Running': 'blue',
'Failed': 'red',
Queued: "orange",
Paused: "orange",
Completed: "green",
"Partially Reconciled": "orange",
Running: "blue",
Failed: "red",
};
let status = doc.status;
return [__(status), colors[status], 'status,=,'+status];
return [__(status), colors[status], "status,=," + status];
},
};

View File

@@ -3,15 +3,14 @@
frappe.ui.form.on("Process Payment Reconciliation Log", {
refresh(frm) {
if (['Completed', 'Running', 'Paused', 'Partially Reconciled'].find(x => x == frm.doc.status)) {
if (["Completed", "Running", "Paused", "Partially Reconciled"].find((x) => x == frm.doc.status)) {
let progress = 0;
if (frm.doc.reconciled_entries != 0) {
progress = frm.doc.reconciled_entries / frm.doc.total_allocations * 100;
} else if(frm.doc.total_allocations == 0 && frm.doc.status == "Completed"){
progress = (frm.doc.reconciled_entries / frm.doc.total_allocations) * 100;
} else if (frm.doc.total_allocations == 0 && frm.doc.status == "Completed") {
progress = 100;
}
frm.dashboard.add_progress(__('Reconciliation Progress'), progress);
frm.dashboard.add_progress(__("Reconciliation Progress"), progress);
}
},
});

View File

@@ -1,15 +1,15 @@
frappe.listview_settings['Process Payment Reconciliation Log'] = {
frappe.listview_settings["Process Payment Reconciliation Log"] = {
add_fields: ["status"],
get_indicator: function(doc) {
get_indicator: function (doc) {
var colors = {
'Partially Reconciled': 'orange',
'Paused': 'orange',
'Reconciled': 'green',
'Failed': 'red',
'Cancelled': 'red',
'Running': 'blue',
"Partially Reconciled": "orange",
Paused: "orange",
Reconciled: "green",
Failed: "red",
Cancelled: "red",
Running: "blue",
};
let status = doc.status;
return [__(status), colors[status], "status,=,"+status];
return [__(status), colors[status], "status,=," + status];
},
};

View File

@@ -1,155 +1,150 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Process Statement Of Accounts', {
view_properties: function(frm) {
frappe.route_options = {doc_type: 'Customer'};
frappe.ui.form.on("Process Statement Of Accounts", {
view_properties: function (frm) {
frappe.route_options = { doc_type: "Customer" };
frappe.set_route("Form", "Customize Form");
},
refresh: function(frm){
if(!frm.doc.__islocal) {
frm.add_custom_button(__('Send Emails'), function(){
if (frm.is_dirty()) frappe.throw(__("Please save before proceeding."))
refresh: function (frm) {
if (!frm.doc.__islocal) {
frm.add_custom_button(__("Send Emails"), function () {
if (frm.is_dirty()) frappe.throw(__("Please save before proceeding."));
frappe.call({
method: "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_emails",
args: {
"document_name": frm.doc.name,
document_name: frm.doc.name,
},
callback: function(r) {
if(r && r.message) {
frappe.show_alert({message: __('Emails Queued'), indicator: 'blue'});
callback: function (r) {
if (r && r.message) {
frappe.show_alert({ message: __("Emails Queued"), indicator: "blue" });
} else {
frappe.msgprint(__("No Records for these settings."));
}
else{
frappe.msgprint(__('No Records for these settings.'))
}
}
},
});
});
frm.add_custom_button(__('Download'), function(){
if (frm.is_dirty()) frappe.throw(__("Please save before proceeding."))
frm.add_custom_button(__("Download"), function () {
if (frm.is_dirty()) frappe.throw(__("Please save before proceeding."));
let url = frappe.urllib.get_full_url(
'/api/method/erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.download_statements?'
+ 'document_name='+encodeURIComponent(frm.doc.name))
"/api/method/erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.download_statements?" +
"document_name=" +
encodeURIComponent(frm.doc.name)
);
$.ajax({
url: url,
type: 'GET',
success: function(result) {
if(jQuery.isEmptyObject(result)){
frappe.msgprint(__('No Records for these settings.'));
}
else{
type: "GET",
success: function (result) {
if (jQuery.isEmptyObject(result)) {
frappe.msgprint(__("No Records for these settings."));
} else {
window.location = url;
}
}
},
});
});
}
},
onload: function(frm) {
frm.set_query('currency', function(){
onload: function (frm) {
frm.set_query("currency", function () {
return {
filters: {
'enabled': 1
}
}
});
frm.set_query("account", function() {
return {
filters: {
'company': frm.doc.company
}
enabled: 1,
},
};
});
if(frm.doc.__islocal){
frm.set_value('from_date', frappe.datetime.add_months(frappe.datetime.get_today(), -1));
frm.set_value('to_date', frappe.datetime.get_today());
frm.set_query("account", function () {
return {
filters: {
company: frm.doc.company,
},
};
});
if (frm.doc.__islocal) {
frm.set_value("from_date", frappe.datetime.add_months(frappe.datetime.get_today(), -1));
frm.set_value("to_date", frappe.datetime.get_today());
}
},
report: function(frm){
report: function (frm) {
let filters = {
'company': frm.doc.company,
company: frm.doc.company,
};
if (frm.doc.report == "Accounts Receivable") {
filters["account_type"] = "Receivable";
}
if(frm.doc.report == 'Accounts Receivable'){
filters['account_type'] = 'Receivable';
}
frm.set_query("account", function() {
frm.set_query("account", function () {
return {
filters: filters
filters: filters,
};
});
},
customer_collection: function(frm){
frm.set_value('collection_name', '');
if(frm.doc.customer_collection){
frm.get_field('collection_name').set_label(frm.doc.customer_collection);
customer_collection: function (frm) {
frm.set_value("collection_name", "");
if (frm.doc.customer_collection) {
frm.get_field("collection_name").set_label(frm.doc.customer_collection);
}
},
frequency: function(frm){
if(frm.doc.frequency != ''){
frm.set_value('start_date', frappe.datetime.get_today());
}
else{
frm.set_value('start_date', '');
frequency: function (frm) {
if (frm.doc.frequency != "") {
frm.set_value("start_date", frappe.datetime.get_today());
} else {
frm.set_value("start_date", "");
}
},
fetch_customers: function(frm){
if(frm.doc.collection_name){
fetch_customers: function (frm) {
if (frm.doc.collection_name) {
frappe.call({
method: "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.fetch_customers",
args: {
'customer_collection': frm.doc.customer_collection,
'collection_name': frm.doc.collection_name,
'primary_mandatory': frm.doc.primary_mandatory
customer_collection: frm.doc.customer_collection,
collection_name: frm.doc.collection_name,
primary_mandatory: frm.doc.primary_mandatory,
},
callback: function(r) {
if(!r.exc) {
if(r.message.length){
frm.clear_table('customers');
for (const customer of r.message){
var row = frm.add_child('customers');
callback: function (r) {
if (!r.exc) {
if (r.message.length) {
frm.clear_table("customers");
for (const customer of r.message) {
var row = frm.add_child("customers");
row.customer = customer.name;
row.primary_email = customer.primary_email;
row.billing_email = customer.billing_email;
}
frm.refresh_field('customers');
}
else{
frappe.throw(__('No Customers found with selected options.'));
frm.refresh_field("customers");
} else {
frappe.throw(__("No Customers found with selected options."));
}
}
}
},
});
} else {
frappe.throw("Enter " + frm.doc.customer_collection + " name.");
}
else {
frappe.throw('Enter ' + frm.doc.customer_collection + ' name.');
}
}
},
});
frappe.ui.form.on('Process Statement Of Accounts Customer', {
customer: function(frm, cdt, cdn){
frappe.ui.form.on("Process Statement Of Accounts Customer", {
customer: function (frm, cdt, cdn) {
var row = locals[cdt][cdn];
if (!row.customer){
if (!row.customer) {
return;
}
frappe.call({
method: 'erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.get_customer_emails',
method: "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.get_customer_emails",
args: {
'customer_name': row.customer,
'primary_mandatory': frm.doc.primary_mandatory
customer_name: row.customer,
primary_mandatory: frm.doc.primary_mandatory,
},
callback: function(r){
if(!r.exe){
if(r.message.length){
frappe.model.set_value(cdt, cdn, "primary_email", r.message[0])
frappe.model.set_value(cdt, cdn, "billing_email", r.message[1])
}
else {
return
callback: function (r) {
if (!r.exe) {
if (r.message.length) {
frappe.model.set_value(cdt, cdn, "primary_email", r.message[0]);
frappe.model.set_value(cdt, cdn, "billing_email", r.message[1]);
} else {
return;
}
}
}
})
}
},
});
},
});

View File

@@ -455,11 +455,16 @@ def send_emails(document_name, from_scheduler=False, posting_date=None):
subject = frappe.render_template(doc.subject, context)
message = frappe.render_template(doc.body, context)
if doc.sender:
sender_email = frappe.db.get_value("Email Account", doc.sender, "email_id")
else:
sender_email = frappe.session.user
frappe.enqueue(
queue="short",
method=frappe.sendmail,
recipients=recipients,
sender=doc.sender or frappe.session.user,
sender=sender_email,
cc=cc,
subject=subject,
message=message,

View File

@@ -1,51 +1,56 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Promotional Scheme', {
refresh: function(frm) {
frappe.ui.form.on("Promotional Scheme", {
refresh: function (frm) {
frm.trigger("set_options_for_applicable_for");
frm.trigger("toggle_reqd_apply_on");
},
selling: function(frm) {
selling: function (frm) {
frm.trigger("set_options_for_applicable_for");
},
buying: function(frm) {
buying: function (frm) {
frm.trigger("set_options_for_applicable_for");
},
set_options_for_applicable_for: function(frm) {
set_options_for_applicable_for: function (frm) {
var options = [""];
var applicable_for = frm.doc.applicable_for;
if(frm.doc.selling) {
options = $.merge(options, ["Customer", "Customer Group", "Territory", "Sales Partner", "Campaign"]);
if (frm.doc.selling) {
options = $.merge(options, [
"Customer",
"Customer Group",
"Territory",
"Sales Partner",
"Campaign",
]);
}
if(frm.doc.buying) {
if (frm.doc.buying) {
$.merge(options, ["Supplier", "Supplier Group"]);
}
set_field_options("applicable_for", options.join("\n"));
if(!in_list(options, applicable_for)) applicable_for = null;
if (!in_list(options, applicable_for)) applicable_for = null;
frm.set_value("applicable_for", applicable_for);
},
apply_on: function(frm) {
apply_on: function (frm) {
frm.trigger("toggle_reqd_apply_on");
},
toggle_reqd_apply_on: function(frm) {
toggle_reqd_apply_on: function (frm) {
const fields = {
'Item Code': 'items',
'Item Group': 'item_groups',
'Brand': 'brands'
"Item Code": "items",
"Item Group": "item_groups",
Brand: "brands",
};
for (var key in fields) {
frm.toggle_reqd(fields[key],
frm.doc.apply_on === key ? 1 : 0);
frm.toggle_reqd(fields[key], frm.doc.apply_on === key ? 1 : 0);
}
}
},
});

View File

@@ -14,19 +14,19 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
super.setup(doc);
// formatter for purchase invoice item
if(this.frm.doc.update_stock) {
this.frm.set_indicator_formatter('item_code', function(doc) {
return (doc.qty<=doc.received_qty) ? "green" : "orange";
if (this.frm.doc.update_stock) {
this.frm.set_indicator_formatter("item_code", function (doc) {
return doc.qty <= doc.received_qty ? "green" : "orange";
});
}
this.frm.set_query("unrealized_profit_loss_account", function() {
this.frm.set_query("unrealized_profit_loss_account", function () {
return {
filters: {
company: doc.company,
is_group: 0,
root_type: "Liability",
}
},
};
});
}
@@ -35,11 +35,21 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
super.onload();
// Ignore linked advances
this.frm.ignore_doctypes_on_cancel_all = ['Journal Entry', 'Payment Entry', 'Purchase Invoice', "Repost Payment Ledger", "Repost Accounting Ledger", "Unreconcile Payment", "Unreconcile Payment Entries", "Serial and Batch Bundle", "Bank Transaction"];
this.frm.ignore_doctypes_on_cancel_all = [
"Journal Entry",
"Payment Entry",
"Purchase Invoice",
"Repost Payment Ledger",
"Repost Accounting Ledger",
"Unreconcile Payment",
"Unreconcile Payment Entries",
"Serial and Batch Bundle",
"Bank Transaction",
];
if(!this.frm.doc.__islocal) {
if (!this.frm.doc.__islocal) {
// show credit_to in print format
if(!this.frm.doc.supplier && this.frm.doc.credit_to) {
if (!this.frm.doc.supplier && this.frm.doc.credit_to) {
this.frm.set_df_property("credit_to", "print_hide", 0);
}
}
@@ -47,7 +57,7 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
// Trigger supplier event on load if supplier is available
// The reason for this is PI can be created from PR or PO and supplier is pre populated
if (this.frm.doc.supplier && this.frm.doc.__islocal) {
this.frm.trigger('supplier');
this.frm.trigger("supplier");
}
}
@@ -60,116 +70,137 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
this.show_general_ledger();
erpnext.accounts.ledger_preview.show_accounting_ledger_preview(this.frm);
if(doc.update_stock==1) {
if (doc.update_stock == 1) {
this.show_stock_ledger();
erpnext.accounts.ledger_preview.show_stock_ledger_preview(this.frm);
}
if (this.frm.doc.repost_required && this.frm.doc.docstatus===1) {
this.frm.set_intro(__("Accounting entries for this invoice need to be reposted. Please click on 'Repost' button to update."));
this.frm.add_custom_button(__('Repost Accounting Entries'),
() => {
if (this.frm.doc.repost_required && this.frm.doc.docstatus === 1) {
this.frm.set_intro(
__(
"Accounting entries for this invoice need to be reposted. Please click on 'Repost' button to update."
)
);
this.frm
.add_custom_button(__("Repost Accounting Entries"), () => {
this.frm.call({
doc: this.frm.doc,
method: 'repost_accounting_entries',
method: "repost_accounting_entries",
freeze: true,
freeze_message: __('Reposting...'),
freeze_message: __("Reposting..."),
callback: (r) => {
if (!r.exc) {
frappe.msgprint(__('Accounting Entries are reposted.'));
frappe.msgprint(__("Accounting Entries are reposted."));
me.frm.refresh();
}
}
},
});
}).removeClass('btn-default').addClass('btn-warning');
})
.removeClass("btn-default")
.addClass("btn-warning");
}
if(!doc.is_return && doc.docstatus == 1 && doc.outstanding_amount != 0){
if(doc.on_hold) {
if (!doc.is_return && doc.docstatus == 1 && doc.outstanding_amount != 0) {
if (doc.on_hold) {
this.frm.add_custom_button(
__('Change Release Date'),
function() {me.change_release_date()},
__('Hold Invoice')
__("Change Release Date"),
function () {
me.change_release_date();
},
__("Hold Invoice")
);
this.frm.add_custom_button(
__('Unblock Invoice'),
function() {me.unblock_invoice()},
__('Create')
__("Unblock Invoice"),
function () {
me.unblock_invoice();
},
__("Create")
);
} else if (!doc.on_hold) {
this.frm.add_custom_button(
__('Block Invoice'),
function() {me.block_invoice()},
__('Create')
__("Block Invoice"),
function () {
me.block_invoice();
},
__("Create")
);
}
}
if(doc.docstatus == 1 && doc.outstanding_amount != 0 && !doc.on_hold) {
this.frm.add_custom_button(
__('Payment'),
() => this.make_payment_entry(),
__('Create')
);
cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
if (doc.docstatus == 1 && doc.outstanding_amount != 0 && !doc.on_hold) {
this.frm.add_custom_button(__("Payment"), () => this.make_payment_entry(), __("Create"));
cur_frm.page.set_inner_btn_group_as_primary(__("Create"));
}
if(!doc.is_return && doc.docstatus==1) {
if(doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) {
cur_frm.add_custom_button(__('Return / Debit Note'),
this.make_debit_note, __('Create'));
if (!doc.is_return && doc.docstatus == 1) {
if (doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) {
cur_frm.add_custom_button(__("Return / Debit Note"), this.make_debit_note, __("Create"));
}
}
if (doc.outstanding_amount > 0 && !cint(doc.is_return) && !doc.on_hold) {
cur_frm.add_custom_button(__('Payment Request'), function() {
me.make_payment_request()
}, __('Create'));
cur_frm.add_custom_button(
__("Payment Request"),
function () {
me.make_payment_request();
},
__("Create")
);
}
if(doc.docstatus===0) {
this.frm.add_custom_button(__('Purchase Order'), function() {
erpnext.utils.map_current_doc({
method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice",
source_doctype: "Purchase Order",
target: me.frm,
setters: {
supplier: me.frm.doc.supplier || undefined,
schedule_date: undefined
},
get_query_filters: {
docstatus: 1,
status: ["not in", ["Closed", "On Hold"]],
per_billed: ["<", 99.99],
company: me.frm.doc.company
}
})
}, __("Get Items From"));
if (doc.docstatus === 0) {
this.frm.add_custom_button(
__("Purchase Order"),
function () {
erpnext.utils.map_current_doc({
method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice",
source_doctype: "Purchase Order",
target: me.frm,
setters: {
supplier: me.frm.doc.supplier || undefined,
schedule_date: undefined,
},
get_query_filters: {
docstatus: 1,
status: ["not in", ["Closed", "On Hold"]],
per_billed: ["<", 99.99],
company: me.frm.doc.company,
},
});
},
__("Get Items From")
);
this.frm.add_custom_button(__('Purchase Receipt'), function() {
erpnext.utils.map_current_doc({
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_invoice",
source_doctype: "Purchase Receipt",
target: me.frm,
setters: {
supplier: me.frm.doc.supplier || undefined,
posting_date: undefined
},
get_query_filters: {
docstatus: 1,
status: ["not in", ["Closed", "Completed", "Return Issued"]],
company: me.frm.doc.company,
is_return: 0
}
})
}, __("Get Items From"));
this.frm.add_custom_button(
__("Purchase Receipt"),
function () {
erpnext.utils.map_current_doc({
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_invoice",
source_doctype: "Purchase Receipt",
target: me.frm,
setters: {
supplier: me.frm.doc.supplier || undefined,
posting_date: undefined,
},
get_query_filters: {
docstatus: 1,
status: ["not in", ["Closed", "Completed", "Return Issued"]],
company: me.frm.doc.company,
is_return: 0,
},
});
},
__("Get Items From")
);
if (!this.frm.doc.is_return) {
frappe.db.get_single_value("Buying Settings", "maintain_same_rate").then((value) => {
if (value) {
this.frm.doc.items.forEach((item) => {
this.frm.fields_dict.items.grid.update_docfield_property(
"rate", "read_only", (item.purchase_receipt && item.pr_detail)
"rate",
"read_only",
item.purchase_receipt && item.pr_detail
);
});
}
@@ -179,14 +210,18 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted);
if (doc.docstatus == 1 && !doc.inter_company_invoice_reference) {
frappe.model.with_doc("Supplier", me.frm.doc.supplier, function() {
frappe.model.with_doc("Supplier", me.frm.doc.supplier, function () {
var supplier = frappe.model.get_doc("Supplier", me.frm.doc.supplier);
var internal = supplier.is_internal_supplier;
var disabled = supplier.disabled;
if (internal == 1 && disabled == 0) {
me.frm.add_custom_button("Inter Company Invoice", function() {
me.make_inter_company_invoice(me.frm);
}, __('Create'));
me.frm.add_custom_button(
"Inter Company Invoice",
function () {
me.make_inter_company_invoice(me.frm);
},
__("Create")
);
}
});
}
@@ -198,9 +233,9 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
unblock_invoice() {
const me = this;
frappe.call({
'method': 'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.unblock_invoice',
'args': {'name': me.frm.doc.name},
'callback': (r) => me.frm.reload_doc()
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.unblock_invoice",
args: { name: me.frm.doc.name },
callback: (r) => me.frm.reload_doc(),
});
}
@@ -215,50 +250,50 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
can_change_release_date(date) {
const diff = frappe.datetime.get_diff(date, frappe.datetime.nowdate());
if (diff < 0) {
frappe.throw(__('New release date should be in the future'));
frappe.throw(__("New release date should be in the future"));
return false;
} else {
return true;
}
}
make_comment_dialog_and_block_invoice(){
make_comment_dialog_and_block_invoice() {
const me = this;
const title = __('Block Invoice');
const title = __("Block Invoice");
const fields = [
{
fieldname: 'release_date',
fieldname: "release_date",
read_only: 0,
fieldtype:'Date',
label: __('Release Date'),
fieldtype: "Date",
label: __("Release Date"),
default: me.frm.doc.release_date,
reqd: 1
reqd: 1,
},
{
fieldname: 'hold_comment',
fieldname: "hold_comment",
read_only: 0,
fieldtype:'Small Text',
label: __('Reason For Putting On Hold'),
default: ""
fieldtype: "Small Text",
label: __("Reason For Putting On Hold"),
default: "",
},
];
this.dialog = new frappe.ui.Dialog({
title: title,
fields: fields
fields: fields,
});
this.dialog.set_primary_action(__('Save'), function() {
this.dialog.set_primary_action(__("Save"), function () {
const dialog_data = me.dialog.get_values();
frappe.call({
'method': 'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.block_invoice',
'args': {
'name': me.frm.doc.name,
'hold_comment': dialog_data.hold_comment,
'release_date': dialog_data.release_date
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.block_invoice",
args: {
name: me.frm.doc.name,
hold_comment: dialog_data.hold_comment,
release_date: dialog_data.release_date,
},
'callback': (r) => me.frm.reload_doc()
callback: (r) => me.frm.reload_doc(),
});
me.dialog.hide();
});
@@ -269,25 +304,25 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
make_dialog_and_set_release_date() {
const me = this;
const title = __('Set New Release Date');
const title = __("Set New Release Date");
const fields = [
{
fieldname: 'release_date',
fieldname: "release_date",
read_only: 0,
fieldtype:'Date',
label: __('Release Date'),
default: me.frm.doc.release_date
fieldtype: "Date",
label: __("Release Date"),
default: me.frm.doc.release_date,
},
];
this.dialog = new frappe.ui.Dialog({
title: title,
fields: fields
fields: fields,
});
this.dialog.set_primary_action(__('Save'), function() {
this.dialog.set_primary_action(__("Save"), function () {
me.dialog_data = me.dialog.get_values();
if(me.can_change_release_date(me.dialog_data.release_date)) {
if (me.can_change_release_date(me.dialog_data.release_date)) {
me.dialog_data.name = me.frm.doc.name;
me.set_release_date(me.dialog_data);
me.dialog.hide();
@@ -299,9 +334,9 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
set_release_date(data) {
return frappe.call({
'method': 'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.change_release_date',
'args': data,
'callback': (r) => this.frm.reload_doc()
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.change_release_date",
args: data,
callback: (r) => this.frm.reload_doc(),
});
}
@@ -309,12 +344,13 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
var me = this;
// Do not update if inter company reference is there as the details will already be updated
if(this.frm.updating_party_details || this.frm.doc.inter_company_invoice_reference)
return;
if (this.frm.updating_party_details || this.frm.doc.inter_company_invoice_reference) return;
if (this.frm.doc.__onload && this.frm.doc.__onload.load_after_mapping) return;
erpnext.utils.get_party_details(this.frm, "erpnext.accounts.party.get_party_details",
erpnext.utils.get_party_details(
this.frm,
"erpnext.accounts.party.get_party_details",
{
posting_date: this.frm.doc.posting_date,
bill_date: this.frm.doc.bill_date,
@@ -322,21 +358,23 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
party_type: "Supplier",
account: this.frm.doc.credit_to,
price_list: this.frm.doc.buying_price_list,
fetch_payment_terms_template: cint(!this.frm.doc.ignore_default_payment_terms_template)
}, function() {
fetch_payment_terms_template: cint(!this.frm.doc.ignore_default_payment_terms_template),
},
function () {
me.apply_pricing_rule();
me.frm.doc.apply_tds = me.frm.supplier_tds ? 1 : 0;
me.frm.doc.tax_withholding_category = me.frm.supplier_tds;
me.frm.set_df_property("apply_tds", "read_only", me.frm.supplier_tds ? 0 : 1);
me.frm.set_df_property("tax_withholding_category", "hidden", me.frm.supplier_tds ? 0 : 1);
})
}
);
}
apply_tds(frm) {
var me = this;
me.frm.set_value("tax_withheld_vouchers", []);
if (!me.frm.doc.apply_tds) {
me.frm.set_value("tax_withholding_category", '');
me.frm.set_value("tax_withholding_category", "");
me.frm.set_df_property("tax_withholding_category", "hidden", 1);
} else {
me.frm.set_value("tax_withholding_category", me.frm.supplier_tds);
@@ -346,7 +384,7 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
credit_to() {
var me = this;
if(this.frm.doc.credit_to) {
if (this.frm.doc.credit_to) {
me.frm.call({
method: "frappe.client.get_value",
args: {
@@ -354,12 +392,12 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
fieldname: "account_currency",
filters: { name: me.frm.doc.credit_to },
},
callback: function(r, rt) {
if(r.message) {
callback: function (r, rt) {
if (r.message) {
me.frm.set_value("party_account_currency", r.message.account_currency);
me.set_dynamic_labels();
}
}
},
});
}
}
@@ -367,16 +405,16 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
make_inter_company_invoice(frm) {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_inter_company_sales_invoice",
frm: frm
frm: frm,
});
}
is_paid() {
hide_fields(this.frm.doc);
if(cint(this.frm.doc.is_paid)) {
if (cint(this.frm.doc.is_paid)) {
this.frm.set_value("allocate_advances_automatically", 0);
if(!this.frm.doc.company) {
this.frm.set_value("is_paid", 0)
if (!this.frm.doc.company) {
this.frm.set_value("is_paid", 0);
frappe.msgprint(__("Please specify Company to proceed"));
}
}
@@ -403,23 +441,27 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
items_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
this.frm.script_manager.copy_from_first_row("items", row,
["expense_account", "discount_account", "cost_center", "project"]);
this.frm.script_manager.copy_from_first_row("items", row, [
"expense_account",
"discount_account",
"cost_center",
"project",
]);
}
on_submit() {
super.on_submit();
$.each(this.frm.doc["items"] || [], function(i, row) {
if(row.purchase_receipt) frappe.model.clear_doc("Purchase Receipt", row.purchase_receipt)
})
$.each(this.frm.doc["items"] || [], function (i, row) {
if (row.purchase_receipt) frappe.model.clear_doc("Purchase Receipt", row.purchase_receipt);
});
}
make_debit_note() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_debit_note",
frm: cur_frm
})
frm: cur_frm,
});
}
};
@@ -428,172 +470,170 @@ cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice);
// Hide Fields
// ------------
function hide_fields(doc) {
var parent_fields = ['due_date', 'is_opening', 'advances_section', 'from_date', 'to_date'];
var parent_fields = ["due_date", "is_opening", "advances_section", "from_date", "to_date"];
if(cint(doc.is_paid) == 1) {
if (cint(doc.is_paid) == 1) {
hide_field(parent_fields);
} else {
for (var i in parent_fields) {
var docfield = frappe.meta.docfield_map[doc.doctype][parent_fields[i]];
if(!docfield.hidden) unhide_field(parent_fields[i]);
if (!docfield.hidden) unhide_field(parent_fields[i]);
}
}
var item_fields_stock = ['warehouse_section', 'received_qty', 'rejected_qty'];
var item_fields_stock = ["warehouse_section", "received_qty", "rejected_qty"];
cur_frm.fields_dict['items'].grid.set_column_disp(item_fields_stock,
(cint(doc.update_stock)==1 || cint(doc.is_return)==1 ? true : false));
cur_frm.fields_dict["items"].grid.set_column_disp(
item_fields_stock,
cint(doc.update_stock) == 1 || cint(doc.is_return) == 1 ? true : false
);
cur_frm.refresh_fields();
}
cur_frm.fields_dict.cash_bank_account.get_query = function(doc) {
cur_frm.fields_dict.cash_bank_account.get_query = function (doc) {
return {
filters: [
["Account", "account_type", "in", ["Cash", "Bank"]],
["Account", "is_group", "=",0],
["Account", "is_group", "=", 0],
["Account", "company", "=", doc.company],
["Account", "report_type", "=", "Balance Sheet"]
]
}
}
["Account", "report_type", "=", "Balance Sheet"],
],
};
};
cur_frm.fields_dict['items'].grid.get_field("item_code").get_query = function(doc, cdt, cdn) {
cur_frm.fields_dict["items"].grid.get_field("item_code").get_query = function (doc, cdt, cdn) {
return {
query: "erpnext.controllers.queries.item_query",
filters: {'is_purchase_item': 1}
}
}
filters: { is_purchase_item: 1 },
};
};
cur_frm.fields_dict['credit_to'].get_query = function(doc) {
cur_frm.fields_dict["credit_to"].get_query = function (doc) {
// filter on Account
return {
filters: {
'account_type': 'Payable',
'is_group': 0,
'company': doc.company
}
}
}
account_type: "Payable",
is_group: 0,
company: doc.company,
},
};
};
// Get Print Heading
cur_frm.fields_dict['select_print_heading'].get_query = function(doc, cdt, cdn) {
cur_frm.fields_dict["select_print_heading"].get_query = function (doc, cdt, cdn) {
return {
filters:[
['Print Heading', 'docstatus', '!=', 2]
]
}
}
filters: [["Print Heading", "docstatus", "!=", 2]],
};
};
cur_frm.set_query("expense_account", "items", function(doc) {
cur_frm.set_query("expense_account", "items", function (doc) {
return {
query: "erpnext.controllers.queries.get_expense_account",
filters: {'company': doc.company }
}
filters: { company: doc.company },
};
});
cur_frm.set_query("wip_composite_asset", "items", function() {
cur_frm.set_query("wip_composite_asset", "items", function () {
return {
filters: {'is_composite_asset': 1, 'docstatus': 0 }
}
filters: { is_composite_asset: 1, docstatus: 0 },
};
});
cur_frm.cscript.expense_account = function(doc, cdt, cdn){
cur_frm.cscript.expense_account = function (doc, cdt, cdn) {
var d = locals[cdt][cdn];
if(d.idx == 1 && d.expense_account){
if (d.idx == 1 && d.expense_account) {
var cl = doc.items || [];
for(var i = 0; i < cl.length; i++){
if(!cl[i].expense_account) cl[i].expense_account = d.expense_account;
for (var i = 0; i < cl.length; i++) {
if (!cl[i].expense_account) cl[i].expense_account = d.expense_account;
}
}
refresh_field('items');
}
refresh_field("items");
};
cur_frm.fields_dict["items"].grid.get_field("cost_center").get_query = function(doc) {
cur_frm.fields_dict["items"].grid.get_field("cost_center").get_query = function (doc) {
return {
filters: {
'company': doc.company,
'is_group': 0
}
company: doc.company,
is_group: 0,
},
};
};
}
}
cur_frm.cscript.cost_center = function(doc, cdt, cdn){
cur_frm.cscript.cost_center = function (doc, cdt, cdn) {
var d = locals[cdt][cdn];
if(d.cost_center){
if (d.cost_center) {
var cl = doc.items || [];
for(var i = 0; i < cl.length; i++){
if(!cl[i].cost_center) cl[i].cost_center = d.cost_center;
for (var i = 0; i < cl.length; i++) {
if (!cl[i].cost_center) cl[i].cost_center = d.cost_center;
}
}
refresh_field('items');
}
refresh_field("items");
};
cur_frm.fields_dict['items'].grid.get_field('project').get_query = function(doc, cdt, cdn) {
return{
filters:[
['Project', 'status', 'not in', 'Completed, Cancelled']
]
}
}
cur_frm.fields_dict["items"].grid.get_field("project").get_query = function (doc, cdt, cdn) {
return {
filters: [["Project", "status", "not in", "Completed, Cancelled"]],
};
};
frappe.ui.form.on("Purchase Invoice", {
setup: function(frm) {
setup: function (frm) {
frm.custom_make_buttons = {
'Purchase Invoice': 'Return / Debit Note',
'Payment Entry': 'Payment',
'Landed Cost Voucher': function () { frm.trigger('create_landed_cost_voucher') },
}
"Purchase Invoice": "Return / Debit Note",
"Payment Entry": "Payment",
"Landed Cost Voucher": function () {
frm.trigger("create_landed_cost_voucher");
},
};
frm.set_query("additional_discount_account", function() {
frm.set_query("additional_discount_account", function () {
return {
filters: {
company: frm.doc.company,
is_group: 0,
report_type: "Profit and Loss",
}
},
};
});
frm.fields_dict['items'].grid.get_field('deferred_expense_account').get_query = function(doc) {
frm.fields_dict["items"].grid.get_field("deferred_expense_account").get_query = function (doc) {
return {
filters: {
'root_type': 'Asset',
'company': doc.company,
"is_group": 0
}
}
}
root_type: "Asset",
company: doc.company,
is_group: 0,
},
};
};
frm.fields_dict['items'].grid.get_field('discount_account').get_query = function(doc) {
frm.fields_dict["items"].grid.get_field("discount_account").get_query = function (doc) {
return {
filters: {
'report_type': 'Profit and Loss',
'company': doc.company,
"is_group": 0
}
}
}
report_type: "Profit and Loss",
company: doc.company,
is_group: 0,
},
};
};
},
refresh: function(frm) {
refresh: function (frm) {
frm.events.add_custom_buttons(frm);
},
mode_of_payment: function(frm) {
erpnext.accounts.pos.get_payment_mode_account(frm, frm.doc.mode_of_payment, function(account) {
mode_of_payment: function (frm) {
erpnext.accounts.pos.get_payment_mode_account(frm, frm.doc.mode_of_payment, function (account) {
frm.set_value("cash_bank_account", account);
})
});
},
create_landed_cost_voucher: function (frm) {
let lcv = frappe.model.get_new_doc('Landed Cost Voucher');
let lcv = frappe.model.get_new_doc("Landed Cost Voucher");
lcv.company = frm.doc.company;
let lcv_receipt = frappe.model.get_new_doc('Landed Cost Purchase Invoice');
lcv_receipt.receipt_document_type = 'Purchase Invoice';
let lcv_receipt = frappe.model.get_new_doc("Landed Cost Purchase Invoice");
lcv_receipt.receipt_document_type = "Purchase Invoice";
lcv_receipt.receipt_document = frm.doc.name;
lcv_receipt.supplier = frm.doc.supplier;
lcv_receipt.grand_total = frm.doc.grand_total;
@@ -602,35 +642,43 @@ frappe.ui.form.on("Purchase Invoice", {
frappe.set_route("Form", lcv.doctype, lcv.name);
},
add_custom_buttons: function(frm) {
add_custom_buttons: function (frm) {
if (frm.doc.docstatus == 1 && frm.doc.per_received < 100) {
frm.add_custom_button(__('Purchase Receipt'), () => {
frm.events.make_purchase_receipt(frm);
}, __('Create'));
frm.add_custom_button(
__("Purchase Receipt"),
() => {
frm.events.make_purchase_receipt(frm);
},
__("Create")
);
}
if (frm.doc.docstatus == 1 && frm.doc.per_received > 0) {
frm.add_custom_button(__('Purchase Receipt'), () => {
frappe.route_options = {
'purchase_invoice': frm.doc.name
}
frm.add_custom_button(
__("Purchase Receipt"),
() => {
frappe.route_options = {
purchase_invoice: frm.doc.name,
};
frappe.set_route("List", "Purchase Receipt", "List")
}, __('View'));
frappe.set_route("List", "Purchase Receipt", "List");
},
__("View")
);
}
},
onload: function(frm) {
if(frm.doc.__onload && frm.is_new()) {
if(frm.doc.supplier) {
onload: function (frm) {
if (frm.doc.__onload && frm.is_new()) {
if (frm.doc.supplier) {
frm.doc.apply_tds = frm.doc.__onload.supplier_tds ? 1 : 0;
}
if(!frm.doc.__onload.supplier_tds) {
if (!frm.doc.__onload.supplier_tds) {
frm.set_df_property("apply_tds", "read_only", 1);
}
}
erpnext.queries.setup_queries(frm, "Warehouse", function() {
erpnext.queries.setup_queries(frm, "Warehouse", function () {
return erpnext.queries.warehouse(frm.doc);
});
@@ -639,7 +687,7 @@ frappe.ui.form.on("Purchase Invoice", {
}
},
is_subcontracted: function(frm) {
is_subcontracted: function (frm) {
if (frm.doc.is_old_subcontracting_flow) {
erpnext.buying.get_default_bom(frm);
}
@@ -647,30 +695,29 @@ frappe.ui.form.on("Purchase Invoice", {
frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted);
},
update_stock: function(frm) {
update_stock: function (frm) {
hide_fields(frm.doc);
frm.fields_dict.items.grid.toggle_reqd("item_code", frm.doc.update_stock? true: false);
frm.fields_dict.items.grid.toggle_reqd("item_code", frm.doc.update_stock ? true : false);
},
make_purchase_receipt: function(frm) {
make_purchase_receipt: function (frm) {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_purchase_receipt",
frm: frm,
freeze_message: __("Creating Purchase Receipt ...")
})
freeze_message: __("Creating Purchase Receipt ..."),
});
},
company: function(frm) {
company: function (frm) {
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
if (frm.doc.company) {
frappe.call({
method:
"erpnext.accounts.party.get_party_account",
method: "erpnext.accounts.party.get_party_account",
args: {
party_type: 'Supplier',
party_type: "Supplier",
party: frm.doc.supplier,
company: frm.doc.company
company: frm.doc.company,
},
callback: (response) => {
if (response) frm.set_value("credit_to", response.message);
@@ -678,4 +725,4 @@ frappe.ui.form.on("Purchase Invoice", {
});
}
},
})
});

View File

@@ -22,48 +22,35 @@ frappe.listview_settings["Purchase Invoice"] = {
return [__(doc.status), "gray", "status,=," + doc.status];
}
if (
flt(doc.outstanding_amount) > 0 &&
doc.docstatus == 1 &&
cint(doc.on_hold)
) {
if (flt(doc.outstanding_amount) > 0 && doc.docstatus == 1 && cint(doc.on_hold)) {
if (!doc.release_date) {
return [__("On Hold"), "darkgrey"];
} else if (
frappe.datetime.get_diff(
doc.release_date,
frappe.datetime.nowdate()
) > 0
) {
} else if (frappe.datetime.get_diff(doc.release_date, frappe.datetime.nowdate()) > 0) {
return [__("Temporarily on Hold"), "darkgrey"];
}
}
const status_colors = {
"Unpaid": "orange",
"Paid": "green",
"Return": "gray",
"Overdue": "red",
Unpaid: "orange",
Paid: "green",
Return: "gray",
Overdue: "red",
"Partly Paid": "yellow",
"Internal Transfer": "darkgrey",
};
if (status_colors[doc.status]) {
return [
__(doc.status),
status_colors[doc.status],
"status,=," + doc.status,
];
return [__(doc.status), status_colors[doc.status], "status,=," + doc.status];
}
},
onload: function(listview) {
listview.page.add_action_item(__("Purchase Receipt"), ()=>{
onload: function (listview) {
listview.page.add_action_item(__("Purchase Receipt"), () => {
erpnext.bulk_transaction_processing.create(listview, "Purchase Invoice", "Purchase Receipt");
});
listview.page.add_action_item(__("Payment"), ()=>{
listview.page.add_action_item(__("Payment"), () => {
erpnext.bulk_transaction_processing.create(listview, "Purchase Invoice", "Payment Entry");
});
}
},
};

View File

@@ -8,24 +8,23 @@ frappe.ui.form.on("Purchase Taxes and Charges", {
add_deduct_tax(doc, cdt, cdn) {
let d = locals[cdt][cdn];
if(!d.category && d.add_deduct_tax) {
if (!d.category && d.add_deduct_tax) {
frappe.msgprint(__("Please select Category first"));
d.add_deduct_tax = '';
}
else if(d.category != 'Total' && d.add_deduct_tax == 'Deduct') {
d.add_deduct_tax = "";
} else if (d.category != "Total" && d.add_deduct_tax == "Deduct") {
frappe.msgprint(__("Cannot deduct when category is for 'Valuation' or 'Valuation and Total'"));
d.add_deduct_tax = '';
d.add_deduct_tax = "";
}
refresh_field('add_deduct_tax', d.name, 'taxes');
refresh_field("add_deduct_tax", d.name, "taxes");
},
category(doc, cdt, cdn) {
let d = locals[cdt][cdn];
if(d.category != 'Total' && d.add_deduct_tax == 'Deduct') {
if (d.category != "Total" && d.add_deduct_tax == "Deduct") {
frappe.msgprint(__("Cannot deduct when category is for 'Valuation' or 'Valuation and Total'"));
d.add_deduct_tax = '';
d.add_deduct_tax = "";
}
refresh_field('add_deduct_tax', d.name, 'taxes');
}
refresh_field("add_deduct_tax", d.name, "taxes");
},
});

View File

@@ -2,47 +2,47 @@
// For license information, please see license.txt
frappe.ui.form.on("Repost Accounting Ledger", {
setup: function(frm) {
frm.fields_dict['vouchers'].grid.get_field('voucher_type').get_query = function(doc) {
setup: function (frm) {
frm.fields_dict["vouchers"].grid.get_field("voucher_type").get_query = function (doc) {
return {
query: "erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger.get_repost_allowed_types"
}
}
query: "erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger.get_repost_allowed_types",
};
};
frm.fields_dict['vouchers'].grid.get_field('voucher_no').get_query = function(doc) {
frm.fields_dict["vouchers"].grid.get_field("voucher_no").get_query = function (doc) {
if (doc.company) {
return {
filters: {
company: doc.company,
docstatus: 1
}
}
docstatus: 1,
},
};
}
}
};
},
refresh: function(frm) {
frm.add_custom_button(__('Show Preview'), () => {
refresh: function (frm) {
frm.add_custom_button(__("Show Preview"), () => {
frm.call({
method: 'generate_preview',
method: "generate_preview",
doc: frm.doc,
freeze: true,
freeze_message: __('Generating Preview'),
callback: function(r) {
freeze_message: __("Generating Preview"),
callback: function (r) {
if (r && r.message) {
let content = r.message;
let opts = {
title: "Preview",
subtitle: "preview",
content: content,
print_settings: {orientation: "landscape"},
print_settings: { orientation: "landscape" },
columns: [],
data: [],
}
};
frappe.render_grid(opts);
}
}
},
});
});
}
},
});

View File

@@ -1,53 +1,53 @@
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Repost Payment Ledger', {
setup: function(frm) {
frappe.ui.form.on("Repost Payment Ledger", {
setup: function (frm) {
frm.set_query("voucher_type", () => {
return {
filters: {
name: ['in', ['Purchase Invoice', 'Sales Invoice', 'Payment Entry', 'Journal Entry']]
}
name: ["in", ["Purchase Invoice", "Sales Invoice", "Payment Entry", "Journal Entry"]],
},
};
});
frm.fields_dict['repost_vouchers'].grid.get_field('voucher_type').get_query = function(doc) {
frm.fields_dict["repost_vouchers"].grid.get_field("voucher_type").get_query = function (doc) {
return {
filters: {
name: ['in', ['Purchase Invoice', 'Sales Invoice', 'Payment Entry', 'Journal Entry']]
}
}
}
name: ["in", ["Purchase Invoice", "Sales Invoice", "Payment Entry", "Journal Entry"]],
},
};
};
frm.fields_dict['repost_vouchers'].grid.get_field('voucher_no').get_query = function(doc) {
frm.fields_dict["repost_vouchers"].grid.get_field("voucher_no").get_query = function (doc) {
if (doc.company) {
return {
filters: {
company: doc.company,
docstatus: 1
}
}
docstatus: 1,
},
};
}
}
};
},
refresh: function(frm) {
if (frm.doc.docstatus==1 && ['Queued', 'Failed'].find(x => x == frm.doc.repost_status)) {
frm.set_intro(__("Use 'Repost in background' button to trigger background job. Job can only be triggered when document is in Queued or Failed status."));
var btn_label = __("Repost in background")
refresh: function (frm) {
if (frm.doc.docstatus == 1 && ["Queued", "Failed"].find((x) => x == frm.doc.repost_status)) {
frm.set_intro(
__(
"Use 'Repost in background' button to trigger background job. Job can only be triggered when document is in Queued or Failed status."
)
);
var btn_label = __("Repost in background");
frm.add_custom_button(btn_label, () => {
frappe.call({
method: 'erpnext.accounts.doctype.repost_payment_ledger.repost_payment_ledger.execute_repost_payment_ledger',
method: "erpnext.accounts.doctype.repost_payment_ledger.repost_payment_ledger.execute_repost_payment_ledger",
args: {
docname: frm.doc.name,
}
},
});
frappe.msgprint(__('Reposting in the background.'));
frappe.msgprint(__("Reposting in the background."));
});
}
}
},
});

View File

@@ -1,12 +1,12 @@
frappe.listview_settings["Repost Payment Ledger"] = {
add_fields: ["repost_status"],
get_indicator: function(doc) {
get_indicator: function (doc) {
var colors = {
'Queued': 'orange',
'Completed': 'green',
'Failed': 'red',
Queued: "orange",
Completed: "green",
Failed: "red",
};
let status = doc.repost_status;
return [__(status), colors[status], 'status,=,'+status];
return [__(status), colors[status], "status,=," + status];
},
};

View File

@@ -1,23 +1,23 @@
frappe.ui.form.on("Sales Invoice", {
refresh: (frm) => {
if(frm.doc.docstatus == 1) {
frm.add_custom_button(__('Generate E-Invoice'), () => {
frm.call({
method: "erpnext.regional.italy.utils.generate_single_invoice",
args: {
docname: frm.doc.name
},
callback: function(r) {
frm.reload_doc();
if(r.message) {
open_url_post(frappe.request.url, {
cmd: 'frappe.core.doctype.file.file.download_file',
file_url: r.message
});
}
}
});
});
}
}
});
refresh: (frm) => {
if (frm.doc.docstatus == 1) {
frm.add_custom_button(__("Generate E-Invoice"), () => {
frm.call({
method: "erpnext.regional.italy.utils.generate_single_invoice",
args: {
docname: frm.doc.name,
},
callback: function (r) {
frm.reload_doc();
if (r.message) {
open_url_post(frappe.request.url, {
cmd: "frappe.core.doctype.file.file.download_file",
file_url: r.message,
});
}
},
});
});
}
},
});

File diff suppressed because it is too large Load Diff

View File

@@ -785,6 +785,7 @@
"hide_days": 1,
"hide_seconds": 1,
"label": "Time Sheets",
"no_copy": 1,
"options": "Sales Invoice Timesheet",
"print_hide": 1
},
@@ -2182,7 +2183,7 @@
"link_fieldname": "consolidated_invoice"
}
],
"modified": "2024-01-02 17:25:46.027523",
"modified": "2024-03-01 09:21:54.201289",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -8,6 +8,7 @@ from frappe.contacts.doctype.address.address import get_address_display
from frappe.model.mapper import get_mapped_doc
from frappe.model.utils import get_fetch_values
from frappe.utils import add_days, cint, cstr, flt, formatdate, get_link_to_form, getdate, nowdate
from frappe.utils.data import comma_and
import erpnext
from erpnext.accounts.deferred_revenue import validate_service_stop_date
@@ -27,7 +28,6 @@ from erpnext.accounts.party import get_due_date, get_party_account, get_party_de
from erpnext.accounts.utils import cancel_exchange_gain_loss_journal, get_account_currency
from erpnext.assets.doctype.asset.depreciation import (
depreciate_asset,
get_disposal_account_and_cost_center,
get_gl_entries_on_asset_disposal,
get_gl_entries_on_asset_regain,
reset_depreciation_schedule,
@@ -39,7 +39,6 @@ from erpnext.controllers.selling_controller import SellingController
from erpnext.projects.doctype.timesheet.timesheet import get_projectwise_timesheet_data
from erpnext.setup.doctype.company.company import update_company_current_month_sales
from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so
from erpnext.stock.doctype.serial_no.serial_no import get_delivery_note_serial_no, get_serial_nos
form_grid_templates = {"items": "templates/form_grid/item_grid.html"}
@@ -297,11 +296,13 @@ class SalesInvoice(SellingController):
if cint(self.is_pos):
self.validate_pos()
self.validate_dropship_item()
if cint(self.update_stock):
self.validate_dropship_item()
self.validate_warehouse()
self.update_current_stock()
self.validate_delivery_note()
self.validate_delivery_note()
# validate service stop date to lie in between start and end date
validate_service_stop_date(self)
@@ -379,13 +380,7 @@ class SalesInvoice(SellingController):
def validate_item_cost_centers(self):
for item in self.items:
cost_center_company = frappe.get_cached_value("Cost Center", item.cost_center, "company")
if cost_center_company != self.company:
frappe.throw(
_("Row #{0}: Cost Center {1} does not belong to company {2}").format(
frappe.bold(item.idx), frappe.bold(item.cost_center), frappe.bold(self.company)
)
)
item.validate_cost_center(self.company)
def validate_income_account(self):
for item in self.get("items"):
@@ -601,43 +596,48 @@ class SalesInvoice(SellingController):
self.delete_auto_created_batches()
def update_status_updater_args(self):
if cint(self.update_stock):
self.status_updater.append(
{
"source_dt": "Sales Invoice Item",
"target_dt": "Sales Order Item",
"target_parent_dt": "Sales Order",
"target_parent_field": "per_delivered",
"target_field": "delivered_qty",
"target_ref_field": "qty",
"source_field": "qty",
"join_field": "so_detail",
"percent_join_field": "sales_order",
"status_field": "delivery_status",
"keyword": "Delivered",
"second_source_dt": "Delivery Note Item",
"second_source_field": "qty",
"second_join_field": "so_detail",
"overflow_type": "delivery",
"extra_cond": """ and exists(select name from `tabSales Invoice`
where name=`tabSales Invoice Item`.parent and update_stock = 1)""",
}
)
if cint(self.is_return):
self.status_updater.append(
{
"source_dt": "Sales Invoice Item",
"target_dt": "Sales Order Item",
"join_field": "so_detail",
"target_field": "returned_qty",
"target_parent_dt": "Sales Order",
"source_field": "-1 * qty",
"second_source_dt": "Delivery Note Item",
"second_source_field": "-1 * qty",
"second_join_field": "so_detail",
"extra_cond": """ and exists (select name from `tabSales Invoice` where name=`tabSales Invoice Item`.parent and update_stock=1 and is_return=1)""",
}
)
if not cint(self.update_stock):
return
self.status_updater.append(
{
"source_dt": "Sales Invoice Item",
"target_dt": "Sales Order Item",
"target_parent_dt": "Sales Order",
"target_parent_field": "per_delivered",
"target_field": "delivered_qty",
"target_ref_field": "qty",
"source_field": "qty",
"join_field": "so_detail",
"percent_join_field": "sales_order",
"status_field": "delivery_status",
"keyword": "Delivered",
"second_source_dt": "Delivery Note Item",
"second_source_field": "qty",
"second_join_field": "so_detail",
"overflow_type": "delivery",
"extra_cond": """ and exists(select name from `tabSales Invoice`
where name=`tabSales Invoice Item`.parent and update_stock = 1)""",
}
)
if not cint(self.is_return):
return
self.status_updater.append(
{
"source_dt": "Sales Invoice Item",
"target_dt": "Sales Order Item",
"join_field": "so_detail",
"target_field": "returned_qty",
"target_parent_dt": "Sales Order",
"source_field": "-1 * qty",
"second_source_dt": "Delivery Note Item",
"second_source_field": "-1 * qty",
"second_join_field": "so_detail",
"extra_cond": """ and exists (select name from `tabSales Invoice` where name=`tabSales Invoice Item`.parent and update_stock=1 and is_return=1)""",
}
)
def check_credit_limit(self):
from erpnext.selling.doctype.customer.customer import check_credit_limit
@@ -662,13 +662,8 @@ class SalesInvoice(SellingController):
def unlink_sales_invoice_from_timesheets(self):
for row in self.timesheets:
timesheet = frappe.get_doc("Timesheet", row.time_sheet)
for time_log in timesheet.time_logs:
if time_log.sales_invoice == self.name:
time_log.sales_invoice = None
timesheet.calculate_total_amounts()
timesheet.calculate_percentage_billed()
timesheet.unlink_sales_invoice(self.name)
timesheet.flags.ignore_validate_update_after_submit = True
timesheet.set_status()
timesheet.db_update_all()
@frappe.whitelist()
@@ -1011,12 +1006,17 @@ class SalesInvoice(SellingController):
frappe.throw(_("Warehouse required for stock Item {0}").format(d.item_code))
def validate_delivery_note(self):
for d in self.get("items"):
if d.delivery_note:
msgprint(
_("Stock cannot be updated against Delivery Note {0}").format(d.delivery_note),
raise_exception=1,
)
"""If items are linked with a delivery note, stock cannot be updated again."""
if not cint(self.update_stock):
return
notes = [item.delivery_note for item in self.items if item.delivery_note]
if notes:
frappe.throw(
_("Stock cannot be updated against the following Delivery Notes: {0}").format(
comma_and(notes)
),
)
def validate_write_off_account(self):
if flt(self.write_off_amount) and not self.write_off_account:
@@ -1030,29 +1030,23 @@ class SalesInvoice(SellingController):
msgprint(_("Please enter Account for Change Amount"), raise_exception=1)
def validate_dropship_item(self):
for item in self.items:
if item.sales_order:
if frappe.db.get_value("Sales Order Item", item.so_detail, "delivered_by_supplier"):
frappe.throw(_("Could not update stock, invoice contains drop shipping item."))
"""If items are drop shipped, stock cannot be updated."""
if not cint(self.update_stock):
return
if any(item.delivered_by_supplier for item in self.items):
frappe.throw(
_(
"Stock cannot be updated because the invoice contains a drop shipping item. Please disable 'Update Stock' or remove the drop shipping item."
),
)
def update_current_stock(self):
for d in self.get("items"):
if d.item_code and d.warehouse:
bin = frappe.db.sql(
"select actual_qty from `tabBin` where item_code = %s and warehouse = %s",
(d.item_code, d.warehouse),
as_dict=1,
)
d.actual_qty = bin and flt(bin[0]["actual_qty"]) or 0
for item in self.items:
item.set_actual_qty()
for d in self.get("packed_items"):
bin = frappe.db.sql(
"select actual_qty, projected_qty from `tabBin` where item_code = %s and warehouse = %s",
(d.item_code, d.warehouse),
as_dict=1,
)
d.actual_qty = bin and flt(bin[0]["actual_qty"]) or 0
d.projected_qty = bin and flt(bin[0]["projected_qty"]) or 0
for packed_item in self.packed_items:
packed_item.set_actual_and_projected_qty()
def update_packing_list(self):
if cint(self.update_stock) == 1:
@@ -1127,17 +1121,8 @@ class SalesInvoice(SellingController):
return warehouse
def set_income_account_for_fixed_assets(self):
disposal_account = depreciation_cost_center = None
for d in self.get("items"):
if d.is_fixed_asset:
if not disposal_account:
disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(
self.company
)
d.income_account = disposal_account
if not d.cost_center:
d.cost_center = depreciation_cost_center
for item in self.items:
item.set_income_account_for_fixed_asset(self.company)
def check_prev_docstatus(self):
for d in self.get("items"):
@@ -1510,47 +1495,46 @@ class SalesInvoice(SellingController):
)
if not skip_change_gl_entries:
self.make_gle_for_change_amount(gl_entries)
gl_entries.extend(self.get_gle_for_change_amount())
def make_gle_for_change_amount(self, gl_entries):
if self.change_amount:
if self.account_for_change_amount:
gl_entries.append(
self.get_gl_dict(
{
"account": self.debit_to,
"party_type": "Customer",
"party": self.customer,
"against": self.account_for_change_amount,
"debit": flt(self.base_change_amount),
"debit_in_account_currency": flt(self.base_change_amount)
if self.party_account_currency == self.company_currency
else flt(self.change_amount),
"against_voucher": self.return_against
if cint(self.is_return) and self.return_against
else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center,
"project": self.project,
},
self.party_account_currency,
item=self,
)
)
def get_gle_for_change_amount(self) -> list[dict]:
if not self.change_amount:
return []
gl_entries.append(
self.get_gl_dict(
{
"account": self.account_for_change_amount,
"against": self.customer,
"credit": self.base_change_amount,
"cost_center": self.cost_center,
},
item=self,
)
)
else:
frappe.throw(_("Select change amount account"), title=_("Mandatory Field"))
if not self.account_for_change_amount:
frappe.throw(_("Please set Account for Change Amount"), title=_("Mandatory Field"))
return [
self.get_gl_dict(
{
"account": self.debit_to,
"party_type": "Customer",
"party": self.customer,
"against": self.account_for_change_amount,
"debit": flt(self.base_change_amount),
"debit_in_account_currency": flt(self.base_change_amount)
if self.party_account_currency == self.company_currency
else flt(self.change_amount),
"against_voucher": self.return_against
if cint(self.is_return) and self.return_against
else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center,
"project": self.project,
},
self.party_account_currency,
item=self,
),
self.get_gl_dict(
{
"account": self.account_for_change_amount,
"against": self.customer,
"credit": self.base_change_amount,
"cost_center": self.cost_center,
},
item=self,
),
]
def make_write_off_gl_entry(self, gl_entries):
# write off entries, applicable if only pos
@@ -1659,48 +1643,9 @@ class SalesInvoice(SellingController):
"""
validate serial number agains Delivery Note and Sales Invoice
"""
self.set_serial_no_against_delivery_note()
self.validate_serial_against_delivery_note()
def set_serial_no_against_delivery_note(self):
for item in self.items:
if item.serial_no and item.delivery_note and item.qty != len(get_serial_nos(item.serial_no)):
item.serial_no = get_delivery_note_serial_no(item.item_code, item.qty, item.delivery_note)
def validate_serial_against_delivery_note(self):
"""
validate if the serial numbers in Sales Invoice Items are same as in
Delivery Note Item
"""
for item in self.items:
if not item.delivery_note or not item.dn_detail:
continue
serial_nos = frappe.db.get_value("Delivery Note Item", item.dn_detail, "serial_no") or ""
dn_serial_nos = set(get_serial_nos(serial_nos))
serial_nos = item.serial_no or ""
si_serial_nos = set(get_serial_nos(serial_nos))
serial_no_diff = si_serial_nos - dn_serial_nos
if serial_no_diff:
dn_link = frappe.utils.get_link_to_form("Delivery Note", item.delivery_note)
serial_no_msg = ", ".join(frappe.bold(d) for d in serial_no_diff)
msg = _("Row #{0}: The following Serial Nos are not present in Delivery Note {1}:").format(
item.idx, dn_link
)
msg += " " + serial_no_msg
frappe.throw(msg=msg, title=_("Serial Nos Mismatch"))
if item.serial_no and cint(item.qty) != len(si_serial_nos):
frappe.throw(
_("Row #{0}: {1} Serial numbers required for Item {2}. You have provided {3}.").format(
item.idx, item.qty, item.item_code, len(si_serial_nos)
)
)
item.set_serial_no_against_delivery_note()
item.validate_serial_against_delivery_note()
def update_project(self):
if self.project:

View File

@@ -2,34 +2,42 @@
// License: GNU General Public License v3. See license.txt
// render
frappe.listview_settings['Sales Invoice'] = {
add_fields: ["customer", "customer_name", "base_grand_total", "outstanding_amount", "due_date", "company",
"currency", "is_return"],
get_indicator: function(doc) {
frappe.listview_settings["Sales Invoice"] = {
add_fields: [
"customer",
"customer_name",
"base_grand_total",
"outstanding_amount",
"due_date",
"company",
"currency",
"is_return",
],
get_indicator: function (doc) {
const status_colors = {
"Draft": "grey",
"Unpaid": "orange",
"Paid": "green",
"Return": "gray",
Draft: "grey",
Unpaid: "orange",
Paid: "green",
Return: "gray",
"Credit Note Issued": "gray",
"Unpaid and Discounted": "orange",
"Partly Paid and Discounted": "yellow",
"Overdue and Discounted": "red",
"Overdue": "red",
Overdue: "red",
"Partly Paid": "yellow",
"Internal Transfer": "darkgrey"
"Internal Transfer": "darkgrey",
};
return [__(doc.status), status_colors[doc.status], "status,=,"+doc.status];
return [__(doc.status), status_colors[doc.status], "status,=," + doc.status];
},
right_column: "grand_total",
onload: function(listview) {
listview.page.add_action_item(__("Delivery Note"), ()=>{
onload: function (listview) {
listview.page.add_action_item(__("Delivery Note"), () => {
erpnext.bulk_transaction_processing.create(listview, "Sales Invoice", "Delivery Note");
});
listview.page.add_action_item(__("Payment"), ()=>{
listview.page.add_action_item(__("Payment"), () => {
erpnext.bulk_transaction_processing.create(listview, "Sales Invoice", "Payment Entry");
});
}
},
};

View File

@@ -2,7 +2,13 @@
# License: GNU General Public License v3. See license.txt
import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils.data import cint
from erpnext.assets.doctype.asset.depreciation import get_disposal_account_and_cost_center
from erpnext.stock.doctype.serial_no.serial_no import get_delivery_note_serial_no, get_serial_nos
class SalesInvoiceItem(Document):
@@ -92,4 +98,67 @@ class SalesInvoiceItem(Document):
weight_uom: DF.Link | None
# end: auto-generated types
pass
def validate_cost_center(self, company: str):
cost_center_company = frappe.get_cached_value("Cost Center", self.cost_center, "company")
if cost_center_company != company:
frappe.throw(
_("Row #{0}: Cost Center {1} does not belong to company {2}").format(
frappe.bold(self.idx), frappe.bold(self.cost_center), frappe.bold(company)
)
)
def set_actual_qty(self):
if self.item_code and self.warehouse:
self.actual_qty = (
frappe.db.get_value(
"Bin", {"item_code": self.item_code, "warehouse": self.warehouse}, "actual_qty"
)
or 0
)
def set_income_account_for_fixed_asset(self, company: str):
"""Set income account for fixed asset item based on company's disposal account and cost center."""
if not self.is_fixed_asset:
return
disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(company)
self.income_account = disposal_account
if not self.cost_center:
self.cost_center = depreciation_cost_center
def set_serial_no_against_delivery_note(self):
"""Set serial no based on delivery note."""
if self.serial_no and self.delivery_note and self.qty != len(get_serial_nos(self.serial_no)):
self.serial_no = get_delivery_note_serial_no(self.item_code, self.qty, self.delivery_note)
def validate_serial_against_delivery_note(self):
"""Ensure the serial numbers in this Sales Invoice Item are same as in the linked Delivery Note."""
if not self.delivery_note or not self.dn_detail:
return
serial_nos = frappe.db.get_value("Delivery Note Item", self.dn_detail, "serial_no") or ""
dn_serial_nos = set(get_serial_nos(serial_nos))
serial_nos = self.serial_no or ""
si_serial_nos = set(get_serial_nos(serial_nos))
serial_no_diff = si_serial_nos - dn_serial_nos
if serial_no_diff:
dn_link = frappe.utils.get_link_to_form("Delivery Note", self.delivery_note)
msg = (
_("Row #{0}: The following serial numbers are not present in Delivery Note {1}:").format(
self.idx, dn_link
)
+ " "
+ ", ".join(frappe.bold(d) for d in serial_no_diff)
)
frappe.throw(msg=msg, title=_("Serial Nos Mismatch"))
if self.serial_no and cint(self.qty) != len(si_serial_nos):
frappe.throw(
_(
"Row #{0}: {1} serial numbers are required for Item {2}. You have provided {3} serial numbers."
).format(self.idx, self.qty, self.item_code, len(si_serial_nos))
)

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