Compare commits
407 Commits
v15.10.4
...
rohitwaghc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a748f45c9 | ||
|
|
581c8b1a22 | ||
|
|
478b988290 | ||
|
|
c0b60413b6 | ||
|
|
11f30e90ab | ||
|
|
5f4b23d4af | ||
|
|
9ce68deff5 | ||
|
|
32660abdc8 | ||
|
|
76fc420b21 | ||
|
|
c111ce9bf4 | ||
|
|
03bde07966 | ||
|
|
a195dd3c1f | ||
|
|
7d3d2eb928 | ||
|
|
5f789d9abe | ||
|
|
44ff607dcd | ||
|
|
54fd9ec21e | ||
|
|
399c5629f4 | ||
|
|
953f64091a | ||
|
|
173b3b85f6 | ||
|
|
8b5afbbaca | ||
|
|
df1a51e291 | ||
|
|
d8c6eb0bf2 | ||
|
|
b6e90c4973 | ||
|
|
b8582db124 | ||
|
|
d6a3b179ec | ||
|
|
6a5a941a5a | ||
|
|
9317adfa33 | ||
|
|
d3039be5bc | ||
|
|
6832908e92 | ||
|
|
5fac50036a | ||
|
|
3035dcab07 | ||
|
|
5af335dc33 | ||
|
|
7ca72423b9 | ||
|
|
9b4a1b0a69 | ||
|
|
1476196966 | ||
|
|
643189a0ce | ||
|
|
e357497bcb | ||
|
|
f21918d06c | ||
|
|
539eb794c0 | ||
|
|
3814c5a54a | ||
|
|
4b15c00b11 | ||
|
|
7001e0a820 | ||
|
|
e0e80f7eed | ||
|
|
62aefcef04 | ||
|
|
6d1c144a66 | ||
|
|
eb9b2e896e | ||
|
|
5e89676d05 | ||
|
|
50e49bef85 | ||
|
|
d74647d5a5 | ||
|
|
ee119f30fb | ||
|
|
c7b96df69c | ||
|
|
63209f4eac | ||
|
|
93f3af7dba | ||
|
|
0b1417e891 | ||
|
|
16349553c7 | ||
|
|
4b5712688a | ||
|
|
cd24a2a05d | ||
|
|
c55c0f7173 | ||
|
|
6230bbc77d | ||
|
|
e20c1acb6e | ||
|
|
6173654093 | ||
|
|
b0be08f05d | ||
|
|
7aeb53a806 | ||
|
|
e5eeb216e8 | ||
|
|
8585cfc533 | ||
|
|
a512ec7af5 | ||
|
|
cdab3fa970 | ||
|
|
6c3b5bb402 | ||
|
|
db7348a1de | ||
|
|
84672e2275 | ||
|
|
c68939a0e0 | ||
|
|
0c234e5c1a | ||
|
|
689f277d13 | ||
|
|
328728e3a4 | ||
|
|
0ede99b3cb | ||
|
|
d130aadcf3 | ||
|
|
1d421713be | ||
|
|
0b091aaf14 | ||
|
|
e5fdca7b05 | ||
|
|
d8cf6ba38d | ||
|
|
9057bff786 | ||
|
|
014d21a050 | ||
|
|
05e4d1c240 | ||
|
|
4513d83f22 | ||
|
|
b785901efa | ||
|
|
b398cc6579 | ||
|
|
85ae9eee25 | ||
|
|
70ab25a611 | ||
|
|
0d8358bdd1 | ||
|
|
13e334398e | ||
|
|
823abfd6e0 | ||
|
|
e55dc2a7c0 | ||
|
|
00d410cc1d | ||
|
|
87596e6e29 | ||
|
|
0182b95230 | ||
|
|
1947a67f3d | ||
|
|
8720115f01 | ||
|
|
a5b3c1e7cb | ||
|
|
23d7a1fc76 | ||
|
|
c7ca929ddb | ||
|
|
4f9b194fe9 | ||
|
|
cda1c5ca10 | ||
|
|
9cb8d33923 | ||
|
|
6352bfe34e | ||
|
|
23011df86b | ||
|
|
4291b9fa8d | ||
|
|
930df21a5f | ||
|
|
6a63a6c98a | ||
|
|
7e43f6b7e0 | ||
|
|
84a359c760 | ||
|
|
7d14ecfcb8 | ||
|
|
07fd93a6f6 | ||
|
|
4784117a8f | ||
|
|
7a9beb4d47 | ||
|
|
87f36ce425 | ||
|
|
48992cd205 | ||
|
|
99d1f1d67b | ||
|
|
eadea0207c | ||
|
|
e67d579ac4 | ||
|
|
bac2f66344 | ||
|
|
e7e8149fbe | ||
|
|
36b442a951 | ||
|
|
65853da505 | ||
|
|
df7afc3154 | ||
|
|
341f9030f5 | ||
|
|
6b5e1cfeb7 | ||
|
|
9f8a27833a | ||
|
|
1860399ccb | ||
|
|
57bb031602 | ||
|
|
9d19ec43c8 | ||
|
|
0694fd19fd | ||
|
|
94bb6241ef | ||
|
|
4d1f56c4bd | ||
|
|
ad53633c66 | ||
|
|
2bf6125b71 | ||
|
|
792de1be03 | ||
|
|
66156fcfa7 | ||
|
|
fc565ecd99 | ||
|
|
d196aa5a36 | ||
|
|
e68d2d1c7a | ||
|
|
93f64396ac | ||
|
|
91c21d13e5 | ||
|
|
38abfdb8ae | ||
|
|
194f46be57 | ||
|
|
d541ba3e61 | ||
|
|
27703b54bd | ||
|
|
9ffbf5623a | ||
|
|
56ee843233 | ||
|
|
383dfdd4ab | ||
|
|
5c269a9947 | ||
|
|
cf5fa210bb | ||
|
|
53d943ec70 | ||
|
|
d755b9d38c | ||
|
|
824df72eeb | ||
|
|
e4baacd79e | ||
|
|
38b384dfa2 | ||
|
|
10fe201bc8 | ||
|
|
bcb280c5e8 | ||
|
|
83d7111649 | ||
|
|
cd42089e20 | ||
|
|
3b96aaeead | ||
|
|
83b4cc5091 | ||
|
|
a75a69a01e | ||
|
|
190bd45bd7 | ||
|
|
c752bec2d9 | ||
|
|
8fef484f0f | ||
|
|
b40baf5e63 | ||
|
|
2c8ba892ac | ||
|
|
2e07b03307 | ||
|
|
0be520331c | ||
|
|
72da3083e6 | ||
|
|
a3ddd326d6 | ||
|
|
1c5a7e29f2 | ||
|
|
f723d7b561 | ||
|
|
6662c321a5 | ||
|
|
4269ef8c98 | ||
|
|
a543bf47ef | ||
|
|
c964c45f4e | ||
|
|
3c98368e45 | ||
|
|
6fc4dac4db | ||
|
|
afc87a4486 | ||
|
|
5137966fe5 | ||
|
|
6f364df48c | ||
|
|
5084b9bd4b | ||
|
|
eaa3849df4 | ||
|
|
9f8f3db953 | ||
|
|
43c218c673 | ||
|
|
32d9642379 | ||
|
|
b9181e85dc | ||
|
|
66a05087b8 | ||
|
|
ca03e9cfd3 | ||
|
|
692867427c | ||
|
|
a0c0ab7709 | ||
|
|
ee2d108bef | ||
|
|
8eb2f67910 | ||
|
|
3d7e87185c | ||
|
|
177110349d | ||
|
|
ed553b89a4 | ||
|
|
2ee51d36ff | ||
|
|
0f87ec15ad | ||
|
|
720144898f | ||
|
|
46f7569a54 | ||
|
|
a102172982 | ||
|
|
b954bdfdf9 | ||
|
|
9c01a5f7ed | ||
|
|
0c9d7434f9 | ||
|
|
2db79cdf3b | ||
|
|
acd2e93f8c | ||
|
|
c81a15eac3 | ||
|
|
18fcbb6f97 | ||
|
|
baa83ece21 | ||
|
|
74819b8e70 | ||
|
|
a2a5b34099 | ||
|
|
ce11180793 | ||
|
|
0b7a95351a | ||
|
|
d225508ab1 | ||
|
|
d213db90af | ||
|
|
f5d7fbdaf8 | ||
|
|
fd76847cfa | ||
|
|
709faaac69 | ||
|
|
3cd315973c | ||
|
|
15135952fc | ||
|
|
6d6a3a10fb | ||
|
|
7af62fb6c8 | ||
|
|
72ff56be13 | ||
|
|
b91f65d4cf | ||
|
|
40d4e3261e | ||
|
|
bf5d2f5fe4 | ||
|
|
bb77f85d89 | ||
|
|
37329469c3 | ||
|
|
ab03ab388c | ||
|
|
c50639334f | ||
|
|
518b22bffc | ||
|
|
a56d5b805c | ||
|
|
bef38f74fe | ||
|
|
14fe0af887 | ||
|
|
c78d085e24 | ||
|
|
8c12b3dbe0 | ||
|
|
88a7248888 | ||
|
|
a548f12941 | ||
|
|
f08b424972 | ||
|
|
375859a25f | ||
|
|
5a66c8585c | ||
|
|
a2f1a964f1 | ||
|
|
92e6017a29 | ||
|
|
10f17dfcc8 | ||
|
|
c643e70e2f | ||
|
|
4daee6d9c7 | ||
|
|
a29468f6fe | ||
|
|
beb4137dac | ||
|
|
2d5f186812 | ||
|
|
43fce29a04 | ||
|
|
63b4d20bdf | ||
|
|
b625b05ddc | ||
|
|
30daccecc7 | ||
|
|
db4efd3332 | ||
|
|
7556457e3e | ||
|
|
5590b04c89 | ||
|
|
490cbc53d8 | ||
|
|
592b3ff7b7 | ||
|
|
0bde22fe46 | ||
|
|
60e04ab661 | ||
|
|
83bf2c17e0 | ||
|
|
a805796c0a | ||
|
|
0bff065f0b | ||
|
|
5fd4ca56f5 | ||
|
|
bc9a63497a | ||
|
|
b9dc0f3896 | ||
|
|
1f21607e4f | ||
|
|
a5ad318a37 | ||
|
|
ba05648741 | ||
|
|
3c6114ab72 | ||
|
|
488e693ed8 | ||
|
|
ae2a8db0d7 | ||
|
|
22138867f5 | ||
|
|
2ba283d138 | ||
|
|
af8af2b36e | ||
|
|
789aee4544 | ||
|
|
02f56ee20e | ||
|
|
c78d4c15d3 | ||
|
|
7833138c57 | ||
|
|
b582e9c42c | ||
|
|
faf79f4d2a | ||
|
|
47c2bd7335 | ||
|
|
73618f0605 | ||
|
|
a08b97e886 | ||
|
|
282c19e7e1 | ||
|
|
53992deb10 | ||
|
|
4235e08668 | ||
|
|
949f4c3790 | ||
|
|
11d4382e19 | ||
|
|
00e86bf318 | ||
|
|
d3c4bd7f5f | ||
|
|
cb15ff1d74 | ||
|
|
55a8326d06 | ||
|
|
451c288011 | ||
|
|
7923bd7964 | ||
|
|
3bef12cb55 | ||
|
|
75bd1e6b65 | ||
|
|
b126720826 | ||
|
|
f246684694 | ||
|
|
1822325f34 | ||
|
|
986273b6d3 | ||
|
|
f4ac00595d | ||
|
|
66661d0649 | ||
|
|
326751c8bd | ||
|
|
5e29aab83b | ||
|
|
1b2831bdfe | ||
|
|
a40864dede | ||
|
|
3eac436e7b | ||
|
|
5fe40ac085 | ||
|
|
4ee8cf3907 | ||
|
|
d7c7748c03 | ||
|
|
f31070741a | ||
|
|
317a74b58c | ||
|
|
0405a2b817 | ||
|
|
e76f59803c | ||
|
|
41e46326c0 | ||
|
|
8574941cb6 | ||
|
|
4f994cf26c | ||
|
|
bb3591deec | ||
|
|
e2d041f51c | ||
|
|
63f306f1b4 | ||
|
|
72c95d31d1 | ||
|
|
1ee15f65a8 | ||
|
|
0a235584ad | ||
|
|
7f4cd3cd15 | ||
|
|
ba55d0ede7 | ||
|
|
c74482a27c | ||
|
|
510ab769f1 | ||
|
|
e9314325cc | ||
|
|
cea4ed6f88 | ||
|
|
29eb090528 | ||
|
|
aebb0c7979 | ||
|
|
dcdd3e8cc4 | ||
|
|
f84f82c7d7 | ||
|
|
32f77eae5d | ||
|
|
d785c6ce3e | ||
|
|
bc8ab51f9d | ||
|
|
5c9c3bee70 | ||
|
|
c9ea83591f | ||
|
|
10fcf5af5f | ||
|
|
e4230cf6d9 | ||
|
|
53c705506b | ||
|
|
960443d268 | ||
|
|
f71af209c0 | ||
|
|
6b20a7eed1 | ||
|
|
5cdc22adf3 | ||
|
|
9e36ab7de7 | ||
|
|
daafe45dd4 | ||
|
|
706d1111ad | ||
|
|
da33079f12 | ||
|
|
07bcc24e35 | ||
|
|
0f0a5b73f6 | ||
|
|
0aa73e31ce | ||
|
|
a3d4f63ba1 | ||
|
|
ff166e8104 | ||
|
|
a118417645 | ||
|
|
a83f3106f3 | ||
|
|
6d4ca6a1ee | ||
|
|
ebec463166 | ||
|
|
10488520e7 | ||
|
|
9e15a3c981 | ||
|
|
63eef680d0 | ||
|
|
7def475eb1 | ||
|
|
0e2f57ba89 | ||
|
|
30bdba4801 | ||
|
|
ed06f0cd1b | ||
|
|
9abc07e34b | ||
|
|
a7d13686c7 | ||
|
|
ab99414242 | ||
|
|
fa8fb7a49e | ||
|
|
4fc3a264f9 | ||
|
|
5df2f5d523 | ||
|
|
e0c35d60b4 | ||
|
|
14aa9d3d0f | ||
|
|
3bdd1e9514 | ||
|
|
171586db9b | ||
|
|
c3557a87ef | ||
|
|
4853ab1fec | ||
|
|
ed032b3224 | ||
|
|
8b7900e6a7 | ||
|
|
e0a38207f6 | ||
|
|
53b844f173 | ||
|
|
34e581715a | ||
|
|
83c120849f | ||
|
|
e08c7bad63 | ||
|
|
2905db19e5 | ||
|
|
bd7e8ed230 | ||
|
|
b2e0d24954 | ||
|
|
84a94cec6b | ||
|
|
cc195777f4 | ||
|
|
60c10f4457 | ||
|
|
871dc6b0da | ||
|
|
3549cd39f1 | ||
|
|
222005ca44 | ||
|
|
98c56535d8 | ||
|
|
f6a779e1aa | ||
|
|
1f5dbebe68 | ||
|
|
4073dfb90b | ||
|
|
e2d85c513c | ||
|
|
880f648846 | ||
|
|
84d2a80f30 | ||
|
|
fe41e2a341 | ||
|
|
a97b8fd876 | ||
|
|
6ed42e939b | ||
|
|
f9d1995954 |
@@ -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
|
||||
|
||||
@@ -124,6 +124,7 @@
|
||||
"beforeEach": true,
|
||||
"onScan": true,
|
||||
"extend_cscript": true,
|
||||
"localforage": true
|
||||
"localforage": true,
|
||||
"Plaid": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import inspect
|
||||
|
||||
import frappe
|
||||
|
||||
__version__ = "15.10.4"
|
||||
__version__ = "15.16.2"
|
||||
|
||||
|
||||
def get_default_company(user=None):
|
||||
@@ -13,7 +13,7 @@ def get_default_company(user=None):
|
||||
if not user:
|
||||
user = frappe.session.user
|
||||
|
||||
companies = get_user_default_as_list(user, "company")
|
||||
companies = get_user_default_as_list("company", user)
|
||||
if companies:
|
||||
default_company = companies[0]
|
||||
else:
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
]
|
||||
],
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ class Account(NestedSet):
|
||||
self.validate_balance_must_be_debit_or_credit()
|
||||
self.validate_account_currency()
|
||||
self.validate_root_company_and_sync_account_to_children()
|
||||
self.validate_receivable_payable_account_type()
|
||||
|
||||
def validate_parent_child_account_type(self):
|
||||
if self.parent_account:
|
||||
@@ -188,6 +189,24 @@ class Account(NestedSet):
|
||||
"Balance Sheet" if self.root_type in ("Asset", "Liability", "Equity") else "Profit and Loss"
|
||||
)
|
||||
|
||||
def validate_receivable_payable_account_type(self):
|
||||
doc_before_save = self.get_doc_before_save()
|
||||
receivable_payable_types = ["Receivable", "Payable"]
|
||||
if (
|
||||
doc_before_save
|
||||
and doc_before_save.account_type in receivable_payable_types
|
||||
and doc_before_save.account_type != self.account_type
|
||||
):
|
||||
# check for ledger entries
|
||||
if frappe.db.get_all("GL Entry", filters={"account": self.name, "is_cancelled": 0}, limit=1):
|
||||
msg = _(
|
||||
"There are ledger entries against this account. Changing {0} to non-{1} in live system will cause incorrect output in 'Accounts {2}' report"
|
||||
).format(
|
||||
frappe.bold("Account Type"), doc_before_save.account_type, doc_before_save.account_type
|
||||
)
|
||||
frappe.msgprint(msg)
|
||||
self.add_comment("Comment", msg)
|
||||
|
||||
def validate_root_details(self):
|
||||
doc_before_save = self.get_doc_before_save()
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -56,7 +56,9 @@
|
||||
"Constru\u00e7\u00f5es em Andamento de Im\u00f3veis Destinados \u00e0 Venda": {},
|
||||
"Estoques Destinados \u00e0 Doa\u00e7\u00e3o": {},
|
||||
"Im\u00f3veis Destinados \u00e0 Venda": {},
|
||||
"Insumos (materiais diretos)": {},
|
||||
"Insumos (materiais diretos)": {
|
||||
"account_type": "Stock"
|
||||
},
|
||||
"Insumos Agropecu\u00e1rios": {},
|
||||
"Mercadorias para Revenda": {},
|
||||
"Outras 11": {},
|
||||
@@ -146,6 +148,65 @@
|
||||
"root_type": "Asset"
|
||||
},
|
||||
"CUSTOS DE PRODU\u00c7\u00c3O": {
|
||||
"CUSTO DOS PRODUTOS E SERVI\u00c7OS VENDIDOS": {
|
||||
"CUSTO DOS PRODUTOS VENDIDOS": {
|
||||
"CUSTO DOS PRODUTOS VENDIDOS PARA AS DEMAIS ATIVIDADES": {
|
||||
"Custos dos Produtos Vendidos em Geral": {
|
||||
"account_type": "Cost of Goods Sold"
|
||||
},
|
||||
"Outros Custos 4": {},
|
||||
"account_type": "Cost of Goods Sold"
|
||||
},
|
||||
"CUSTO DOS PRODUTOS VENDIDOS PARA ASSIST\u00caNCIA SOCIAL": {
|
||||
"Custos dos Produtos para Assist\u00eancia Social - Gratuidades": {},
|
||||
"Custos dos Produtos para Assist\u00eancia Social - Vendidos": {},
|
||||
"Outras": {}
|
||||
},
|
||||
"CUSTO DOS PRODUTOS VENDIDOS PARA EDUCA\u00c7\u00c3O": {
|
||||
"Custos dos Produtos para Educa\u00e7\u00e3o - Gratuidades": {},
|
||||
"Custos dos Produtos para Educa\u00e7\u00e3o - Vendidos": {},
|
||||
"Outros Custos 6": {}
|
||||
},
|
||||
"CUSTO DOS PRODUTOS VENDIDOS PARA SA\u00daDE": {
|
||||
"Custos dos Produtos para Sa\u00fade - Gratuidades": {},
|
||||
"Custos dos Produtos para Sa\u00fade \u2013 Vendidos": {},
|
||||
"Outros Custos 5": {}
|
||||
},
|
||||
"account_type": "Cost of Goods Sold"
|
||||
},
|
||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS": {
|
||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA AS DEMAIS ATIVIDADES": {
|
||||
"Custo dos Servi\u00e7os Prestados em Geral": {},
|
||||
"Outros Custos": {}
|
||||
},
|
||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA ASSIST\u00caNCIA SOCIAL": {
|
||||
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es 1": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas 1": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Gratuidade 1": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Pacientes Particulares": {},
|
||||
"Outros Custos 2": {}
|
||||
},
|
||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA EDUCA\u00c7\u00c3O": {
|
||||
"Custo dos Servi\u00e7os Prestados a Alunos N\u00e3o Bolsistas": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias (Exceto PROUNI)": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Gratuidade": {},
|
||||
"Custo dos Servi\u00e7os Prestados ao PROUNI": {},
|
||||
"Outros Custos 1": {}
|
||||
},
|
||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA SA\u00daDE": {
|
||||
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios SUS": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias 1": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es 2": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas 2": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Gratuidade 2": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Pacientes Particulares 1": {},
|
||||
"Outros Custos 3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"CUSTO DOS BENS E SERVI\u00c7OS PRODUZIDOS": {
|
||||
"CUSTO DOS PRODUTOS DE FABRICA\u00c7\u00c3O PR\u00d3PRIA PRODUZIDOS": {
|
||||
"Alimenta\u00e7\u00e3o do Trabalhador": {},
|
||||
@@ -621,7 +682,9 @@
|
||||
"Receita das Unidades Imobili\u00e1rias Vendidas": {},
|
||||
"Receita de Exporta\u00e7\u00e3o Direta de Mercadorias e Produtos": {},
|
||||
"Receita de Exporta\u00e7\u00e3o de Servi\u00e7os": {},
|
||||
"Receita de Loca\u00e7\u00e3o de Bens M\u00f3veis e Im\u00f3veis": {},
|
||||
"Receita de Loca\u00e7\u00e3o de Bens M\u00f3veis e Im\u00f3veis": {
|
||||
"account_type": "Income Account"
|
||||
},
|
||||
"Receita de Vendas de Mercadorias e Produtos a Comercial Exportadora com Fim Espec\u00edfico de Exporta\u00e7\u00e3o": {}
|
||||
}
|
||||
}
|
||||
@@ -645,65 +708,6 @@
|
||||
}
|
||||
},
|
||||
"RESULTADO OPERACIONAL": {
|
||||
"CUSTO DOS PRODUTOS E SERVI\u00c7OS VENDIDOS": {
|
||||
"CUSTO DOS PRODUTOS VENDIDOS": {
|
||||
"CUSTO DOS PRODUTOS VENDIDOS PARA AS DEMAIS ATIVIDADES": {
|
||||
"Custos dos Produtos Vendidos em Geral": {
|
||||
"account_type": "Cost of Goods Sold"
|
||||
},
|
||||
"Outros Custos 4": {},
|
||||
"account_type": "Cost of Goods Sold"
|
||||
},
|
||||
"CUSTO DOS PRODUTOS VENDIDOS PARA ASSIST\u00caNCIA SOCIAL": {
|
||||
"Custos dos Produtos para Assist\u00eancia Social - Gratuidades": {},
|
||||
"Custos dos Produtos para Assist\u00eancia Social - Vendidos": {},
|
||||
"Outras": {}
|
||||
},
|
||||
"CUSTO DOS PRODUTOS VENDIDOS PARA EDUCA\u00c7\u00c3O": {
|
||||
"Custos dos Produtos para Educa\u00e7\u00e3o - Gratuidades": {},
|
||||
"Custos dos Produtos para Educa\u00e7\u00e3o - Vendidos": {},
|
||||
"Outros Custos 6": {}
|
||||
},
|
||||
"CUSTO DOS PRODUTOS VENDIDOS PARA SA\u00daDE": {
|
||||
"Custos dos Produtos para Sa\u00fade - Gratuidades": {},
|
||||
"Custos dos Produtos para Sa\u00fade \u2013 Vendidos": {},
|
||||
"Outros Custos 5": {}
|
||||
},
|
||||
"account_type": "Cost of Goods Sold"
|
||||
},
|
||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS": {
|
||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA AS DEMAIS ATIVIDADES": {
|
||||
"Custo dos Servi\u00e7os Prestados em Geral": {},
|
||||
"Outros Custos": {}
|
||||
},
|
||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA ASSIST\u00caNCIA SOCIAL": {
|
||||
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es 1": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas 1": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Gratuidade 1": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Pacientes Particulares": {},
|
||||
"Outros Custos 2": {}
|
||||
},
|
||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA EDUCA\u00c7\u00c3O": {
|
||||
"Custo dos Servi\u00e7os Prestados a Alunos N\u00e3o Bolsistas": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias (Exceto PROUNI)": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Gratuidade": {},
|
||||
"Custo dos Servi\u00e7os Prestados ao PROUNI": {},
|
||||
"Outros Custos 1": {}
|
||||
},
|
||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA SA\u00daDE": {
|
||||
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios SUS": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias 1": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es 2": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas 2": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Gratuidade 2": {},
|
||||
"Custo dos Servi\u00e7os Prestados a Pacientes Particulares 1": {},
|
||||
"Outros Custos 3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"DESPESAS OPERACIONAIS": {
|
||||
"DESPESAS OPERACIONAIS 1": {
|
||||
"DESPESAS OPERACIONAIS 2": {
|
||||
|
||||
@@ -6,6 +6,7 @@ import unittest
|
||||
|
||||
import frappe
|
||||
from frappe.test_runner import make_test_records
|
||||
from frappe.utils import nowdate
|
||||
|
||||
from erpnext.accounts.doctype.account.account import (
|
||||
InvalidAccountMergeError,
|
||||
@@ -324,6 +325,19 @@ class TestAccount(unittest.TestCase):
|
||||
acc.account_currency = "USD"
|
||||
self.assertRaises(frappe.ValidationError, acc.save)
|
||||
|
||||
def test_account_balance(self):
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
|
||||
if not frappe.db.exists("Account", "Test Percent Account %5 - _TC"):
|
||||
acc = frappe.new_doc("Account")
|
||||
acc.account_name = "Test Percent Account %5"
|
||||
acc.parent_account = "Tax Assets - _TC"
|
||||
acc.company = "_Test Company"
|
||||
acc.insert()
|
||||
|
||||
balance = get_balance_on(account="Test Percent Account %5 - _TC", date=nowdate())
|
||||
self.assertEqual(balance, 0)
|
||||
|
||||
|
||||
def _make_test_records(verbose=None):
|
||||
from frappe.test_runner import make_test_objects
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -11,6 +11,10 @@ from frappe.model import core_doctypes_list
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cstr
|
||||
|
||||
from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import (
|
||||
get_allowed_types_from_settings,
|
||||
)
|
||||
|
||||
|
||||
class AccountingDimension(Document):
|
||||
# begin: auto-generated types
|
||||
@@ -106,6 +110,7 @@ def make_dimension_in_accounting_doctypes(doc, doclist=None):
|
||||
|
||||
doc_count = len(get_accounting_dimensions())
|
||||
count = 0
|
||||
repostable_doctypes = get_allowed_types_from_settings()
|
||||
|
||||
for doctype in doclist:
|
||||
|
||||
@@ -121,6 +126,7 @@ def make_dimension_in_accounting_doctypes(doc, doclist=None):
|
||||
"options": doc.document_type,
|
||||
"insert_after": insert_after_field,
|
||||
"owner": "Administrator",
|
||||
"allow_on_submit": 1 if doctype in repostable_doctypes else 0,
|
||||
}
|
||||
|
||||
meta = frappe.get_meta(doctype, cached=False)
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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) {},
|
||||
});
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2013-06-24 15:49:57",
|
||||
"description": "Settings for Accounts",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Other",
|
||||
"editable_grid": 1,
|
||||
@@ -462,7 +461,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2023-11-20 09:37:47.650347",
|
||||
"modified": "2024-01-30 14:04:26.553554",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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" });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -9,6 +9,7 @@ from frappe.contacts.address_and_contact import (
|
||||
load_address_and_contact,
|
||||
)
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import comma_and, get_link_to_form
|
||||
|
||||
|
||||
class BankAccount(Document):
|
||||
@@ -52,6 +53,19 @@ class BankAccount(Document):
|
||||
def validate(self):
|
||||
self.validate_company()
|
||||
self.validate_iban()
|
||||
self.validate_account()
|
||||
|
||||
def validate_account(self):
|
||||
if self.account:
|
||||
if accounts := frappe.db.get_all(
|
||||
"Bank Account", filters={"account": self.account, "name": ["!=", self.name]}, as_list=1
|
||||
):
|
||||
frappe.throw(
|
||||
_("'{0}' account is already used by {1}. Use another account.").format(
|
||||
frappe.bold(self.account),
|
||||
frappe.bold(comma_and([get_link_to_form(self.doctype, x[0]) for x in accounts])),
|
||||
)
|
||||
)
|
||||
|
||||
def validate_company(self):
|
||||
if self.is_company_account and not self.company:
|
||||
|
||||
@@ -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 () {},
|
||||
});
|
||||
|
||||
@@ -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) {
|
||||
|
||||
// }
|
||||
});
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
import frappe
|
||||
from frappe import _, msgprint
|
||||
from frappe.model.document import Document
|
||||
from frappe.query_builder.custom import ConstantColumn
|
||||
from frappe.utils import flt, fmt_money, getdate
|
||||
from pypika import Order
|
||||
|
||||
import erpnext
|
||||
|
||||
@@ -179,39 +181,62 @@ def get_payment_entries_for_bank_clearance(
|
||||
|
||||
pos_sales_invoices, pos_purchase_invoices = [], []
|
||||
if include_pos_transactions:
|
||||
pos_sales_invoices = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
"Sales Invoice Payment" as payment_document, sip.name as payment_entry, sip.amount as debit,
|
||||
si.posting_date, si.customer as against_account, sip.clearance_date,
|
||||
account.account_currency, 0 as credit
|
||||
from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account
|
||||
where
|
||||
sip.account=%(account)s and si.docstatus=1 and sip.parent = si.name
|
||||
and account.name = sip.account and si.posting_date >= %(from)s and si.posting_date <= %(to)s
|
||||
order by
|
||||
si.posting_date ASC, si.name DESC
|
||||
""",
|
||||
{"account": account, "from": from_date, "to": to_date},
|
||||
as_dict=1,
|
||||
)
|
||||
si_payment = frappe.qb.DocType("Sales Invoice Payment")
|
||||
si = frappe.qb.DocType("Sales Invoice")
|
||||
acc = frappe.qb.DocType("Account")
|
||||
|
||||
pos_purchase_invoices = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
"Purchase Invoice" as payment_document, pi.name as payment_entry, pi.paid_amount as credit,
|
||||
pi.posting_date, pi.supplier as against_account, pi.clearance_date,
|
||||
account.account_currency, 0 as debit
|
||||
from `tabPurchase Invoice` pi, `tabAccount` account
|
||||
where
|
||||
pi.cash_bank_account=%(account)s and pi.docstatus=1 and account.name = pi.cash_bank_account
|
||||
and pi.posting_date >= %(from)s and pi.posting_date <= %(to)s
|
||||
order by
|
||||
pi.posting_date ASC, pi.name DESC
|
||||
""",
|
||||
{"account": account, "from": from_date, "to": to_date},
|
||||
as_dict=1,
|
||||
)
|
||||
pos_sales_invoices = (
|
||||
frappe.qb.from_(si_payment)
|
||||
.inner_join(si)
|
||||
.on(si_payment.parent == si.name)
|
||||
.inner_join(acc)
|
||||
.on(si_payment.account == acc.name)
|
||||
.select(
|
||||
ConstantColumn("Sales Invoice").as_("payment_document"),
|
||||
si.name.as_("payment_entry"),
|
||||
si_payment.reference_no.as_("cheque_number"),
|
||||
si_payment.amount.as_("debit"),
|
||||
si.posting_date,
|
||||
si.customer.as_("against_account"),
|
||||
si_payment.clearance_date,
|
||||
acc.account_currency,
|
||||
ConstantColumn(0).as_("credit"),
|
||||
)
|
||||
.where(
|
||||
(si.docstatus == 1)
|
||||
& (si_payment.account == account)
|
||||
& (si.posting_date >= from_date)
|
||||
& (si.posting_date <= to_date)
|
||||
)
|
||||
.orderby(si.posting_date)
|
||||
.orderby(si.name, order=Order.desc)
|
||||
).run(as_dict=True)
|
||||
|
||||
pi = frappe.qb.DocType("Purchase Invoice")
|
||||
|
||||
pos_purchase_invoices = (
|
||||
frappe.qb.from_(pi)
|
||||
.inner_join(acc)
|
||||
.on(pi.cash_bank_account == acc.name)
|
||||
.select(
|
||||
ConstantColumn("Purchase Invoice").as_("payment_document"),
|
||||
pi.name.as_("payment_entry"),
|
||||
pi.paid_amount.as_("credit"),
|
||||
pi.posting_date,
|
||||
pi.supplier.as_("against_account"),
|
||||
pi.clearance_date,
|
||||
acc.account_currency,
|
||||
ConstantColumn(0).as_("debit"),
|
||||
)
|
||||
.where(
|
||||
(pi.docstatus == 1)
|
||||
& (pi.cash_bank_account == account)
|
||||
& (pi.posting_date >= from_date)
|
||||
& (pi.posting_date <= to_date)
|
||||
)
|
||||
.orderby(pi.posting_date)
|
||||
.orderby(pi.name, order=Order.desc)
|
||||
).run(as_dict=True)
|
||||
|
||||
entries = (
|
||||
list(payment_entries)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -9,7 +9,6 @@ from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.query_builder.custom import ConstantColumn
|
||||
from frappe.utils import cint, flt
|
||||
from pypika.terms import Parameter
|
||||
|
||||
from erpnext import get_default_cost_center
|
||||
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount
|
||||
@@ -509,6 +508,18 @@ def check_matching(
|
||||
to_reference_date,
|
||||
):
|
||||
exact_match = True if "exact_match" in document_types else False
|
||||
|
||||
common_filters = frappe._dict(
|
||||
{
|
||||
"amount": transaction.unallocated_amount,
|
||||
"payment_type": "Receive" if transaction.deposit > 0.0 else "Pay",
|
||||
"reference_no": transaction.reference_number,
|
||||
"party_type": transaction.party_type,
|
||||
"party": transaction.party,
|
||||
"bank_account": bank_account,
|
||||
}
|
||||
)
|
||||
|
||||
queries = get_queries(
|
||||
bank_account,
|
||||
company,
|
||||
@@ -520,20 +531,12 @@ def check_matching(
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
exact_match,
|
||||
common_filters,
|
||||
)
|
||||
|
||||
filters = {
|
||||
"amount": transaction.unallocated_amount,
|
||||
"payment_type": "Receive" if transaction.deposit > 0.0 else "Pay",
|
||||
"reference_no": transaction.reference_number,
|
||||
"party_type": transaction.party_type,
|
||||
"party": transaction.party,
|
||||
"bank_account": bank_account,
|
||||
}
|
||||
|
||||
matching_vouchers = []
|
||||
for query in queries:
|
||||
matching_vouchers.extend(frappe.db.sql(query, filters, as_dict=True))
|
||||
matching_vouchers.extend(query.run(as_dict=True))
|
||||
|
||||
return (
|
||||
sorted(matching_vouchers, key=lambda x: x["rank"], reverse=True) if matching_vouchers else []
|
||||
@@ -551,6 +554,7 @@ def get_queries(
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
exact_match,
|
||||
common_filters,
|
||||
):
|
||||
# get queries to get matching vouchers
|
||||
account_from_to = "paid_to" if transaction.deposit > 0.0 else "paid_from"
|
||||
@@ -571,6 +575,7 @@ def get_queries(
|
||||
filter_by_reference_date,
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
common_filters,
|
||||
)
|
||||
or []
|
||||
)
|
||||
@@ -590,6 +595,7 @@ def get_matching_queries(
|
||||
filter_by_reference_date,
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
common_filters,
|
||||
):
|
||||
queries = []
|
||||
currency = get_account_currency(bank_account)
|
||||
@@ -604,6 +610,7 @@ def get_matching_queries(
|
||||
filter_by_reference_date,
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
common_filters,
|
||||
)
|
||||
queries.append(query)
|
||||
|
||||
@@ -616,16 +623,17 @@ def get_matching_queries(
|
||||
filter_by_reference_date,
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
common_filters,
|
||||
)
|
||||
queries.append(query)
|
||||
|
||||
if transaction.deposit > 0.0 and "sales_invoice" in document_types:
|
||||
query = get_si_matching_query(exact_match, currency)
|
||||
query = get_si_matching_query(exact_match, currency, common_filters)
|
||||
queries.append(query)
|
||||
|
||||
if transaction.withdrawal > 0.0:
|
||||
if "purchase_invoice" in document_types:
|
||||
query = get_pi_matching_query(exact_match, currency)
|
||||
query = get_pi_matching_query(exact_match, currency, common_filters)
|
||||
queries.append(query)
|
||||
|
||||
if "bank_transaction" in document_types:
|
||||
@@ -680,7 +688,7 @@ def get_bt_matching_query(exact_match, transaction):
|
||||
.where(amount_condition)
|
||||
.where(bt.docstatus == 1)
|
||||
)
|
||||
return str(query)
|
||||
return query
|
||||
|
||||
|
||||
def get_pe_matching_query(
|
||||
@@ -692,6 +700,7 @@ def get_pe_matching_query(
|
||||
filter_by_reference_date,
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
common_filters,
|
||||
):
|
||||
# get matching payment entries query
|
||||
to_from = "to" if transaction.deposit > 0.0 else "from"
|
||||
@@ -734,7 +743,7 @@ def get_pe_matching_query(
|
||||
.where(pe.docstatus == 1)
|
||||
.where(pe.payment_type.isin([payment_type, "Internal Transfer"]))
|
||||
.where(pe.clearance_date.isnull())
|
||||
.where(getattr(pe, account_from_to) == Parameter("%(bank_account)s"))
|
||||
.where(getattr(pe, account_from_to) == common_filters.bank_account)
|
||||
.where(amount_condition)
|
||||
.where(filter_by_date)
|
||||
.orderby(pe.reference_date if cint(filter_by_reference_date) else pe.posting_date)
|
||||
@@ -743,7 +752,7 @@ def get_pe_matching_query(
|
||||
if frappe.flags.auto_reconcile_vouchers == True:
|
||||
query = query.where(ref_condition)
|
||||
|
||||
return str(query)
|
||||
return query
|
||||
|
||||
|
||||
def get_je_matching_query(
|
||||
@@ -754,6 +763,7 @@ def get_je_matching_query(
|
||||
filter_by_reference_date,
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
common_filters,
|
||||
):
|
||||
# get matching journal entry query
|
||||
# We have mapping at the bank level
|
||||
@@ -793,7 +803,7 @@ def get_je_matching_query(
|
||||
.where(je.docstatus == 1)
|
||||
.where(je.voucher_type != "Opening Entry")
|
||||
.where(je.clearance_date.isnull())
|
||||
.where(jea.account == Parameter("%(bank_account)s"))
|
||||
.where(jea.account == common_filters.bank_account)
|
||||
.where(amount_equality if exact_match else getattr(jea, amount_field) > 0.0)
|
||||
.where(je.docstatus == 1)
|
||||
.where(filter_by_date)
|
||||
@@ -803,19 +813,19 @@ def get_je_matching_query(
|
||||
if frappe.flags.auto_reconcile_vouchers == True:
|
||||
query = query.where(ref_condition)
|
||||
|
||||
return str(query)
|
||||
return query
|
||||
|
||||
|
||||
def get_si_matching_query(exact_match, currency):
|
||||
def get_si_matching_query(exact_match, currency, common_filters):
|
||||
# get matching sales invoice query
|
||||
si = frappe.qb.DocType("Sales Invoice")
|
||||
sip = frappe.qb.DocType("Sales Invoice Payment")
|
||||
|
||||
amount_equality = sip.amount == Parameter("%(amount)s")
|
||||
amount_equality = sip.amount == common_filters.amount
|
||||
amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0)
|
||||
amount_condition = amount_equality if exact_match else sip.amount > 0.0
|
||||
|
||||
party_condition = si.customer == Parameter("%(party)s")
|
||||
party_condition = si.customer == common_filters.party
|
||||
party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0)
|
||||
|
||||
query = (
|
||||
@@ -836,23 +846,23 @@ def get_si_matching_query(exact_match, currency):
|
||||
)
|
||||
.where(si.docstatus == 1)
|
||||
.where(sip.clearance_date.isnull())
|
||||
.where(sip.account == Parameter("%(bank_account)s"))
|
||||
.where(sip.account == common_filters.bank_account)
|
||||
.where(amount_condition)
|
||||
.where(si.currency == currency)
|
||||
)
|
||||
|
||||
return str(query)
|
||||
return query
|
||||
|
||||
|
||||
def get_pi_matching_query(exact_match, currency):
|
||||
def get_pi_matching_query(exact_match, currency, common_filters):
|
||||
# get matching purchase invoice query when they are also used as payment entries (is_paid)
|
||||
purchase_invoice = frappe.qb.DocType("Purchase Invoice")
|
||||
|
||||
amount_equality = purchase_invoice.paid_amount == Parameter("%(amount)s")
|
||||
amount_equality = purchase_invoice.paid_amount == common_filters.amount
|
||||
amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0)
|
||||
amount_condition = amount_equality if exact_match else purchase_invoice.paid_amount > 0.0
|
||||
|
||||
party_condition = purchase_invoice.supplier == Parameter("%(party)s")
|
||||
party_condition = purchase_invoice.supplier == common_filters.party
|
||||
party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0)
|
||||
|
||||
query = (
|
||||
@@ -872,9 +882,9 @@ def get_pi_matching_query(exact_match, currency):
|
||||
.where(purchase_invoice.docstatus == 1)
|
||||
.where(purchase_invoice.is_paid == 1)
|
||||
.where(purchase_invoice.clearance_date.isnull())
|
||||
.where(purchase_invoice.cash_bank_account == Parameter("%(bank_account)s"))
|
||||
.where(purchase_invoice.cash_bank_account == common_filters.bank_account)
|
||||
.where(amount_condition)
|
||||
.where(purchase_invoice.currency == currency)
|
||||
)
|
||||
|
||||
return str(query)
|
||||
return query
|
||||
|
||||
@@ -7,11 +7,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;
|
||||
@@ -38,20 +36,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
|
||||
@@ -93,15 +80,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)
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -118,13 +102,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());
|
||||
}
|
||||
@@ -166,24 +145,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);
|
||||
@@ -226,8 +205,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",
|
||||
@@ -240,7 +218,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
"description",
|
||||
"reference_number",
|
||||
"bank_account",
|
||||
"currency"
|
||||
"currency",
|
||||
],
|
||||
},
|
||||
});
|
||||
@@ -311,10 +289,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();
|
||||
@@ -330,19 +305,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"));
|
||||
},
|
||||
},
|
||||
@@ -376,8 +342,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);
|
||||
@@ -392,9 +357,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>`;
|
||||
@@ -413,10 +376,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})`;
|
||||
}
|
||||
@@ -455,36 +417,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("");
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -94,10 +94,13 @@ class BankTransaction(Document):
|
||||
pe.append(reference)
|
||||
|
||||
def update_allocated_amount(self):
|
||||
self.allocated_amount = (
|
||||
allocated_amount = (
|
||||
sum(p.allocated_amount for p in self.payment_entries) if self.payment_entries else 0.0
|
||||
)
|
||||
self.unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) - self.allocated_amount
|
||||
unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) - allocated_amount
|
||||
|
||||
self.allocated_amount = flt(allocated_amount, self.precision("allocated_amount"))
|
||||
self.unallocated_amount = flt(unallocated_amount, self.precision("unallocated_amount"))
|
||||
|
||||
def before_submit(self):
|
||||
self.allocate_payment_entries()
|
||||
|
||||
@@ -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"];
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -32,8 +32,16 @@ class TestBankTransaction(FrappeTestCase):
|
||||
frappe.db.delete(dt)
|
||||
clear_loan_transactions()
|
||||
make_pos_profile()
|
||||
add_transactions()
|
||||
add_vouchers()
|
||||
|
||||
# generate and use a uniq hash identifier for 'Bank Account' and it's linked GL 'Account' to avoid validation error
|
||||
uniq_identifier = frappe.generate_hash(length=10)
|
||||
gl_account = create_gl_account("_Test Bank " + uniq_identifier)
|
||||
bank_account = create_bank_account(
|
||||
gl_account=gl_account, bank_account_name="Checking Account " + uniq_identifier
|
||||
)
|
||||
|
||||
add_transactions(bank_account=bank_account)
|
||||
add_vouchers(gl_account=gl_account)
|
||||
|
||||
# This test checks if ERPNext is able to provide a linked payment for a bank transaction based on the amount of the bank transaction.
|
||||
def test_linked_payments(self):
|
||||
@@ -219,7 +227,9 @@ def clear_loan_transactions():
|
||||
frappe.db.delete("Loan Repayment")
|
||||
|
||||
|
||||
def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
|
||||
def create_bank_account(
|
||||
bank_name="Citi Bank", gl_account="_Test Bank - _TC", bank_account_name="Checking Account"
|
||||
):
|
||||
try:
|
||||
frappe.get_doc(
|
||||
{
|
||||
@@ -231,21 +241,35 @@ def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
|
||||
pass
|
||||
|
||||
try:
|
||||
frappe.get_doc(
|
||||
bank_account = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Bank Account",
|
||||
"account_name": "Checking Account",
|
||||
"account_name": bank_account_name,
|
||||
"bank": bank_name,
|
||||
"account": account_name,
|
||||
"account": gl_account,
|
||||
}
|
||||
).insert(ignore_if_duplicate=True)
|
||||
except frappe.DuplicateEntryError:
|
||||
pass
|
||||
|
||||
return bank_account.name
|
||||
|
||||
def add_transactions():
|
||||
create_bank_account()
|
||||
|
||||
def create_gl_account(gl_account_name="_Test Bank - _TC"):
|
||||
gl_account = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Account",
|
||||
"company": "_Test Company",
|
||||
"parent_account": "Current Assets - _TC",
|
||||
"account_type": "Bank",
|
||||
"is_group": 0,
|
||||
"account_name": gl_account_name,
|
||||
}
|
||||
).insert()
|
||||
return gl_account.name
|
||||
|
||||
|
||||
def add_transactions(bank_account="_Test Bank - _TC"):
|
||||
doc = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Bank Transaction",
|
||||
@@ -253,7 +277,7 @@ def add_transactions():
|
||||
"date": "2018-10-23",
|
||||
"deposit": 1200,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank",
|
||||
"bank_account": bank_account,
|
||||
}
|
||||
).insert()
|
||||
doc.submit()
|
||||
@@ -265,7 +289,7 @@ def add_transactions():
|
||||
"date": "2018-10-23",
|
||||
"deposit": 1700,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank",
|
||||
"bank_account": bank_account,
|
||||
}
|
||||
).insert()
|
||||
doc.submit()
|
||||
@@ -277,7 +301,7 @@ def add_transactions():
|
||||
"date": "2018-10-26",
|
||||
"withdrawal": 690,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank",
|
||||
"bank_account": bank_account,
|
||||
}
|
||||
).insert()
|
||||
doc.submit()
|
||||
@@ -289,7 +313,7 @@ def add_transactions():
|
||||
"date": "2018-10-27",
|
||||
"deposit": 3900,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank",
|
||||
"bank_account": bank_account,
|
||||
}
|
||||
).insert()
|
||||
doc.submit()
|
||||
@@ -301,13 +325,13 @@ def add_transactions():
|
||||
"date": "2018-10-27",
|
||||
"withdrawal": 109080,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank",
|
||||
"bank_account": bank_account,
|
||||
}
|
||||
).insert()
|
||||
doc.submit()
|
||||
|
||||
|
||||
def add_vouchers():
|
||||
def add_vouchers(gl_account="_Test Bank - _TC"):
|
||||
try:
|
||||
frappe.get_doc(
|
||||
{
|
||||
@@ -323,7 +347,7 @@ def add_vouchers():
|
||||
|
||||
pi = make_purchase_invoice(supplier="Conrad Electronic", qty=1, rate=690)
|
||||
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
|
||||
pe.reference_no = "Conrad Oct 18"
|
||||
pe.reference_date = "2018-10-24"
|
||||
pe.insert()
|
||||
@@ -342,14 +366,14 @@ def add_vouchers():
|
||||
pass
|
||||
|
||||
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1200)
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
|
||||
pe.reference_no = "Herr G Oct 18"
|
||||
pe.reference_date = "2018-10-24"
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1700)
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
|
||||
pe.reference_no = "Herr G Nov 18"
|
||||
pe.reference_date = "2018-11-01"
|
||||
pe.insert()
|
||||
@@ -380,10 +404,10 @@ def add_vouchers():
|
||||
pass
|
||||
|
||||
pi = make_purchase_invoice(supplier="Poore Simon's", qty=1, rate=3900, is_paid=1, do_not_save=1)
|
||||
pi.cash_bank_account = "_Test Bank - _TC"
|
||||
pi.cash_bank_account = gl_account
|
||||
pi.insert()
|
||||
pi.submit()
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
|
||||
pe.reference_no = "Poore Simon's Oct 18"
|
||||
pe.reference_date = "2018-10-28"
|
||||
pe.paid_amount = 690
|
||||
@@ -392,7 +416,7 @@ def add_vouchers():
|
||||
pe.submit()
|
||||
|
||||
si = create_sales_invoice(customer="Poore Simon's", qty=1, rate=3900)
|
||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
|
||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account=gl_account)
|
||||
pe.reference_no = "Poore Simon's Oct 18"
|
||||
pe.reference_date = "2018-10-28"
|
||||
pe.insert()
|
||||
@@ -415,16 +439,12 @@ def add_vouchers():
|
||||
if not frappe.db.get_value(
|
||||
"Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}
|
||||
):
|
||||
mode_of_payment.append(
|
||||
"accounts", {"company": "_Test Company", "default_account": "_Test Bank - _TC"}
|
||||
)
|
||||
mode_of_payment.append("accounts", {"company": "_Test Company", "default_account": gl_account})
|
||||
mode_of_payment.save()
|
||||
|
||||
si = create_sales_invoice(customer="Fayva", qty=1, rate=109080, do_not_save=1)
|
||||
si.is_pos = 1
|
||||
si.append(
|
||||
"payments", {"mode_of_payment": "Cash", "account": "_Test Bank - _TC", "amount": 109080}
|
||||
)
|
||||
si.append("payments", {"mode_of_payment": "Cash", "account": gl_account, "amount": 109080})
|
||||
si.insert()
|
||||
si.submit()
|
||||
|
||||
|
||||
@@ -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");
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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"))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Cost Center Number",
|
||||
"read_only": 1
|
||||
"read_only_depends_on": "eval:!doc.__islocal"
|
||||
},
|
||||
{
|
||||
"fieldname": "parent_cost_center",
|
||||
@@ -170,4 +170,4 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC",
|
||||
"states": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,19 +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) {
|
||||
let filters = {"is_group": 0};
|
||||
if (frm.doc.company) {
|
||||
$.extend(filters, {
|
||||
"company": frm.doc.company
|
||||
});
|
||||
}
|
||||
|
||||
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: filters
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
is_group: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
frm.set_query("cost_center", "allocation_percentages", function () {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
is_group: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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) {},
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"allow_import": 1,
|
||||
"autoname": "field:year",
|
||||
"creation": "2013-01-22 16:50:25",
|
||||
"description": "**Fiscal Year** represents a Financial Year. All accounting entries and other major transactions are tracked against **Fiscal Year**.",
|
||||
"description": "Represents a Financial Year. All accounting entries and other major transactions are tracked against the Fiscal Year.",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"engine": "InnoDB",
|
||||
@@ -82,10 +82,11 @@
|
||||
"icon": "fa fa-calendar",
|
||||
"idx": 1,
|
||||
"links": [],
|
||||
"modified": "2020-11-05 12:16:53.081573",
|
||||
"modified": "2024-01-30 12:35:38.645968",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Fiscal Year",
|
||||
"naming_rule": "By fieldname",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
@@ -122,5 +123,6 @@
|
||||
],
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "name",
|
||||
"sort_order": "DESC"
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
@@ -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();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -13,16 +13,9 @@ import erpnext
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||
get_checks_for_pl_and_bs_accounts,
|
||||
)
|
||||
from erpnext.accounts.doctype.accounting_dimension_filter.accounting_dimension_filter import (
|
||||
get_dimension_filter_map,
|
||||
)
|
||||
from erpnext.accounts.party import validate_party_frozen_disabled, validate_party_gle_currency
|
||||
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
|
||||
from erpnext.exceptions import (
|
||||
InvalidAccountCurrency,
|
||||
InvalidAccountDimensionError,
|
||||
MandatoryAccountDimensionError,
|
||||
)
|
||||
from erpnext.exceptions import InvalidAccountCurrency
|
||||
|
||||
exclude_from_linked_with = True
|
||||
|
||||
@@ -98,7 +91,6 @@ class GLEntry(Document):
|
||||
if not self.flags.from_repost and self.voucher_type != "Period Closing Voucher":
|
||||
self.validate_account_details(adv_adj)
|
||||
self.validate_dimensions_for_pl_and_bs()
|
||||
self.validate_allowed_dimensions()
|
||||
validate_balance_type(self.account, adv_adj)
|
||||
validate_frozen_account(self.account, adv_adj)
|
||||
|
||||
@@ -208,42 +200,6 @@ class GLEntry(Document):
|
||||
)
|
||||
)
|
||||
|
||||
def validate_allowed_dimensions(self):
|
||||
dimension_filter_map = get_dimension_filter_map()
|
||||
for key, value in dimension_filter_map.items():
|
||||
dimension = key[0]
|
||||
account = key[1]
|
||||
|
||||
if self.account == account:
|
||||
if value["is_mandatory"] and not self.get(dimension):
|
||||
frappe.throw(
|
||||
_("{0} is mandatory for account {1}").format(
|
||||
frappe.bold(frappe.unscrub(dimension)), frappe.bold(self.account)
|
||||
),
|
||||
MandatoryAccountDimensionError,
|
||||
)
|
||||
|
||||
if value["allow_or_restrict"] == "Allow":
|
||||
if self.get(dimension) and self.get(dimension) not in value["allowed_dimensions"]:
|
||||
frappe.throw(
|
||||
_("Invalid value {0} for {1} against account {2}").format(
|
||||
frappe.bold(self.get(dimension)),
|
||||
frappe.bold(frappe.unscrub(dimension)),
|
||||
frappe.bold(self.account),
|
||||
),
|
||||
InvalidAccountDimensionError,
|
||||
)
|
||||
else:
|
||||
if self.get(dimension) and self.get(dimension) in value["allowed_dimensions"]:
|
||||
frappe.throw(
|
||||
_("Invalid value {0} for {1} against account {2}").format(
|
||||
frappe.bold(self.get(dimension)),
|
||||
frappe.bold(frappe.unscrub(dimension)),
|
||||
frappe.bold(self.account),
|
||||
),
|
||||
InvalidAccountDimensionError,
|
||||
)
|
||||
|
||||
def check_pl_account(self):
|
||||
if (
|
||||
self.is_opening == "Yes"
|
||||
|
||||
@@ -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 Invocies')
|
||||
primary_action_label: __("Get Invocies"),
|
||||
});
|
||||
d.show();
|
||||
},
|
||||
|
||||
create_disbursement_entry: (frm) => {
|
||||
frappe.call({
|
||||
method:"create_disbursement_entry",
|
||||
method: "create_disbursement_entry",
|
||||
doc: frm.doc,
|
||||
callback: function(r) {
|
||||
if(!r.exc){
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
close_loan: (frm) => {
|
||||
frappe.call({
|
||||
method:"close_loan",
|
||||
method: "close_loan",
|
||||
doc: frm.doc,
|
||||
callback: function(r) {
|
||||
if(!r.exc){
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
show_general_ledger: (frm) => {
|
||||
if(frm.doc.docstatus > 0) {
|
||||
cur_frm.add_custom_button(__('Accounting Ledger'), function() {
|
||||
frappe.route_options = {
|
||||
voucher_no: frm.doc.name,
|
||||
from_date: frm.doc.posting_date,
|
||||
to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
|
||||
company: frm.doc.company,
|
||||
group_by: "Group by Voucher (Consolidated)",
|
||||
show_cancelled_entries: frm.doc.docstatus === 2
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}, __("View"));
|
||||
if (frm.doc.docstatus > 0) {
|
||||
cur_frm.add_custom_button(
|
||||
__("Accounting Ledger"),
|
||||
function () {
|
||||
frappe.route_options = {
|
||||
voucher_no: frm.doc.name,
|
||||
from_date: frm.doc.posting_date,
|
||||
to_date: moment(frm.doc.modified).format("YYYY-MM-DD"),
|
||||
company: frm.doc.company,
|
||||
group_by: "Group by Voucher (Consolidated)",
|
||||
show_cancelled_entries: frm.doc.docstatus === 2,
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
},
|
||||
__("View")
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Discounted Invoice', {
|
||||
frappe.ui.form.on("Discounted Invoice", {
|
||||
sales_invoice: (frm) => {
|
||||
frm.events.calculate_total_amount(frm);
|
||||
frm.events.refresh_filters(frm);
|
||||
@@ -212,5 +216,5 @@ frappe.ui.form.on('Discounted Invoice', {
|
||||
invoices_remove: (frm) => {
|
||||
frm.events.calculate_total_amount(frm);
|
||||
frm.events.refresh_filters(frm);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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"];
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
],
|
||||
],
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -4,39 +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.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.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");
|
||||
}
|
||||
|
||||
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 > 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.__islocal) {
|
||||
frm.add_custom_button(__('Quick Entry'), function() {
|
||||
frm.add_custom_button(__("Quick Entry"), function () {
|
||||
return erpnext.journal_entry.quick_entry(frm);
|
||||
});
|
||||
}
|
||||
@@ -44,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) {
|
||||
@@ -97,103 +151,106 @@ 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, "balance", d.balance)
|
||||
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() {
|
||||
this.load_defaults();
|
||||
this.setup_queries();
|
||||
this.setup_balance_formatter();
|
||||
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
|
||||
}
|
||||
|
||||
@@ -203,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");
|
||||
@@ -273,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";
|
||||
}
|
||||
|
||||
@@ -288,64 +343,49 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
|
||||
|
||||
return out;
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
setup_balance_formatter() {
|
||||
const formatter = function(value, df, options, doc) {
|
||||
var currency = frappe.meta.get_field_currency(df, doc);
|
||||
var dr_or_cr = value ? ('<label>' + (value > 0.0 ? __("Dr") : __("Cr")) + '</label>') : "";
|
||||
return "<div style='text-align: right'>"
|
||||
+ ((value==null || value==="") ? "" : format_currency(Math.abs(value), currency))
|
||||
+ " " + dr_or_cr
|
||||
+ "</div>";
|
||||
};
|
||||
this.frm.fields_dict.accounts.grid.update_docfield_property('balance', 'formatter', formatter);
|
||||
this.frm.fields_dict.accounts.grid.update_docfield_property('party_balance', 'formatter', formatter);
|
||||
}
|
||||
|
||||
reference_name(doc, cdt, cdn) {
|
||||
var d = frappe.get_doc(cdt, cdn);
|
||||
|
||||
if(d.reference_name) {
|
||||
if (d.reference_type==="Purchase Invoice" && !flt(d.debit)) {
|
||||
this.get_outstanding('Purchase Invoice', d.reference_name, doc.company, d);
|
||||
} else if (d.reference_type==="Sales Invoice" && !flt(d.credit)) {
|
||||
this.get_outstanding('Sales Invoice', d.reference_name, doc.company, d);
|
||||
} else if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
|
||||
this.get_outstanding('Journal Entry', d.reference_name, doc.company, d);
|
||||
if (d.reference_name) {
|
||||
if (d.reference_type === "Purchase Invoice" && !flt(d.debit)) {
|
||||
this.get_outstanding("Purchase Invoice", d.reference_name, doc.company, d);
|
||||
} else if (d.reference_type === "Sales Invoice" && !flt(d.credit)) {
|
||||
this.get_outstanding("Sales Invoice", d.reference_name, doc.company, d);
|
||||
} else if (d.reference_type === "Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
|
||||
this.get_outstanding("Journal Entry", d.reference_name, doc.company, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get_outstanding(doctype, docname, company, child) {
|
||||
var args = {
|
||||
"doctype": doctype,
|
||||
"docname": docname,
|
||||
"party": child.party,
|
||||
"account": child.account,
|
||||
"account_currency": child.account_currency,
|
||||
"company": company
|
||||
}
|
||||
doctype: doctype,
|
||||
docname: docname,
|
||||
party: child.party,
|
||||
account: child.account,
|
||||
account_currency: child.account_currency,
|
||||
company: company,
|
||||
};
|
||||
|
||||
return frappe.call({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_outstanding",
|
||||
args: { args: args},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
$.each(r.message, function(field, value) {
|
||||
args: { args: args },
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
$.each(r.message, function (field, value) {
|
||||
frappe.model.set_value(child.doctype, child.name, field, value);
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
accounts_add(doc, cdt, cdn) {
|
||||
var row = frappe.get_doc(cdt, cdn);
|
||||
$.each(doc.accounts, function(i, d) {
|
||||
if(d.account && d.party && d.party_type) {
|
||||
$.each(doc.accounts, function (i, d) {
|
||||
if (d.account && d.party && d.party_type) {
|
||||
row.account = d.account;
|
||||
row.party = d.party;
|
||||
row.party_type = d.party_type;
|
||||
@@ -353,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 {
|
||||
@@ -364,132 +404,141 @@ 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_balance",
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_party_account_and_currency",
|
||||
child: d,
|
||||
args: {
|
||||
company: frm.doc.company,
|
||||
party_type: d.party_type,
|
||||
party: d.party,
|
||||
cost_center: d.cost_center
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
cost_center: function(frm, dt, dn) {
|
||||
erpnext.journal_entry.set_account_balance(frm, dt, dn);
|
||||
cost_center: function (frm, dt, dn) {
|
||||
erpnext.journal_entry.set_account_details(frm, dt, dn);
|
||||
},
|
||||
|
||||
account: function(frm, dt, dn) {
|
||||
erpnext.journal_entry.set_account_balance(frm, dt, dn);
|
||||
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") {
|
||||
@@ -504,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();
|
||||
|
||||
@@ -564,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();
|
||||
|
||||
@@ -578,36 +657,39 @@ $.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_balance: 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_balance_and_party_type",
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_details_and_party_type",
|
||||
args: {
|
||||
account: d.account,
|
||||
date: frm.doc.posting_date,
|
||||
@@ -615,15 +697,14 @@ $.extend(erpnext.journal_entry, {
|
||||
debit: flt(d.debit_in_account_currency),
|
||||
credit: flt(d.credit_in_account_currency),
|
||||
exchange_rate: d.exchange_rate,
|
||||
cost_center: d.cost_center
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
$.extend(d, r.message);
|
||||
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, dt, dn);
|
||||
refresh_field('accounts');
|
||||
refresh_field("accounts");
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -64,7 +64,8 @@
|
||||
"stock_entry",
|
||||
"subscription_section",
|
||||
"auto_repeat",
|
||||
"amended_from"
|
||||
"amended_from",
|
||||
"repost_required"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -543,6 +544,15 @@
|
||||
"label": "Is System Generated",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "repost_required",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Repost Required",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-file-text",
|
||||
|
||||
@@ -13,6 +13,10 @@ from erpnext.accounts.deferred_revenue import get_deferred_booking_accounts
|
||||
from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import (
|
||||
get_party_account_based_on_invoice_discounting,
|
||||
)
|
||||
from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import (
|
||||
validate_docs_for_deferred_accounting,
|
||||
validate_docs_for_voucher_types,
|
||||
)
|
||||
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import (
|
||||
get_party_tax_withholding_details,
|
||||
)
|
||||
@@ -140,7 +144,6 @@ class JournalEntry(AccountsController):
|
||||
self.set_print_format_fields()
|
||||
self.validate_credit_debit_note()
|
||||
self.validate_empty_accounts_table()
|
||||
self.set_account_and_party_balance()
|
||||
self.validate_inter_company_accounts()
|
||||
self.validate_depr_entry_voucher_type()
|
||||
|
||||
@@ -150,6 +153,24 @@ class JournalEntry(AccountsController):
|
||||
if not self.title:
|
||||
self.title = self.get_title()
|
||||
|
||||
def validate_for_repost(self):
|
||||
validate_docs_for_voucher_types(["Journal Entry"])
|
||||
validate_docs_for_deferred_accounting([self.name], [])
|
||||
|
||||
def submit(self):
|
||||
if len(self.accounts) > 100:
|
||||
msgprint(_("The task has been enqueued as a background job."), alert=True)
|
||||
self.queue_action("submit", timeout=4600)
|
||||
else:
|
||||
return self._submit()
|
||||
|
||||
def cancel(self):
|
||||
if len(self.accounts) > 100:
|
||||
msgprint(_("The task has been enqueued as a background job."), alert=True)
|
||||
self.queue_action("cancel", timeout=4600)
|
||||
else:
|
||||
return self._cancel()
|
||||
|
||||
def on_submit(self):
|
||||
self.validate_cheque_info()
|
||||
self.check_credit_limit()
|
||||
@@ -159,6 +180,15 @@ class JournalEntry(AccountsController):
|
||||
self.update_inter_company_jv()
|
||||
self.update_invoice_discounting()
|
||||
|
||||
def on_update_after_submit(self):
|
||||
if hasattr(self, "repost_required"):
|
||||
self.needs_repost = self.check_if_fields_updated(
|
||||
fields_to_check=[], child_tables={"accounts": []}
|
||||
)
|
||||
if self.needs_repost:
|
||||
self.validate_for_repost()
|
||||
self.db_set("repost_required", self.needs_repost)
|
||||
|
||||
def on_cancel(self):
|
||||
# References for this Journal are removed on the `on_cancel` event in accounts_controller
|
||||
super(JournalEntry, self).on_cancel()
|
||||
@@ -545,17 +575,28 @@ class JournalEntry(AccountsController):
|
||||
elif d.party_type == "Supplier" and flt(d.credit) > 0:
|
||||
frappe.throw(_("Row {0}: Advance against Supplier must be debit").format(d.idx))
|
||||
|
||||
def system_generated_gain_loss(self):
|
||||
return (
|
||||
self.voucher_type == "Exchange Gain Or Loss"
|
||||
and self.multi_currency
|
||||
and self.is_system_generated
|
||||
)
|
||||
|
||||
def validate_against_jv(self):
|
||||
for d in self.get("accounts"):
|
||||
if d.reference_type == "Journal Entry":
|
||||
account_root_type = frappe.get_cached_value("Account", d.account, "root_type")
|
||||
if account_root_type == "Asset" and flt(d.debit) > 0:
|
||||
if account_root_type == "Asset" and flt(d.debit) > 0 and not self.system_generated_gain_loss():
|
||||
frappe.throw(
|
||||
_(
|
||||
"Row #{0}: For {1}, you can select reference document only if account gets credited"
|
||||
).format(d.idx, d.account)
|
||||
)
|
||||
elif account_root_type == "Liability" and flt(d.credit) > 0:
|
||||
elif (
|
||||
account_root_type == "Liability"
|
||||
and flt(d.credit) > 0
|
||||
and not self.system_generated_gain_loss()
|
||||
):
|
||||
frappe.throw(
|
||||
_(
|
||||
"Row #{0}: For {1}, you can select reference document only if account gets debited"
|
||||
@@ -587,7 +628,7 @@ class JournalEntry(AccountsController):
|
||||
for jvd in against_entries:
|
||||
if flt(jvd[dr_or_cr]) > 0:
|
||||
valid = True
|
||||
if not valid:
|
||||
if not valid and not self.system_generated_gain_loss():
|
||||
frappe.throw(
|
||||
_("Against Journal Entry {0} does not have any unmatched {1} entry").format(
|
||||
d.reference_name, dr_or_cr
|
||||
@@ -1135,21 +1176,6 @@ class JournalEntry(AccountsController):
|
||||
if not self.get("accounts"):
|
||||
frappe.throw(_("Accounts table cannot be blank."))
|
||||
|
||||
def set_account_and_party_balance(self):
|
||||
account_balance = {}
|
||||
party_balance = {}
|
||||
for d in self.get("accounts"):
|
||||
if d.account not in account_balance:
|
||||
account_balance[d.account] = get_balance_on(account=d.account, date=self.posting_date)
|
||||
|
||||
if (d.party_type, d.party) not in party_balance:
|
||||
party_balance[(d.party_type, d.party)] = get_balance_on(
|
||||
party_type=d.party_type, party=d.party, date=self.posting_date, company=self.company
|
||||
)
|
||||
|
||||
d.account_balance = account_balance[d.account]
|
||||
d.party_balance = party_balance[(d.party_type, d.party)]
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_default_bank_cash_account(company, account_type=None, mode_of_payment=None, account=None):
|
||||
@@ -1315,8 +1341,6 @@ def get_payment_entry(ref_doc, args):
|
||||
"account_type": frappe.get_cached_value("Account", args.get("party_account"), "account_type"),
|
||||
"account_currency": args.get("party_account_currency")
|
||||
or get_account_currency(args.get("party_account")),
|
||||
"balance": get_balance_on(args.get("party_account")),
|
||||
"party_balance": get_balance_on(party=args.get("party"), party_type=args.get("party_type")),
|
||||
"exchange_rate": exchange_rate,
|
||||
args.get("amount_field_party"): args.get("amount"),
|
||||
"is_advance": args.get("is_advance"),
|
||||
@@ -1464,30 +1488,23 @@ def get_outstanding(args):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_party_account_and_balance(company, party_type, party, cost_center=None):
|
||||
def get_party_account_and_currency(company, party_type, party):
|
||||
if not frappe.has_permission("Account"):
|
||||
frappe.msgprint(_("No Permission"), raise_exception=1)
|
||||
|
||||
account = get_party_account(party_type, party, company)
|
||||
|
||||
account_balance = get_balance_on(account=account, cost_center=cost_center)
|
||||
party_balance = get_balance_on(
|
||||
party_type=party_type, party=party, company=company, cost_center=cost_center
|
||||
)
|
||||
|
||||
return {
|
||||
"account": account,
|
||||
"balance": account_balance,
|
||||
"party_balance": party_balance,
|
||||
"account_currency": frappe.get_cached_value("Account", account, "account_currency"),
|
||||
}
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_account_balance_and_party_type(
|
||||
account, date, company, debit=None, credit=None, exchange_rate=None, cost_center=None
|
||||
def get_account_details_and_party_type(
|
||||
account, date, company, debit=None, credit=None, exchange_rate=None
|
||||
):
|
||||
"""Returns dict of account balance and party type to be set in Journal Entry on selection of account."""
|
||||
"""Returns dict of account details and party type to be set in Journal Entry on selection of account."""
|
||||
if not frappe.has_permission("Account"):
|
||||
frappe.msgprint(_("No Permission"), raise_exception=1)
|
||||
|
||||
@@ -1507,7 +1524,6 @@ def get_account_balance_and_party_type(
|
||||
party_type = ""
|
||||
|
||||
grid_values = {
|
||||
"balance": get_balance_on(account, date, cost_center=cost_center),
|
||||
"party_type": party_type,
|
||||
"account_type": account_details.account_type,
|
||||
"account_currency": account_details.account_currency or company_currency,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
frappe.listview_settings['Journal Entry'] = {
|
||||
frappe.listview_settings["Journal Entry"] = {
|
||||
add_fields: ["voucher_type", "posting_date", "total_debit", "company", "user_remark"],
|
||||
get_indicator: function(doc) {
|
||||
if(doc.docstatus==0) {
|
||||
return [__("Draft", "red", "docstatus,=,0")]
|
||||
} else if(doc.docstatus==2) {
|
||||
return [__("Cancelled", "grey", "docstatus,=,2")]
|
||||
get_indicator: function (doc) {
|
||||
if (doc.docstatus == 0) {
|
||||
return [__("Draft", "red", "docstatus,=,0")];
|
||||
} else if (doc.docstatus == 2) {
|
||||
return [__("Cancelled", "grey", "docstatus,=,2")];
|
||||
} else {
|
||||
return [__(doc.voucher_type), "blue", "voucher_type,=," + doc.voucher_type]
|
||||
return [__(doc.voucher_type), "blue", "voucher_type,=," + doc.voucher_type];
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -166,43 +166,37 @@ class TestJournalEntry(unittest.TestCase):
|
||||
jv.get("accounts")[1].credit_in_account_currency = 5000
|
||||
jv.submit()
|
||||
|
||||
gl_entries = frappe.db.sql(
|
||||
"""select account, account_currency, debit, credit,
|
||||
debit_in_account_currency, credit_in_account_currency
|
||||
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
|
||||
order by account asc""",
|
||||
jv.name,
|
||||
as_dict=1,
|
||||
)
|
||||
self.voucher_no = jv.name
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
self.fields = [
|
||||
"account",
|
||||
"account_currency",
|
||||
"debit",
|
||||
"debit_in_account_currency",
|
||||
"credit",
|
||||
"credit_in_account_currency",
|
||||
]
|
||||
|
||||
expected_values = {
|
||||
"_Test Bank USD - _TC": {
|
||||
"account_currency": "USD",
|
||||
"debit": 5000,
|
||||
"debit_in_account_currency": 100,
|
||||
"credit": 0,
|
||||
"credit_in_account_currency": 0,
|
||||
},
|
||||
"_Test Bank - _TC": {
|
||||
self.expected_gle = [
|
||||
{
|
||||
"account": "_Test Bank - _TC",
|
||||
"account_currency": "INR",
|
||||
"debit": 0,
|
||||
"debit_in_account_currency": 0,
|
||||
"credit": 5000,
|
||||
"credit_in_account_currency": 5000,
|
||||
},
|
||||
}
|
||||
{
|
||||
"account": "_Test Bank USD - _TC",
|
||||
"account_currency": "USD",
|
||||
"debit": 5000,
|
||||
"debit_in_account_currency": 100,
|
||||
"credit": 0,
|
||||
"credit_in_account_currency": 0,
|
||||
},
|
||||
]
|
||||
|
||||
for field in (
|
||||
"account_currency",
|
||||
"debit",
|
||||
"debit_in_account_currency",
|
||||
"credit",
|
||||
"credit_in_account_currency",
|
||||
):
|
||||
for i, gle in enumerate(gl_entries):
|
||||
self.assertEqual(expected_values[gle.account][field], gle[field])
|
||||
self.check_gl_entries()
|
||||
|
||||
# cancel
|
||||
jv.cancel()
|
||||
@@ -228,43 +222,37 @@ class TestJournalEntry(unittest.TestCase):
|
||||
rjv.posting_date = nowdate()
|
||||
rjv.submit()
|
||||
|
||||
gl_entries = frappe.db.sql(
|
||||
"""select account, account_currency, debit, credit,
|
||||
debit_in_account_currency, credit_in_account_currency
|
||||
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
|
||||
order by account asc""",
|
||||
rjv.name,
|
||||
as_dict=1,
|
||||
)
|
||||
self.voucher_no = rjv.name
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
self.fields = [
|
||||
"account",
|
||||
"account_currency",
|
||||
"debit",
|
||||
"credit",
|
||||
"debit_in_account_currency",
|
||||
"credit_in_account_currency",
|
||||
]
|
||||
|
||||
expected_values = {
|
||||
"_Test Bank USD - _TC": {
|
||||
self.expected_gle = [
|
||||
{
|
||||
"account": "_Test Bank USD - _TC",
|
||||
"account_currency": "USD",
|
||||
"debit": 0,
|
||||
"debit_in_account_currency": 0,
|
||||
"credit": 5000,
|
||||
"credit_in_account_currency": 100,
|
||||
},
|
||||
"Sales - _TC": {
|
||||
{
|
||||
"account": "Sales - _TC",
|
||||
"account_currency": "INR",
|
||||
"debit": 5000,
|
||||
"debit_in_account_currency": 5000,
|
||||
"credit": 0,
|
||||
"credit_in_account_currency": 0,
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
for field in (
|
||||
"account_currency",
|
||||
"debit",
|
||||
"debit_in_account_currency",
|
||||
"credit",
|
||||
"credit_in_account_currency",
|
||||
):
|
||||
for i, gle in enumerate(gl_entries):
|
||||
self.assertEqual(expected_values[gle.account][field], gle[field])
|
||||
self.check_gl_entries()
|
||||
|
||||
def test_disallow_change_in_account_currency_for_a_party(self):
|
||||
# create jv in USD
|
||||
@@ -344,23 +332,25 @@ class TestJournalEntry(unittest.TestCase):
|
||||
jv.insert()
|
||||
jv.submit()
|
||||
|
||||
expected_values = {
|
||||
"_Test Cash - _TC": {"cost_center": cost_center},
|
||||
"_Test Bank - _TC": {"cost_center": cost_center},
|
||||
}
|
||||
self.voucher_no = jv.name
|
||||
|
||||
gl_entries = frappe.db.sql(
|
||||
"""select account, cost_center, debit, credit
|
||||
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
|
||||
order by account asc""",
|
||||
jv.name,
|
||||
as_dict=1,
|
||||
)
|
||||
self.fields = [
|
||||
"account",
|
||||
"cost_center",
|
||||
]
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
self.expected_gle = [
|
||||
{
|
||||
"account": "_Test Bank - _TC",
|
||||
"cost_center": cost_center,
|
||||
},
|
||||
{
|
||||
"account": "_Test Cash - _TC",
|
||||
"cost_center": cost_center,
|
||||
},
|
||||
]
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
self.check_gl_entries()
|
||||
|
||||
def test_jv_with_project(self):
|
||||
from erpnext.projects.doctype.project.test_project import make_project
|
||||
@@ -387,23 +377,22 @@ class TestJournalEntry(unittest.TestCase):
|
||||
jv.insert()
|
||||
jv.submit()
|
||||
|
||||
expected_values = {
|
||||
"_Test Cash - _TC": {"project": project_name},
|
||||
"_Test Bank - _TC": {"project": project_name},
|
||||
}
|
||||
self.voucher_no = jv.name
|
||||
|
||||
gl_entries = frappe.db.sql(
|
||||
"""select account, project, debit, credit
|
||||
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
|
||||
order by account asc""",
|
||||
jv.name,
|
||||
as_dict=1,
|
||||
)
|
||||
self.fields = ["account", "project"]
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
self.expected_gle = [
|
||||
{
|
||||
"account": "_Test Bank - _TC",
|
||||
"project": project_name,
|
||||
},
|
||||
{
|
||||
"account": "_Test Cash - _TC",
|
||||
"project": project_name,
|
||||
},
|
||||
]
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["project"], gle.project)
|
||||
self.check_gl_entries()
|
||||
|
||||
def test_jv_account_and_party_balance_with_cost_centre(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
@@ -426,6 +415,79 @@ class TestJournalEntry(unittest.TestCase):
|
||||
account_balance = get_balance_on(account="_Test Bank - _TC", cost_center=cost_center)
|
||||
self.assertEqual(expected_account_balance, account_balance)
|
||||
|
||||
def test_repost_accounting_entries(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
|
||||
# Configure Repost Accounting Ledger for JVs
|
||||
settings = frappe.get_doc("Repost Accounting Ledger Settings")
|
||||
if not [x for x in settings.allowed_types if x.document_type == "Journal Entry"]:
|
||||
settings.append("allowed_types", {"document_type": "Journal Entry", "allowed": True})
|
||||
settings.save()
|
||||
|
||||
# Create JV with defaut cost center - _Test Cost Center
|
||||
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, save=False)
|
||||
jv.multi_currency = 0
|
||||
jv.submit()
|
||||
|
||||
# Check GL entries before reposting
|
||||
self.voucher_no = jv.name
|
||||
|
||||
self.fields = [
|
||||
"account",
|
||||
"debit_in_account_currency",
|
||||
"credit_in_account_currency",
|
||||
"cost_center",
|
||||
]
|
||||
|
||||
self.expected_gle = [
|
||||
{
|
||||
"account": "_Test Bank - _TC",
|
||||
"debit_in_account_currency": 0,
|
||||
"credit_in_account_currency": 100,
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
},
|
||||
{
|
||||
"account": "_Test Cash - _TC",
|
||||
"debit_in_account_currency": 100,
|
||||
"credit_in_account_currency": 0,
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
},
|
||||
]
|
||||
|
||||
self.check_gl_entries()
|
||||
|
||||
# Change cost center for bank account - _Test Cost Center for BS Account
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
jv.accounts[1].cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
jv.save()
|
||||
|
||||
# Check if repost flag gets set on update after submit
|
||||
self.assertTrue(jv.repost_required)
|
||||
jv.repost_accounting_entries()
|
||||
|
||||
# Check GL entries after reposting
|
||||
jv.load_from_db()
|
||||
self.expected_gle[0]["cost_center"] = "_Test Cost Center for BS Account - _TC"
|
||||
self.check_gl_entries()
|
||||
|
||||
def check_gl_entries(self):
|
||||
gl = frappe.qb.DocType("GL Entry")
|
||||
query = frappe.qb.from_(gl)
|
||||
for field in self.fields:
|
||||
query = query.select(gl[field])
|
||||
|
||||
query = query.where(
|
||||
(gl.voucher_type == "Journal Entry")
|
||||
& (gl.voucher_no == self.voucher_no)
|
||||
& (gl.is_cancelled == 0)
|
||||
).orderby(gl.account)
|
||||
|
||||
gl_entries = query.run(as_dict=True)
|
||||
|
||||
for i in range(len(self.expected_gle)):
|
||||
for field in self.fields:
|
||||
self.assertEqual(self.expected_gle[i][field], gl_entries[i][field])
|
||||
|
||||
|
||||
def make_journal_entry(
|
||||
account1,
|
||||
|
||||
@@ -9,12 +9,10 @@
|
||||
"field_order": [
|
||||
"account",
|
||||
"account_type",
|
||||
"balance",
|
||||
"col_break1",
|
||||
"bank_account",
|
||||
"party_type",
|
||||
"party",
|
||||
"party_balance",
|
||||
"accounting_dimensions_section",
|
||||
"cost_center",
|
||||
"dimension_col_break",
|
||||
@@ -64,17 +62,7 @@
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "balance",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Account Balance",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "balance",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "account_currency",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"default": ":Company",
|
||||
"description": "If Income or Expense",
|
||||
"fieldname": "cost_center",
|
||||
@@ -107,14 +95,6 @@
|
||||
"label": "Party",
|
||||
"options": "party_type"
|
||||
},
|
||||
{
|
||||
"fieldname": "party_balance",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Party Balance",
|
||||
"options": "account_currency",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "currency_section",
|
||||
"fieldtype": "Section Break",
|
||||
@@ -223,6 +203,7 @@
|
||||
"no_copy": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"fieldname": "project",
|
||||
"fieldtype": "Link",
|
||||
"label": "Project",
|
||||
@@ -287,7 +268,7 @@
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2023-11-23 11:44:25.841187",
|
||||
"modified": "2024-02-05 01:10:50.224840",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Entry Account",
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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");
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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) {},
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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],
|
||||
],
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,173 +1,77 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "field:distribution_id",
|
||||
"beta": 0,
|
||||
"creation": "2013-01-10 16:34:05",
|
||||
"custom": 0,
|
||||
"description": "**Monthly Distribution** helps you distribute the Budget/Target across months if you have seasonality in your business.",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 0,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"autoname": "field:distribution_id",
|
||||
"creation": "2013-01-10 16:34:05",
|
||||
"description": "Helps you distribute the Budget/Target across months if you have seasonality in your business.",
|
||||
"doctype": "DocType",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"distribution_id",
|
||||
"fiscal_year",
|
||||
"percentages"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Name of the Monthly Distribution",
|
||||
"fieldname": "distribution_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Distribution Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "distribution_id",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"description": "Name of the Monthly Distribution",
|
||||
"fieldname": "distribution_id",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Distribution Name",
|
||||
"oldfieldname": "distribution_id",
|
||||
"oldfieldtype": "Data",
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "fiscal_year",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Fiscal Year",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "fiscal_year",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Fiscal Year",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "fiscal_year",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Fiscal Year",
|
||||
"oldfieldname": "fiscal_year",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Fiscal Year",
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "percentages",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Monthly Distribution Percentages",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "budget_distribution_details",
|
||||
"oldfieldtype": "Table",
|
||||
"options": "Monthly Distribution Percentage",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
"fieldname": "percentages",
|
||||
"fieldtype": "Table",
|
||||
"label": "Monthly Distribution Percentages",
|
||||
"oldfieldname": "budget_distribution_details",
|
||||
"oldfieldtype": "Table",
|
||||
"options": "Monthly Distribution Percentage"
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-bar-chart",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-11-21 14:54:35.998761",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Monthly Distribution",
|
||||
"name_case": "Title Case",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"icon": "fa fa-bar-chart",
|
||||
"idx": 1,
|
||||
"links": [],
|
||||
"modified": "2024-01-30 13:57:55.802744",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Monthly Distribution",
|
||||
"naming_rule": "By fieldname",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 2,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
"permlevel": 2,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager"
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_seen": 0
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
@@ -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");
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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
@@ -87,12 +87,14 @@
|
||||
"status",
|
||||
"custom_remarks",
|
||||
"remarks",
|
||||
"base_in_words",
|
||||
"column_break_16",
|
||||
"letter_head",
|
||||
"print_heading",
|
||||
"bank",
|
||||
"bank_account_no",
|
||||
"payment_order",
|
||||
"in_words",
|
||||
"subscription_section",
|
||||
"auto_repeat",
|
||||
"amended_from",
|
||||
@@ -746,6 +748,20 @@
|
||||
"hidden": 1,
|
||||
"label": "Book Advance Payments in Separate Party Account",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "base_in_words",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "In Words (Company Currency)",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "in_words",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "In Words",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
@@ -759,7 +775,7 @@
|
||||
"table_fieldname": "payment_entries"
|
||||
}
|
||||
],
|
||||
"modified": "2023-11-23 12:07:20.887885",
|
||||
"modified": "2024-01-03 12:46:41.759121",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Entry",
|
||||
|
||||
@@ -13,6 +13,7 @@ from pypika import Case
|
||||
from pypika.functions import Coalesce, Sum
|
||||
|
||||
import erpnext
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_dimensions
|
||||
from erpnext.accounts.doctype.bank_account.bank_account import (
|
||||
get_bank_account_details,
|
||||
get_party_bank_account,
|
||||
@@ -95,6 +96,7 @@ class PaymentEntry(AccountsController):
|
||||
self.validate_paid_invoices()
|
||||
self.ensure_supplier_is_not_blocked()
|
||||
self.set_status()
|
||||
self.set_total_in_words()
|
||||
|
||||
def on_submit(self):
|
||||
if self.difference_amount:
|
||||
@@ -107,7 +109,7 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
def set_liability_account(self):
|
||||
# Auto setting liability account should only be done during 'draft' status
|
||||
if self.docstatus > 0:
|
||||
if self.docstatus > 0 or self.payment_type == "Internal Transfer":
|
||||
return
|
||||
|
||||
if not frappe.db.get_value(
|
||||
@@ -387,7 +389,10 @@ class PaymentEntry(AccountsController):
|
||||
)
|
||||
|
||||
def set_missing_ref_details(
|
||||
self, force: bool = False, update_ref_details_only_for: list | None = None
|
||||
self,
|
||||
force: bool = False,
|
||||
update_ref_details_only_for: list | None = None,
|
||||
ref_exchange_rate: float | None = None,
|
||||
) -> None:
|
||||
for d in self.get("references"):
|
||||
if d.allocated_amount:
|
||||
@@ -399,6 +404,8 @@ class PaymentEntry(AccountsController):
|
||||
ref_details = get_reference_details(
|
||||
d.reference_doctype, d.reference_name, self.party_account_currency
|
||||
)
|
||||
if ref_exchange_rate:
|
||||
ref_details.update({"exchange_rate": ref_exchange_rate})
|
||||
|
||||
for field, value in ref_details.items():
|
||||
if d.exchange_gain_loss:
|
||||
@@ -702,6 +709,21 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
self.db_set("status", self.status, update_modified=True)
|
||||
|
||||
def set_total_in_words(self):
|
||||
from frappe.utils import money_in_words
|
||||
|
||||
if self.payment_type in ("Pay", "Internal Transfer"):
|
||||
base_amount = abs(self.base_paid_amount)
|
||||
amount = abs(self.paid_amount)
|
||||
currency = self.paid_from_account_currency
|
||||
elif self.payment_type == "Receive":
|
||||
base_amount = abs(self.base_received_amount)
|
||||
amount = abs(self.received_amount)
|
||||
currency = self.paid_to_account_currency
|
||||
|
||||
self.base_in_words = money_in_words(base_amount, self.company_currency)
|
||||
self.in_words = money_in_words(amount, currency)
|
||||
|
||||
def set_tax_withholding(self):
|
||||
if not self.party_type == "Supplier":
|
||||
return
|
||||
@@ -929,19 +951,19 @@ class PaymentEntry(AccountsController):
|
||||
)
|
||||
|
||||
base_party_amount = flt(self.base_total_allocated_amount) + flt(base_unallocated_amount)
|
||||
|
||||
if self.payment_type == "Receive":
|
||||
self.difference_amount = base_party_amount - self.base_received_amount
|
||||
elif self.payment_type == "Pay":
|
||||
self.difference_amount = self.base_paid_amount - base_party_amount
|
||||
else:
|
||||
self.difference_amount = self.base_paid_amount - flt(self.base_received_amount)
|
||||
|
||||
total_deductions = sum(flt(d.amount) for d in self.get("deductions"))
|
||||
included_taxes = self.get_included_taxes()
|
||||
|
||||
if self.payment_type == "Receive":
|
||||
self.difference_amount = base_party_amount - self.base_received_amount + included_taxes
|
||||
elif self.payment_type == "Pay":
|
||||
self.difference_amount = self.base_paid_amount - base_party_amount - included_taxes
|
||||
else:
|
||||
self.difference_amount = self.base_paid_amount - flt(self.base_received_amount) - included_taxes
|
||||
|
||||
total_deductions = sum(flt(d.amount) for d in self.get("deductions"))
|
||||
|
||||
self.difference_amount = flt(
|
||||
self.difference_amount - total_deductions - included_taxes, self.precision("difference_amount")
|
||||
self.difference_amount - total_deductions, self.precision("difference_amount")
|
||||
)
|
||||
|
||||
def get_included_taxes(self):
|
||||
@@ -1163,7 +1185,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):
|
||||
@@ -1177,14 +1205,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
|
||||
@@ -1588,6 +1617,13 @@ def get_outstanding_reference_documents(args, validate=False):
|
||||
condition += " and cost_center='%s'" % args.get("cost_center")
|
||||
accounting_dimensions_filter.append(ple.cost_center == args.get("cost_center"))
|
||||
|
||||
# dynamic dimension filters
|
||||
active_dimensions = get_dimensions()[0]
|
||||
for dim in active_dimensions:
|
||||
if args.get(dim.fieldname):
|
||||
condition += " and {0}='{1}'".format(dim.fieldname, args.get(dim.fieldname))
|
||||
accounting_dimensions_filter.append(ple[dim.fieldname] == args.get(dim.fieldname))
|
||||
|
||||
date_fields_dict = {
|
||||
"posting_date": ["from_posting_date", "to_posting_date"],
|
||||
"due_date": ["from_due_date", "to_due_date"],
|
||||
@@ -1821,6 +1857,12 @@ def get_orders_to_be_billed(
|
||||
if doc and hasattr(doc, "cost_center") and doc.cost_center:
|
||||
condition = " and cost_center='%s'" % cost_center
|
||||
|
||||
# dynamic dimension filters
|
||||
active_dimensions = get_dimensions()[0]
|
||||
for dim in active_dimensions:
|
||||
if filters.get(dim.fieldname):
|
||||
condition += " and {0}='{1}'".format(dim.fieldname, filters.get(dim.fieldname))
|
||||
|
||||
if party_account_currency == company_currency:
|
||||
grand_total_field = "base_grand_total"
|
||||
rounded_total_field = "base_rounded_total"
|
||||
@@ -2073,6 +2115,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)
|
||||
|
||||
@@ -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)],
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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) {
|
||||
|
||||
// }
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
},
|
||||
|
||||
@@ -4,9 +4,13 @@
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
from frappe.tests.utils import FrappeTestCase
|
||||
from frappe.utils import getdate
|
||||
|
||||
from erpnext.accounts.doctype.bank_transaction.test_bank_transaction import create_bank_account
|
||||
from erpnext.accounts.doctype.bank_transaction.test_bank_transaction import (
|
||||
create_bank_account,
|
||||
create_gl_account,
|
||||
)
|
||||
from erpnext.accounts.doctype.payment_entry.payment_entry import (
|
||||
get_payment_entry,
|
||||
make_payment_order,
|
||||
@@ -14,28 +18,32 @@ from erpnext.accounts.doctype.payment_entry.payment_entry import (
|
||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||
|
||||
|
||||
class TestPaymentOrder(unittest.TestCase):
|
||||
class TestPaymentOrder(FrappeTestCase):
|
||||
def setUp(self):
|
||||
create_bank_account()
|
||||
# generate and use a uniq hash identifier for 'Bank Account' and it's linked GL 'Account' to avoid validation error
|
||||
uniq_identifier = frappe.generate_hash(length=10)
|
||||
self.gl_account = create_gl_account("_Test Bank " + uniq_identifier)
|
||||
self.bank_account = create_bank_account(
|
||||
gl_account=self.gl_account, bank_account_name="Checking Account " + uniq_identifier
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
for bt in frappe.get_all("Payment Order"):
|
||||
doc = frappe.get_doc("Payment Order", bt.name)
|
||||
doc.cancel()
|
||||
doc.delete()
|
||||
frappe.db.rollback()
|
||||
|
||||
def test_payment_order_creation_against_payment_entry(self):
|
||||
purchase_invoice = make_purchase_invoice()
|
||||
payment_entry = get_payment_entry(
|
||||
"Purchase Invoice", purchase_invoice.name, bank_account="_Test Bank - _TC"
|
||||
"Purchase Invoice", purchase_invoice.name, bank_account=self.gl_account
|
||||
)
|
||||
payment_entry.reference_no = "_Test_Payment_Order"
|
||||
payment_entry.reference_date = getdate()
|
||||
payment_entry.party_bank_account = "Checking Account - Citi Bank"
|
||||
payment_entry.party_bank_account = self.bank_account
|
||||
payment_entry.insert()
|
||||
payment_entry.submit()
|
||||
|
||||
doc = create_payment_order_against_payment_entry(payment_entry, "Payment Entry")
|
||||
doc = create_payment_order_against_payment_entry(
|
||||
payment_entry, "Payment Entry", self.bank_account
|
||||
)
|
||||
reference_doc = doc.get("references")[0]
|
||||
self.assertEqual(reference_doc.reference_name, payment_entry.name)
|
||||
self.assertEqual(reference_doc.reference_doctype, "Payment Entry")
|
||||
@@ -43,13 +51,13 @@ class TestPaymentOrder(unittest.TestCase):
|
||||
self.assertEqual(reference_doc.amount, 250)
|
||||
|
||||
|
||||
def create_payment_order_against_payment_entry(ref_doc, order_type):
|
||||
def create_payment_order_against_payment_entry(ref_doc, order_type, bank_account):
|
||||
payment_order = frappe.get_doc(
|
||||
dict(
|
||||
doctype="Payment Order",
|
||||
company="_Test Company",
|
||||
payment_order_type=order_type,
|
||||
company_bank_account="Checking Account - Citi Bank",
|
||||
company_bank_account=bank_account,
|
||||
)
|
||||
)
|
||||
doc = make_payment_order(ref_doc.name, payment_order)
|
||||
|
||||
@@ -2,141 +2,167 @@
|
||||
// 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");
|
||||
|
||||
// check for any running reconciliation jobs
|
||||
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({
|
||||
method: "erpnext.accounts.doctype.payment_reconciliation.payment_reconciliation.get_queries_for_dimension_filters",
|
||||
args: {
|
||||
company: this.frm.doc.company,
|
||||
},
|
||||
callback: (r) => {
|
||||
if (!r.exc && r.message) {
|
||||
r.message.forEach((x) => {
|
||||
this.frm.set_query(x.fieldname, () => {
|
||||
return {
|
||||
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) {
|
||||
@@ -146,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) {
|
||||
@@ -154,7 +180,7 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
||||
this.frm.set_value("default_advance_account", r.message[1]);
|
||||
}
|
||||
this.frm.refresh();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -172,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");
|
||||
@@ -184,48 +209,48 @@ 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"),
|
||||
@@ -240,66 +265,75 @@ 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:'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: "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);
|
||||
args.forEach((d) => {
|
||||
frappe.model.set_value(
|
||||
"Payment Reconciliation Allocation",
|
||||
d.docname,
|
||||
"difference_account",
|
||||
d.difference_account
|
||||
);
|
||||
});
|
||||
|
||||
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,
|
||||
docname: d.name,
|
||||
reference_name: d.reference_name,
|
||||
difference_amount: d.difference_amount,
|
||||
difference_account: d.difference_account,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -315,41 +349,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 }));
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
"invoice_limit",
|
||||
"payment_limit",
|
||||
"bank_cash_account",
|
||||
"accounting_dimensions_section",
|
||||
"cost_center",
|
||||
"dimension_col_break",
|
||||
"sec_break1",
|
||||
"invoice_name",
|
||||
"invoices",
|
||||
@@ -208,6 +210,18 @@
|
||||
"fieldname": "payment_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Filter on Payment"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval: doc.invoices.length == 0",
|
||||
"depends_on": "eval:doc.receivable_payable_account",
|
||||
"fieldname": "accounting_dimensions_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Accounting Dimensions Filter"
|
||||
},
|
||||
{
|
||||
"fieldname": "dimension_col_break",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"hide_toolbar": 1,
|
||||
@@ -215,7 +229,7 @@
|
||||
"is_virtual": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2023-11-17 17:33:55.701726",
|
||||
"modified": "2023-12-14 13:38:16.264013",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation",
|
||||
|
||||
@@ -10,6 +10,7 @@ from frappe.query_builder.custom import ConstantColumn
|
||||
from frappe.utils import flt, fmt_money, get_link_to_form, getdate, nowdate, today
|
||||
|
||||
import erpnext
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_dimensions
|
||||
from erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation import (
|
||||
is_any_doc_running,
|
||||
)
|
||||
@@ -70,6 +71,7 @@ class PaymentReconciliation(Document):
|
||||
self.common_filter_conditions = []
|
||||
self.accounting_dimension_filter_conditions = []
|
||||
self.ple_posting_date_filter = []
|
||||
self.dimensions = get_dimensions()[0]
|
||||
|
||||
def load_from_db(self):
|
||||
# 'modified' attribute is required for `run_doc_method` to work properly.
|
||||
@@ -172,6 +174,14 @@ class PaymentReconciliation(Document):
|
||||
if self.payment_name:
|
||||
condition.update({"name": self.payment_name})
|
||||
|
||||
# pass dynamic dimension filter values to query builder
|
||||
dimensions = {}
|
||||
for x in self.dimensions:
|
||||
dimension = x.fieldname
|
||||
if self.get(dimension):
|
||||
dimensions.update({dimension: self.get(dimension)})
|
||||
condition.update({"accounting_dimensions": dimensions})
|
||||
|
||||
payment_entries = get_advance_payment_entries_for_regional(
|
||||
self.party_type,
|
||||
self.party,
|
||||
@@ -185,66 +195,67 @@ class PaymentReconciliation(Document):
|
||||
return payment_entries
|
||||
|
||||
def get_jv_entries(self):
|
||||
condition = self.get_conditions()
|
||||
je = qb.DocType("Journal Entry")
|
||||
jea = qb.DocType("Journal Entry Account")
|
||||
conditions = self.get_journal_filter_conditions()
|
||||
|
||||
# Dimension filters
|
||||
for x in self.dimensions:
|
||||
dimension = x.fieldname
|
||||
if self.get(dimension):
|
||||
conditions.append(jea[dimension] == self.get(dimension))
|
||||
|
||||
if self.payment_name:
|
||||
condition += f" and t1.name like '%%{self.payment_name}%%'"
|
||||
conditions.append(je.name.like(f"%%{self.payment_name}%%"))
|
||||
|
||||
if self.get("cost_center"):
|
||||
condition += f" and t2.cost_center = '{self.cost_center}' "
|
||||
conditions.append(jea.cost_center == self.cost_center)
|
||||
|
||||
dr_or_cr = (
|
||||
"credit_in_account_currency"
|
||||
if erpnext.get_party_account_type(self.party_type) == "Receivable"
|
||||
else "debit_in_account_currency"
|
||||
)
|
||||
conditions.append(jea[dr_or_cr].gt(0))
|
||||
|
||||
bank_account_condition = (
|
||||
"t2.against_account like %(bank_cash_account)s" if self.bank_cash_account else "1=1"
|
||||
if self.bank_cash_account:
|
||||
conditions.append(jea.against_account.like(f"%%{self.bank_cash_account}%%"))
|
||||
|
||||
journal_query = (
|
||||
qb.from_(je)
|
||||
.inner_join(jea)
|
||||
.on(jea.parent == je.name)
|
||||
.select(
|
||||
ConstantColumn("Journal Entry").as_("reference_type"),
|
||||
je.name.as_("reference_name"),
|
||||
je.posting_date,
|
||||
je.remark.as_("remarks"),
|
||||
jea.name.as_("reference_row"),
|
||||
jea[dr_or_cr].as_("amount"),
|
||||
jea.is_advance,
|
||||
jea.exchange_rate,
|
||||
jea.account_currency.as_("currency"),
|
||||
jea.cost_center.as_("cost_center"),
|
||||
)
|
||||
.where(
|
||||
(je.docstatus == 1)
|
||||
& (jea.party_type == self.party_type)
|
||||
& (jea.party == self.party)
|
||||
& (jea.account == self.receivable_payable_account)
|
||||
& (
|
||||
(jea.reference_type == "")
|
||||
| (jea.reference_type.isnull())
|
||||
| (jea.reference_type.isin(("Sales Order", "Purchase Order")))
|
||||
)
|
||||
)
|
||||
.where(Criterion.all(conditions))
|
||||
.orderby(je.posting_date)
|
||||
)
|
||||
|
||||
limit = f"limit {self.payment_limit}" if self.payment_limit else " "
|
||||
if self.payment_limit:
|
||||
journal_query = journal_query.limit(self.payment_limit)
|
||||
|
||||
# nosemgrep
|
||||
journal_entries = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
"Journal Entry" as reference_type, t1.name as reference_name,
|
||||
t1.posting_date, t1.remark as remarks, t2.name as reference_row,
|
||||
{dr_or_cr} as amount, t2.is_advance, t2.exchange_rate,
|
||||
t2.account_currency as currency, t2.cost_center as cost_center
|
||||
from
|
||||
`tabJournal Entry` t1, `tabJournal Entry Account` t2
|
||||
where
|
||||
t1.name = t2.parent and t1.docstatus = 1 and t2.docstatus = 1
|
||||
and t2.party_type = %(party_type)s and t2.party = %(party)s
|
||||
and t2.account = %(account)s and {dr_or_cr} > 0 {condition}
|
||||
and (t2.reference_type is null or t2.reference_type = '' or
|
||||
(t2.reference_type in ('Sales Order', 'Purchase Order')
|
||||
and t2.reference_name is not null and t2.reference_name != ''))
|
||||
and (CASE
|
||||
WHEN t1.voucher_type in ('Debit Note', 'Credit Note')
|
||||
THEN 1=1
|
||||
ELSE {bank_account_condition}
|
||||
END)
|
||||
order by t1.posting_date
|
||||
{limit}
|
||||
""".format(
|
||||
**{
|
||||
"dr_or_cr": dr_or_cr,
|
||||
"bank_account_condition": bank_account_condition,
|
||||
"condition": condition,
|
||||
"limit": limit,
|
||||
}
|
||||
),
|
||||
{
|
||||
"party_type": self.party_type,
|
||||
"party": self.party,
|
||||
"account": self.receivable_payable_account,
|
||||
"bank_cash_account": "%%%s%%" % self.bank_cash_account,
|
||||
},
|
||||
as_dict=1,
|
||||
)
|
||||
journal_entries = journal_query.run(as_dict=True)
|
||||
|
||||
return list(journal_entries)
|
||||
|
||||
@@ -298,6 +309,7 @@ class PaymentReconciliation(Document):
|
||||
min_outstanding=-(self.minimum_payment_amount) if self.minimum_payment_amount else None,
|
||||
max_outstanding=-(self.maximum_payment_amount) if self.maximum_payment_amount else None,
|
||||
get_payments=True,
|
||||
accounting_dimensions=self.accounting_dimension_filter_conditions,
|
||||
)
|
||||
|
||||
for inv in return_outstanding:
|
||||
@@ -446,8 +458,15 @@ class PaymentReconciliation(Document):
|
||||
row = self.append("allocation", {})
|
||||
row.update(entry)
|
||||
|
||||
def update_dimension_values_in_allocated_entries(self, res):
|
||||
for x in self.dimensions:
|
||||
dimension = x.fieldname
|
||||
if self.get(dimension):
|
||||
res[dimension] = self.get(dimension)
|
||||
return res
|
||||
|
||||
def get_allocated_entry(self, pay, inv, allocated_amount):
|
||||
return frappe._dict(
|
||||
res = frappe._dict(
|
||||
{
|
||||
"reference_type": pay.get("reference_type"),
|
||||
"reference_name": pay.get("reference_name"),
|
||||
@@ -463,6 +482,9 @@ class PaymentReconciliation(Document):
|
||||
}
|
||||
)
|
||||
|
||||
res = self.update_dimension_values_in_allocated_entries(res)
|
||||
return res
|
||||
|
||||
def reconcile_allocations(self, skip_ref_details_update_for_pe=False):
|
||||
adjust_allocations_for_taxes(self)
|
||||
dr_or_cr = (
|
||||
@@ -485,10 +507,10 @@ class PaymentReconciliation(Document):
|
||||
reconciled_entry.append(payment_details)
|
||||
|
||||
if entry_list:
|
||||
reconcile_against_document(entry_list, skip_ref_details_update_for_pe)
|
||||
reconcile_against_document(entry_list, skip_ref_details_update_for_pe, self.dimensions)
|
||||
|
||||
if dr_or_cr_notes:
|
||||
reconcile_dr_cr_note(dr_or_cr_notes, self.company)
|
||||
reconcile_dr_cr_note(dr_or_cr_notes, self.company, self.dimensions)
|
||||
|
||||
@frappe.whitelist()
|
||||
def reconcile(self):
|
||||
@@ -517,7 +539,7 @@ class PaymentReconciliation(Document):
|
||||
self.get_unreconciled_entries()
|
||||
|
||||
def get_payment_details(self, row, dr_or_cr):
|
||||
return frappe._dict(
|
||||
payment_details = frappe._dict(
|
||||
{
|
||||
"voucher_type": row.get("reference_type"),
|
||||
"voucher_no": row.get("reference_name"),
|
||||
@@ -539,6 +561,12 @@ class PaymentReconciliation(Document):
|
||||
}
|
||||
)
|
||||
|
||||
for x in self.dimensions:
|
||||
if row.get(x.fieldname):
|
||||
payment_details[x.fieldname] = row.get(x.fieldname)
|
||||
|
||||
return payment_details
|
||||
|
||||
def check_mandatory_to_fetch(self):
|
||||
for fieldname in ["company", "party_type", "party", "receivable_payable_account"]:
|
||||
if not self.get(fieldname):
|
||||
@@ -603,7 +631,12 @@ class PaymentReconciliation(Document):
|
||||
journals_map = frappe._dict(
|
||||
frappe.db.get_all(
|
||||
"Journal Entry Account",
|
||||
filters={"parent": ("in", journals), "account": ("in", [self.receivable_payable_account])},
|
||||
filters={
|
||||
"parent": ("in", journals),
|
||||
"account": ("in", [self.receivable_payable_account]),
|
||||
"party_type": self.party_type,
|
||||
"party": self.party,
|
||||
},
|
||||
fields=[
|
||||
"parent as `name`",
|
||||
"exchange_rate",
|
||||
@@ -646,6 +679,13 @@ class PaymentReconciliation(Document):
|
||||
if not invoices_to_reconcile:
|
||||
frappe.throw(_("No records found in Allocation table"))
|
||||
|
||||
def build_dimensions_filter_conditions(self):
|
||||
ple = qb.DocType("Payment Ledger Entry")
|
||||
for x in self.dimensions:
|
||||
dimension = x.fieldname
|
||||
if self.get(dimension):
|
||||
self.accounting_dimension_filter_conditions.append(ple[dimension] == self.get(dimension))
|
||||
|
||||
def build_qb_filter_conditions(self, get_invoices=False, get_return_invoices=False):
|
||||
self.common_filter_conditions.clear()
|
||||
self.accounting_dimension_filter_conditions.clear()
|
||||
@@ -669,40 +709,30 @@ class PaymentReconciliation(Document):
|
||||
if self.to_payment_date:
|
||||
self.ple_posting_date_filter.append(ple.posting_date.lte(self.to_payment_date))
|
||||
|
||||
def get_conditions(self, get_payments=False):
|
||||
condition = " and company = '{0}' ".format(self.company)
|
||||
self.build_dimensions_filter_conditions()
|
||||
|
||||
if self.get("cost_center") and get_payments:
|
||||
condition = " and cost_center = '{0}' ".format(self.cost_center)
|
||||
def get_journal_filter_conditions(self):
|
||||
conditions = []
|
||||
je = qb.DocType("Journal Entry")
|
||||
jea = qb.DocType("Journal Entry Account")
|
||||
conditions.append(je.company == self.company)
|
||||
|
||||
condition += (
|
||||
" and posting_date >= {0}".format(frappe.db.escape(self.from_payment_date))
|
||||
if self.from_payment_date
|
||||
else ""
|
||||
)
|
||||
condition += (
|
||||
" and posting_date <= {0}".format(frappe.db.escape(self.to_payment_date))
|
||||
if self.to_payment_date
|
||||
else ""
|
||||
)
|
||||
if self.from_payment_date:
|
||||
conditions.append(je.posting_date.gte(self.from_payment_date))
|
||||
|
||||
if self.to_payment_date:
|
||||
conditions.append(je.posting_date.lte(self.to_payment_date))
|
||||
|
||||
if self.minimum_payment_amount:
|
||||
condition += (
|
||||
" and unallocated_amount >= {0}".format(flt(self.minimum_payment_amount))
|
||||
if get_payments
|
||||
else " and total_debit >= {0}".format(flt(self.minimum_payment_amount))
|
||||
)
|
||||
conditions.append(je.total_debit.gte(self.minimum_payment_amount))
|
||||
|
||||
if self.maximum_payment_amount:
|
||||
condition += (
|
||||
" and unallocated_amount <= {0}".format(flt(self.maximum_payment_amount))
|
||||
if get_payments
|
||||
else " and total_debit <= {0}".format(flt(self.maximum_payment_amount))
|
||||
)
|
||||
conditions.append(je.total_debit.lte(self.maximum_payment_amount))
|
||||
|
||||
return condition
|
||||
return conditions
|
||||
|
||||
|
||||
def reconcile_dr_cr_note(dr_cr_notes, company):
|
||||
def reconcile_dr_cr_note(dr_cr_notes, company, active_dimensions=None):
|
||||
for inv in dr_cr_notes:
|
||||
voucher_type = "Credit Note" if inv.voucher_type == "Sales Invoice" else "Debit Note"
|
||||
|
||||
@@ -752,6 +782,15 @@ def reconcile_dr_cr_note(dr_cr_notes, company):
|
||||
}
|
||||
)
|
||||
|
||||
# Credit Note(JE) will inherit the same dimension values as payment
|
||||
dimensions_dict = frappe._dict()
|
||||
if active_dimensions:
|
||||
for dim in active_dimensions:
|
||||
dimensions_dict[dim.fieldname] = inv.get(dim.fieldname)
|
||||
|
||||
jv.accounts[0].update(dimensions_dict)
|
||||
jv.accounts[1].update(dimensions_dict)
|
||||
|
||||
jv.flags.ignore_mandatory = True
|
||||
jv.flags.ignore_exchange_rate = True
|
||||
jv.remark = None
|
||||
@@ -785,9 +824,27 @@ def reconcile_dr_cr_note(dr_cr_notes, company):
|
||||
inv.against_voucher,
|
||||
None,
|
||||
inv.cost_center,
|
||||
dimensions_dict,
|
||||
)
|
||||
|
||||
|
||||
@erpnext.allow_regional
|
||||
def adjust_allocations_for_taxes(doc):
|
||||
pass
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_queries_for_dimension_filters(company: str = None):
|
||||
dimensions_with_filters = []
|
||||
for d in get_dimensions()[0]:
|
||||
filters = {}
|
||||
meta = frappe.get_meta(d.document_type)
|
||||
if meta.has_field("company") and company:
|
||||
filters.update({"company": company})
|
||||
|
||||
if meta.is_tree:
|
||||
filters.update({"is_group": 0})
|
||||
|
||||
dimensions_with_filters.append({"fieldname": d.fieldname, "filters": filters})
|
||||
|
||||
return dimensions_with_filters
|
||||
|
||||
@@ -56,6 +56,7 @@ class TestPaymentReconciliation(FrappeTestCase):
|
||||
self.expense_account = "Cost of Goods Sold - _PR"
|
||||
self.debit_to = "Debtors - _PR"
|
||||
self.creditors = "Creditors - _PR"
|
||||
self.cash = "Cash - _PR"
|
||||
|
||||
# create bank account
|
||||
if frappe.db.exists("Account", "HDFC - _PR"):
|
||||
@@ -486,6 +487,91 @@ class TestPaymentReconciliation(FrappeTestCase):
|
||||
self.assertEqual(len(pr.get("invoices")), 0)
|
||||
self.assertEqual(len(pr.get("payments")), 0)
|
||||
|
||||
def test_payment_against_foreign_currency_journal(self):
|
||||
transaction_date = nowdate()
|
||||
|
||||
self.supplier = "_Test Supplier USD"
|
||||
self.supplier2 = make_supplier("_Test Supplier2 USD", "USD")
|
||||
amount = 100
|
||||
exc_rate1 = 80
|
||||
exc_rate2 = 83
|
||||
|
||||
je = frappe.new_doc("Journal Entry")
|
||||
je.posting_date = transaction_date
|
||||
je.company = self.company
|
||||
je.user_remark = "test"
|
||||
je.multi_currency = 1
|
||||
je.set(
|
||||
"accounts",
|
||||
[
|
||||
{
|
||||
"account": self.creditors_usd,
|
||||
"party_type": "Supplier",
|
||||
"party": self.supplier,
|
||||
"exchange_rate": exc_rate1,
|
||||
"cost_center": self.cost_center,
|
||||
"credit": amount * exc_rate1,
|
||||
"credit_in_account_currency": amount,
|
||||
},
|
||||
{
|
||||
"account": self.creditors_usd,
|
||||
"party_type": "Supplier",
|
||||
"party": self.supplier2,
|
||||
"exchange_rate": exc_rate2,
|
||||
"cost_center": self.cost_center,
|
||||
"credit": amount * exc_rate2,
|
||||
"credit_in_account_currency": amount,
|
||||
},
|
||||
{
|
||||
"account": self.expense_account,
|
||||
"cost_center": self.cost_center,
|
||||
"debit": (amount * exc_rate1) + (amount * exc_rate2),
|
||||
"debit_in_account_currency": (amount * exc_rate1) + (amount * exc_rate2),
|
||||
},
|
||||
],
|
||||
)
|
||||
je.save().submit()
|
||||
|
||||
pe = self.create_payment_entry(amount=amount, posting_date=transaction_date)
|
||||
pe.payment_type = "Pay"
|
||||
pe.party_type = "Supplier"
|
||||
pe.party = self.supplier
|
||||
pe.paid_to = self.creditors_usd
|
||||
pe.paid_from = self.cash
|
||||
pe.paid_amount = 8000
|
||||
pe.received_amount = 100
|
||||
pe.target_exchange_rate = exc_rate1
|
||||
pe.paid_to_account_currency = "USD"
|
||||
pe.save().submit()
|
||||
|
||||
pr = self.create_payment_reconciliation(party_is_customer=False)
|
||||
pr.receivable_payable_account = self.creditors_usd
|
||||
pr.minimum_invoice_amount = pr.maximum_invoice_amount = amount
|
||||
pr.from_invoice_date = pr.to_invoice_date = transaction_date
|
||||
pr.from_payment_date = pr.to_payment_date = transaction_date
|
||||
|
||||
pr.get_unreconciled_entries()
|
||||
invoices = [x.as_dict() for x in pr.get("invoices")]
|
||||
payments = [x.as_dict() for x in pr.get("payments")]
|
||||
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
|
||||
|
||||
# There should no difference_amount as the Journal and Payment have same exchange rate - 'exc_rate1'
|
||||
for row in pr.allocation:
|
||||
self.assertEqual(flt(row.get("difference_amount")), 0.0)
|
||||
|
||||
pr.reconcile()
|
||||
|
||||
# check PR tool output
|
||||
self.assertEqual(len(pr.get("invoices")), 0)
|
||||
self.assertEqual(len(pr.get("payments")), 0)
|
||||
|
||||
journals = frappe.db.get_all(
|
||||
"Journal Entry Account",
|
||||
filters={"reference_type": je.doctype, "reference_name": je.name, "docstatus": 1},
|
||||
fields=["parent"],
|
||||
)
|
||||
self.assertEqual([], journals)
|
||||
|
||||
def test_journal_against_invoice(self):
|
||||
transaction_date = nowdate()
|
||||
amount = 100
|
||||
@@ -591,6 +677,70 @@ class TestPaymentReconciliation(FrappeTestCase):
|
||||
self.assertEqual(si.status, "Paid")
|
||||
self.assertEqual(si.outstanding_amount, 0)
|
||||
|
||||
def test_invoice_status_after_cr_note_cancellation(self):
|
||||
# This test case is made after the 'always standalone Credit/Debit notes' feature is introduced
|
||||
transaction_date = nowdate()
|
||||
amount = 100
|
||||
|
||||
si = self.create_sales_invoice(qty=1, rate=amount, posting_date=transaction_date)
|
||||
|
||||
cr_note = self.create_sales_invoice(
|
||||
qty=-1, rate=amount, posting_date=transaction_date, do_not_save=True, do_not_submit=True
|
||||
)
|
||||
cr_note.is_return = 1
|
||||
cr_note.return_against = si.name
|
||||
cr_note = cr_note.save().submit()
|
||||
|
||||
pr = self.create_payment_reconciliation()
|
||||
|
||||
pr.get_unreconciled_entries()
|
||||
invoices = [x.as_dict() for x in pr.get("invoices")]
|
||||
payments = [x.as_dict() for x in pr.get("payments")]
|
||||
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
|
||||
pr.reconcile()
|
||||
|
||||
pr.get_unreconciled_entries()
|
||||
self.assertEqual(pr.get("invoices"), [])
|
||||
self.assertEqual(pr.get("payments"), [])
|
||||
|
||||
journals = frappe.db.get_all(
|
||||
"Journal Entry",
|
||||
filters={
|
||||
"is_system_generated": 1,
|
||||
"docstatus": 1,
|
||||
"voucher_type": "Credit Note",
|
||||
"reference_type": si.doctype,
|
||||
"reference_name": si.name,
|
||||
},
|
||||
pluck="name",
|
||||
)
|
||||
self.assertEqual(len(journals), 1)
|
||||
|
||||
# assert status and outstanding
|
||||
si.reload()
|
||||
self.assertEqual(si.status, "Credit Note Issued")
|
||||
self.assertEqual(si.outstanding_amount, 0)
|
||||
|
||||
cr_note.reload()
|
||||
cr_note.cancel()
|
||||
# 'Credit Note' Journal should be auto cancelled
|
||||
journals = frappe.db.get_all(
|
||||
"Journal Entry",
|
||||
filters={
|
||||
"is_system_generated": 1,
|
||||
"docstatus": 1,
|
||||
"voucher_type": "Credit Note",
|
||||
"reference_type": si.doctype,
|
||||
"reference_name": si.name,
|
||||
},
|
||||
pluck="name",
|
||||
)
|
||||
self.assertEqual(len(journals), 0)
|
||||
# assert status and outstanding
|
||||
si.reload()
|
||||
self.assertEqual(si.status, "Unpaid")
|
||||
self.assertEqual(si.outstanding_amount, 100)
|
||||
|
||||
def test_cr_note_partial_against_invoice(self):
|
||||
transaction_date = nowdate()
|
||||
amount = 100
|
||||
@@ -1184,3 +1334,17 @@ def make_customer(customer_name, currency=None):
|
||||
return customer.name
|
||||
else:
|
||||
return customer_name
|
||||
|
||||
|
||||
def make_supplier(supplier_name, currency=None):
|
||||
if not frappe.db.exists("Supplier", supplier_name):
|
||||
supplier = frappe.new_doc("Supplier")
|
||||
supplier.supplier_name = supplier_name
|
||||
supplier.type = "Individual"
|
||||
|
||||
if currency:
|
||||
supplier.default_currency = currency
|
||||
supplier.save()
|
||||
return supplier.name
|
||||
else:
|
||||
return supplier_name
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
"difference_account",
|
||||
"exchange_rate",
|
||||
"currency",
|
||||
"cost_center"
|
||||
"accounting_dimensions_section",
|
||||
"cost_center",
|
||||
"dimension_col_break"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -151,12 +153,26 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Cost Center",
|
||||
"options": "Cost Center"
|
||||
},
|
||||
{
|
||||
"fieldname": "gain_loss_posting_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Difference Posting Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "accounting_dimensions_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Accounting Dimensions"
|
||||
},
|
||||
{
|
||||
"fieldname": "dimension_col_break",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"is_virtual": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2023-11-17 17:33:38.612615",
|
||||
"modified": "2023-12-14 13:38:26.104150",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation Allocation",
|
||||
|
||||
@@ -1,83 +1,95 @@
|
||||
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.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.ui.form.on("Payment Request", "refresh", function (frm) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
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 == "Cancelled") {
|
||||
} else if (doc.status == "Cancelled") {
|
||||
return [__("Cancelled"), "red", "status,=,Cancelled"];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -11,7 +11,6 @@ from erpnext.accounts.doctype.loyalty_program.loyalty_program import validate_lo
|
||||
from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request
|
||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import (
|
||||
SalesInvoice,
|
||||
get_bank_cash_account,
|
||||
get_mode_of_payment_info,
|
||||
update_multi_mode_option,
|
||||
)
|
||||
@@ -208,7 +207,6 @@ class POSInvoice(SalesInvoice):
|
||||
self.validate_stock_availablility()
|
||||
self.validate_return_items_qty()
|
||||
self.set_status()
|
||||
self.set_account_for_mode_of_payment()
|
||||
self.validate_pos()
|
||||
self.validate_payment_amount()
|
||||
self.validate_loyalty_transaction()
|
||||
@@ -643,11 +641,6 @@ class POSInvoice(SalesInvoice):
|
||||
update_multi_mode_option(self, pos_profile)
|
||||
self.paid_amount = 0
|
||||
|
||||
def set_account_for_mode_of_payment(self):
|
||||
for pay in self.payments:
|
||||
if not pay.account:
|
||||
pay.account = get_bank_cash_account(pay.mode_of_payment, self.company).get("account")
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_payment_request(self):
|
||||
for pay in self.payments:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
@@ -80,13 +80,16 @@
|
||||
"target_warehouse",
|
||||
"quality_inspection",
|
||||
"serial_and_batch_bundle",
|
||||
"batch_no",
|
||||
"use_serial_batch_fields",
|
||||
"col_break5",
|
||||
"allow_zero_valuation_rate",
|
||||
"serial_no",
|
||||
"item_tax_rate",
|
||||
"actual_batch_qty",
|
||||
"actual_qty",
|
||||
"section_break_tlhi",
|
||||
"serial_no",
|
||||
"column_break_ciit",
|
||||
"batch_no",
|
||||
"edit_references",
|
||||
"sales_order",
|
||||
"so_detail",
|
||||
@@ -628,13 +631,13 @@
|
||||
"options": "Quality Inspection"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.use_serial_batch_fields === 1",
|
||||
"fieldname": "batch_no",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"label": "Batch No",
|
||||
"options": "Batch",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break5",
|
||||
@@ -649,14 +652,14 @@
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.use_serial_batch_fields === 1",
|
||||
"fieldname": "serial_no",
|
||||
"fieldtype": "Small Text",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Serial No",
|
||||
"oldfieldname": "serial_no",
|
||||
"oldfieldtype": "Small Text",
|
||||
"read_only": 1
|
||||
"oldfieldtype": "Small Text"
|
||||
},
|
||||
{
|
||||
"fieldname": "item_tax_rate",
|
||||
@@ -824,17 +827,33 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.use_serial_batch_fields === 1",
|
||||
"fieldname": "serial_and_batch_bundle",
|
||||
"fieldtype": "Link",
|
||||
"label": "Serial and Batch Bundle",
|
||||
"no_copy": 1,
|
||||
"options": "Serial and Batch Bundle",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "use_serial_batch_fields",
|
||||
"fieldtype": "Check",
|
||||
"label": "Use Serial No / Batch Fields"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.use_serial_batch_fields === 1",
|
||||
"fieldname": "section_break_tlhi",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_ciit",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2023-11-14 18:33:22.585715",
|
||||
"modified": "2024-02-25 15:50:17.140269",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Invoice Item",
|
||||
|
||||
@@ -72,7 +72,7 @@ class POSInvoiceItem(Document):
|
||||
rate_with_margin: DF.Currency
|
||||
sales_order: DF.Link | None
|
||||
serial_and_batch_bundle: DF.Link | None
|
||||
serial_no: DF.SmallText | None
|
||||
serial_no: DF.Text | None
|
||||
service_end_date: DF.Date | None
|
||||
service_start_date: DF.Date | None
|
||||
service_stop_date: DF.Date | None
|
||||
@@ -82,6 +82,7 @@ class POSInvoiceItem(Document):
|
||||
target_warehouse: DF.Link | None
|
||||
total_weight: DF.Float
|
||||
uom: DF.Link
|
||||
use_serial_batch_fields: DF.Check
|
||||
warehouse: DF.Link | None
|
||||
weight_per_unit: DF.Float
|
||||
weight_uom: DF.Link | None
|
||||
|
||||
@@ -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", "");
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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];
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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));
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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", {});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user