Compare commits

..

3 Commits

Author SHA1 Message Date
Ankush Menat
0255642deb Merge branch 'develop' into fix-get_single_value 2024-01-10 10:42:12 +05:30
barredterra
d4d9e6c6fa test: fix wrong fieldname 2024-01-10 01:25:24 +01:00
barredterra
2eb318a5ce fix: wrong usage of get_single_value 2024-01-10 00:53:05 +01:00
1035 changed files with 592454 additions and 1580356 deletions

View File

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

View File

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

View File

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

View File

@@ -1,40 +0,0 @@
#!/bin/bash
set -e
cd ~ || exit
echo "Setting Up Bench..."
pip install frappe-bench
bench -v init frappe-bench --skip-assets --skip-redis-config-generation --python "$(which python)"
cd ./frappe-bench || exit
echo "Get ERPNext..."
bench get-app --skip-assets erpnext "${GITHUB_WORKSPACE}"
echo "Generating POT file..."
bench generate-pot-file --app erpnext
cd ./apps/erpnext || exit
echo "Configuring git user..."
git config user.email "developers@erpnext.com"
git config user.name "frappe-pr-bot"
echo "Setting the correct git remote..."
# Here, the git remote is a local file path by default. Let's change it to the upstream repo.
git remote set-url upstream https://github.com/frappe/erpnext.git
echo "Creating a new branch..."
isodate=$(date -u +"%Y-%m-%d")
branch_name="pot_${BASE_BRANCH}_${isodate}"
git checkout -b "${branch_name}"
echo "Commiting changes..."
git add .
git commit -m "chore: update POT file"
gh auth setup-git
git push -u upstream "${branch_name}"
echo "Creating a PR..."
gh pr create --fill --base "${BASE_BRANCH}" --head "${branch_name}" -R frappe/erpnext

View File

@@ -1,38 +0,0 @@
# This workflow is agnostic to branches. Only maintain on develop branch.
# To add/remove branches just modify the matrix.
name: Regenerate POT file (translatable strings)
on:
schedule:
# 9:30 UTC => 3 PM IST Sunday
- cron: "30 9 * * 0"
workflow_dispatch:
jobs:
regeneratee-pot-file:
name: Release
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
branch: ["develop"]
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ matrix.branch }}
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Run script to update POT file
run: |
bash ${GITHUB_WORKSPACE}/.github/helper/update_pot_file.sh
env:
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
BASE_BRANCH: ${{ matrix.branch }}

View File

@@ -20,18 +20,6 @@ jobs:
- name: Install and Run Pre-commit
uses: pre-commit/action@v3.0.0
semgrep:
name: semgrep
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.10
uses: actions/setup-python@v4
with:
python-version: '3.10'
cache: pip
- name: Download Semgrep rules
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules

View File

@@ -1,22 +0,0 @@
# Tests are skipped for these files but github doesn't allow "passing" hence this is required.
name: Skipped Patch Test
on:
pull_request:
paths:
- "**.js"
- "**.css"
- "**.md"
- "**.html"
- "**.csv"
jobs:
test:
runs-on: ubuntu-latest
name: Patch Test
steps:
- name: Pass skipped tests unconditionally
run: "echo Skipped"

View File

@@ -16,7 +16,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 20
node-version: 18
- name: Setup dependencies
run: |
npm install @semantic-release/git @semantic-release/exec --no-save

View File

@@ -1,24 +0,0 @@
# Tests are skipped for these files but github doesn't allow "passing" hence this is required.
name: Skipped Tests
on:
pull_request:
paths:
- "**.js"
- "**.css"
- "**.md"
- "**.html"
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
container: [1, 2, 3, 4]
name: Python Unit Tests
steps:
- name: Pass skipped tests unconditionally
run: "echo Skipped"

View File

@@ -31,9 +31,6 @@ jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 60
env:
NODE_ENV: "production"
WITH_COVERAGE: ${{ github.event_name != 'pull_request' }}
strategy:
fail-fast: false
@@ -120,11 +117,11 @@ jobs:
FRAPPE_BRANCH: ${{ github.event.inputs.branch }}
- name: Run Tests
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --total-builds 4 --build-number ${{ matrix.container }}'
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --with-coverage --total-builds 4 --build-number ${{ matrix.container }}'
env:
TYPE: server
CAPTURE_COVERAGE: ${{ github.event_name != 'pull_request' }}
CI_BUILD_ID: ${{ github.run_id }}
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
- name: Show bench output
if: ${{ always() }}
@@ -132,7 +129,6 @@ jobs:
- name: Upload coverage data
uses: actions/upload-artifact@v3
if: github.event_name != 'pull_request'
with:
name: coverage-${{ matrix.container }}
path: /home/runner/frappe-bench/sites/coverage.xml
@@ -141,7 +137,6 @@ jobs:
name: Coverage Wrap Up
needs: test
runs-on: ubuntu-latest
if: ${{ github.event_name != 'pull_request' }}
steps:
- name: Clone
uses: actions/checkout@v2
@@ -153,6 +148,5 @@ jobs:
uses: codecov/codecov-action@v2
with:
name: MariaDB
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
verbose: true

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@
*.py~
.DS_Store
conf.py
locale
latest_updates.json
.wnf-lang-status
*.egg-info

View File

@@ -20,23 +20,6 @@ repos:
- id: check-yaml
- id: debug-statements
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1
hooks:
- id: prettier
types_or: [javascript, vue, scss]
# Ignore any files that might contain jinja / bundles
exclude: |
(?x)^(
erpnext/public/dist/.*|
cypress/.*|
.*node_modules.*|
.*boilerplate.*|
erpnext/public/js/controllers/.*|
erpnext/templates/pages/order.js|
erpnext/templates/includes/.*
)$
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.44.0
hooks:

View File

@@ -7,7 +7,8 @@
<p>ERP made simple</p>
</p>
[![CI](https://github.com/frappe/erpnext/actions/workflows/server-tests-mariadb.yml/badge.svg?event=schedule)](https://github.com/frappe/erpnext/actions/workflows/server-tests-mariadb.yml)
[![CI](https://github.com/frappe/erpnext/actions/workflows/server-tests.yml/badge.svg?branch=develop)](https://github.com/frappe/erpnext/actions/workflows/server-tests.yml)
[![UI](https://github.com/erpnext/erpnext_ui_tests/actions/workflows/ui-tests.yml/badge.svg?branch=develop&event=schedule)](https://github.com/erpnext/erpnext_ui_tests/actions/workflows/ui-tests.yml)
[![Open Source Helpers](https://www.codetriage.com/frappe/erpnext/badges/users.svg)](https://www.codetriage.com/frappe/erpnext)
[![codecov](https://codecov.io/gh/frappe/erpnext/branch/develop/graph/badge.svg?token=0TwvyUg3I5)](https://codecov.io/gh/frappe/erpnext)
[![docker pulls](https://img.shields.io/docker/pulls/frappe/erpnext-worker.svg)](https://hub.docker.com/r/frappe/erpnext-worker)

View File

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

View File

@@ -1,4 +0,0 @@
files:
- source: /erpnext/locale/main.pot
translation: /erpnext/locale/%two_letters_code%.po
pull_request_title: "chore: sync translations from crowdin"

View File

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

View File

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

View File

@@ -358,9 +358,11 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
account_currency = get_account_currency(item.expense_account or item.income_account)
if doc.doctype == "Sales Invoice":
against_type = "Customer"
against, project = doc.customer, doc.project
credit_account, debit_account = item.income_account, item.deferred_revenue_account
else:
against_type = "Supplier"
against, project = doc.supplier, item.project
credit_account, debit_account = item.deferred_expense_account, item.expense_account
@@ -413,6 +415,7 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
doc,
credit_account,
debit_account,
against_type,
against,
amount,
base_amount,
@@ -494,6 +497,7 @@ def make_gl_entries(
doc,
credit_account,
debit_account,
against_type,
against,
amount,
base_amount,
@@ -515,7 +519,9 @@ def make_gl_entries(
doc.get_gl_dict(
{
"account": credit_account,
"against_type": against_type,
"against": against,
"against_link": against,
"credit": base_amount,
"credit_in_account_currency": amount,
"cost_center": cost_center,
@@ -534,7 +540,9 @@ def make_gl_entries(
doc.get_gl_dict(
{
"account": debit_account,
"against_type": against_type,
"against": against,
"against_link": against,
"debit": base_amount,
"debit_in_account_currency": amount,
"cost_center": cost_center,

View File

@@ -26,14 +26,19 @@ 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);
@@ -75,33 +80,27 @@ 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"),
@@ -194,8 +193,14 @@ frappe.ui.form.on("Account", {
if (r.message) {
frappe.set_route("Form", "Account", r.message);
} else {
frm.set_value("account_number", data.account_number);
frm.set_value("account_name", data.account_name);
frm.set_value(
"account_number",
data.account_number
);
frm.set_value(
"account_name",
data.account_name
);
}
d.hide();
}

View File

@@ -108,7 +108,6 @@
"fieldname": "parent_account",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"in_preview": 1,
"label": "Parent Account",
"oldfieldname": "parent_account",
"oldfieldtype": "Link",
@@ -193,7 +192,7 @@
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2024-01-10 04:57:33.681676",
"modified": "2023-07-20 18:18:44.405723",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",
@@ -250,9 +249,8 @@
],
"search_fields": "account_number",
"show_name_in_global_search": 1,
"show_preview_popup": 1,
"sort_field": "modified",
"sort_order": "ASC",
"states": [],
"track_changes": 1
}
}

View File

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

View File

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

View File

@@ -56,9 +56,7 @@
"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)": {
"account_type": "Stock"
},
"Insumos (materiais diretos)": {},
"Insumos Agropecu\u00e1rios": {},
"Mercadorias para Revenda": {},
"Outras 11": {},
@@ -148,65 +146,6 @@
"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": {},
@@ -682,9 +621,7 @@
"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": {
"account_type": "Income Account"
},
"Receita de Loca\u00e7\u00e3o de Bens M\u00f3veis e Im\u00f3veis": {},
"Receita de Vendas de Mercadorias e Produtos a Comercial Exportadora com Fim Espec\u00edfico de Exporta\u00e7\u00e3o": {}
}
}
@@ -708,6 +645,65 @@
}
},
"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": {

View File

@@ -36,16 +36,16 @@
}
},
"Fixed Assets": {
"Capital Equipment": {
"Capital Equipments": {
"account_type": "Fixed Asset"
},
"Electronic Equipment": {
"Electronic Equipments": {
"account_type": "Fixed Asset"
},
"Furniture and Fixtures": {
"Furnitures and Fixtures": {
"account_type": "Fixed Asset"
},
"Office Equipment": {
"Office Equipments": {
"account_type": "Fixed Asset"
},
"Plants and Machineries": {

View File

@@ -23,13 +23,13 @@ def get():
_("Tax Assets"): {"is_group": 1},
},
_("Fixed Assets"): {
_("Capital Equipment"): {"account_type": "Fixed Asset"},
_("Electronic Equipment"): {"account_type": "Fixed Asset"},
_("Furniture and Fixtures"): {"account_type": "Fixed Asset"},
_("Office Equipment"): {"account_type": "Fixed Asset"},
_("Capital Equipments"): {"account_type": "Fixed Asset"},
_("Electronic Equipments"): {"account_type": "Fixed Asset"},
_("Furnitures and Fixtures"): {"account_type": "Fixed Asset"},
_("Office Equipments"): {"account_type": "Fixed Asset"},
_("Plants and Machineries"): {"account_type": "Fixed Asset"},
_("Buildings"): {"account_type": "Fixed Asset"},
_("Software"): {"account_type": "Fixed Asset"},
_("Softwares"): {"account_type": "Fixed Asset"},
_("Accumulated Depreciation"): {"account_type": "Accumulated Depreciation"},
_("CWIP Account"): {
"account_type": "Capital Work in Progress",

View File

@@ -36,13 +36,13 @@ def get():
"account_number": "1100-1600",
},
_("Fixed Assets"): {
_("Capital Equipment"): {"account_type": "Fixed Asset", "account_number": "1710"},
_("Electronic Equipment"): {"account_type": "Fixed Asset", "account_number": "1720"},
_("Furniture and Fixtures"): {"account_type": "Fixed Asset", "account_number": "1730"},
_("Office Equipment"): {"account_type": "Fixed Asset", "account_number": "1740"},
_("Capital Equipments"): {"account_type": "Fixed Asset", "account_number": "1710"},
_("Electronic Equipments"): {"account_type": "Fixed Asset", "account_number": "1720"},
_("Furnitures and Fixtures"): {"account_type": "Fixed Asset", "account_number": "1730"},
_("Office Equipments"): {"account_type": "Fixed Asset", "account_number": "1740"},
_("Plants and Machineries"): {"account_type": "Fixed Asset", "account_number": "1750"},
_("Buildings"): {"account_type": "Fixed Asset", "account_number": "1760"},
_("Software"): {"account_type": "Fixed Asset", "account_number": "1770"},
_("Softwares"): {"account_type": "Fixed Asset", "account_number": "1770"},
_("Accumulated Depreciation"): {
"account_type": "Accumulated Depreciation",
"account_number": "1780",

View File

@@ -6,7 +6,6 @@ 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,
@@ -120,7 +119,7 @@ class TestAccount(unittest.TestCase):
InvalidAccountMergeError,
merge_account,
"Capital Stock - _TC",
"Software - _TC",
"Softwares - _TC",
)
# Raise error as currency doesn't match
@@ -325,19 +324,6 @@ 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

View File

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

View File

@@ -11,10 +11,6 @@ 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
@@ -110,7 +106,6 @@ 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:
@@ -126,7 +121,6 @@ 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)

View File

@@ -1,9 +1,10 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Accounting Dimension Filter", {
refresh: function (frm, cdt, cdn) {
let help_content = `<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
frappe.ui.form.on('Accounting Dimension Filter', {
refresh: function(frm, cdt, cdn) {
let help_content =
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
<tr><td>
<p>
<i class="fa fa-hand-right"></i>
@@ -12,80 +13,77 @@ frappe.ui.form.on("Accounting Dimension Filter", {
</td></tr>
</table>`;
frm.set_df_property("dimension_filter_help", "options", help_content);
frm.set_df_property('dimension_filter_help', 'options', help_content);
},
onload: function (frm) {
frm.set_query("applicable_on_account", "accounts", function () {
onload: function(frm) {
frm.set_query('applicable_on_account', 'accounts', function() {
return {
filters: {
company: frm.doc.company,
},
'company': frm.doc.company
}
};
});
frappe.db.get_list("Accounting Dimension", { fields: ["document_type"] }).then((res) => {
let options = ["Cost Center", "Project"];
frappe.db.get_list('Accounting Dimension',
{fields: ['document_type']}).then((res) => {
let options = ['Cost Center', 'Project'];
res.forEach((dimension) => {
options.push(dimension.document_type);
});
frm.set_df_property("accounting_dimension", "options", options);
frm.set_df_property('accounting_dimension', 'options', options);
});
frm.trigger("setup_filters");
frm.trigger('setup_filters');
},
setup_filters: function (frm) {
setup_filters: function(frm) {
let filters = {};
if (frm.doc.accounting_dimension) {
frappe.model.with_doctype(frm.doc.accounting_dimension, function () {
frappe.model.with_doctype(frm.doc.accounting_dimension, function() {
if (frappe.model.is_tree(frm.doc.accounting_dimension)) {
filters["is_group"] = 0;
filters['is_group'] = 0;
}
if (frappe.meta.has_field(frm.doc.accounting_dimension, "company")) {
filters["company"] = frm.doc.company;
if (frappe.meta.has_field(frm.doc.accounting_dimension, 'company')) {
filters['company'] = frm.doc.company;
}
frm.set_query("dimension_value", "dimensions", function () {
frm.set_query('dimension_value', 'dimensions', function() {
return {
filters: filters,
filters: filters
};
});
});
}
},
accounting_dimension: function (frm) {
accounting_dimension: function(frm) {
frm.clear_table("dimensions");
let row = frm.add_child("dimensions");
row.accounting_dimension = frm.doc.accounting_dimension;
frm.fields_dict["dimensions"].grid.update_docfield_property(
"dimension_value",
"label",
frm.doc.accounting_dimension
);
frm.fields_dict["dimensions"].grid.update_docfield_property("dimension_value", "label", frm.doc.accounting_dimension);
frm.refresh_field("dimensions");
frm.trigger("setup_filters");
frm.trigger('setup_filters');
},
apply_restriction_on_values: function (frm) {
apply_restriction_on_values: function(frm) {
/** If restriction on values is not applied, we should set "allow_or_restrict" to "Restrict" with an empty allowed dimension table.
* Hence it's not "restricted" on any value.
*/
*/
if (!frm.doc.apply_restriction_on_values) {
frm.set_value("allow_or_restrict", "Restrict");
frm.clear_table("dimensions");
frm.refresh_field("dimensions");
}
},
}
});
frappe.ui.form.on("Allowed Dimension", {
dimensions_add: function (frm, cdt, cdn) {
frappe.ui.form.on('Allowed Dimension', {
dimensions_add: function(frm, cdt, cdn) {
let row = locals[cdt][cdn];
row.accounting_dimension = frm.doc.accounting_dimension;
frm.refresh_field("dimensions");
},
}
});

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
{
"actions": [],
"creation": "2013-06-24 15:49:57",
"description": "Settings for Accounts",
"doctype": "DocType",
"document_type": "Other",
"editable_grid": 1,
@@ -461,7 +462,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2024-01-30 14:04:26.553554",
"modified": "2023-11-20 09:37:47.650347",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",

View File

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

View File

@@ -1,36 +1,38 @@
// 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);
}
@@ -38,32 +40,30 @@ let add_fields_to_mapping_table = function (frm) {
});
frm.fields_dict.bank_transaction_mapping.grid.update_docfield_property(
"bank_transaction_field",
"options",
options
'bank_transaction_field', 'options', options
);
};
erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
constructor(access_token) {
this.access_token = access_token;
this.plaidUrl = "https://cdn.plaid.com/link/v2/stable/link-initialize.js";
this.plaidUrl = 'https://cdn.plaid.com/link/v2/stable/link-initialize.js';
this.init_config();
}
async init_config() {
this.plaid_env = await frappe.db.get_single_value("Plaid Settings", "plaid_env");
this.plaid_env = await frappe.db.get_single_value('Plaid Settings', 'plaid_env');
this.token = await this.get_link_token_for_update();
this.init_plaid();
}
async get_link_token_for_update() {
const token = frappe.xcall(
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.get_link_token_for_update",
'erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.get_link_token_for_update',
{ access_token: this.access_token }
);
)
if (!token) {
frappe.throw(__("Cannot retrieve link token for update. Check Error Log for more information"));
frappe.throw(__('Cannot retrieve link token for update. Check Error Log for more information'));
}
return token;
}
@@ -90,45 +90,35 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
resolve();
return;
}
const el = document.createElement("script");
el.type = "text/javascript";
const el = document.createElement('script');
el.type = 'text/javascript';
el.async = true;
el.src = src;
el.addEventListener("load", resolve);
el.addEventListener("error", reject);
el.addEventListener("abort", reject);
el.addEventListener('load', resolve);
el.addEventListener('error', reject);
el.addEventListener('abort', reject);
document.head.appendChild(el);
});
}
onScriptLoaded(me) {
me.linkHandler = Plaid.create({
// eslint-disable-line no-undef
me.linkHandler = Plaid.create({ // eslint-disable-line no-undef
env: me.plaid_env,
token: me.token,
onSuccess: me.plaid_success,
onSuccess: me.plaid_success
});
}
onScriptError(error) {
frappe.msgprint(
__(
"There was an issue connecting to Plaid's authentication server. Check browser console for more information"
)
);
frappe.msgprint(__("There was an issue connecting to Plaid's authentication server. Check browser console for more information"));
console.log(error);
}
plaid_success(token, response) {
frappe
.xcall(
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.update_bank_account_ids",
{
response: response,
}
)
.then(() => {
frappe.show_alert({ message: __("Plaid Link Updated"), indicator: "green" });
});
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.update_bank_account_ids', {
response: response,
}).then(() => {
frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' });
});
}
};

View File

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

View File

@@ -9,7 +9,6 @@ from frappe.contacts.address_and_contact import (
load_address_and_contact,
)
from frappe.model.document import Document
from frappe.utils import comma_and, get_link_to_form
class BankAccount(Document):
@@ -53,23 +52,10 @@ 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:
frappe.throw(_("Company is mandatory for company account"))
frappe.throw(_("Company is manadatory for company account"))
def validate_iban(self):
"""

View File

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

View File

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

View File

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

View File

@@ -5,9 +5,7 @@
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
@@ -181,62 +179,39 @@ def get_payment_entries_for_bank_clearance(
pos_sales_invoices, pos_purchase_invoices = [], []
if include_pos_transactions:
si_payment = frappe.qb.DocType("Sales Invoice Payment")
si = frappe.qb.DocType("Sales Invoice")
acc = frappe.qb.DocType("Account")
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,
)
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)
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,
)
entries = (
list(payment_entries)

View File

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

View File

@@ -48,11 +48,11 @@ class BankGuarantee(Document):
def on_submit(self):
if not self.bank_guarantee_number:
frappe.throw(_("Enter the Bank Guarantee Number before submitting."))
frappe.throw(_("Enter the Bank Guarantee Number before submittting."))
if not self.name_of_beneficiary:
frappe.throw(_("Enter the name of the Beneficiary before submitting."))
frappe.throw(_("Enter the name of the Beneficiary before submittting."))
if not self.bank:
frappe.throw(_("Enter the name of the bank or lending institution before submitting."))
frappe.throw(_("Enter the name of the bank or lending institution before submittting."))
@frappe.whitelist()

View File

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

View File

@@ -76,7 +76,6 @@ class TestBankReconciliationTool(AccountsTestMixin, FrappeTestCase):
"deposit": 100,
"bank_account": self.bank_account,
"reference_number": "123",
"currency": "INR",
}
)
.save()

View File

@@ -17,9 +17,11 @@ 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;
@@ -46,9 +48,20 @@ frappe.ui.form.on("Bank Statement Import", {
: __("Updating {0} of {1}, {2}", message_args);
}
if (data.skipping) {
message = __("Skipping {0} of {1}, {2}", [data.current, data.total, eta_message]);
message = __(
"Skipping {0} of {1}, {2}",
[
data.current,
data.total,
eta_message,
]
);
}
frm.dashboard.show_progress(__("Import Progress"), percent, message);
frm.dashboard.show_progress(
__("Import Progress"),
percent,
message
);
frm.page.set_indicator(__("In Progress"), "orange");
// hide progress when complete
@@ -90,12 +103,15 @@ frappe.ui.form.on("Bank Statement Import", {
frm.trigger("show_report_error_button");
if (frm.doc.status === "Partial Success") {
frm.add_custom_button(__("Export Errored Rows"), () => frm.trigger("export_errored_rows"));
frm.add_custom_button(__("Export Errored Rows"), () =>
frm.trigger("export_errored_rows")
);
}
if (frm.doc.status.includes("Success")) {
frm.add_custom_button(__("Go to {0} List", [__(frm.doc.reference_doctype)]), () =>
frappe.set_route("List", frm.doc.reference_doctype)
frm.add_custom_button(
__("Go to {0} List", [__(frm.doc.reference_doctype)]),
() => frappe.set_route("List", frm.doc.reference_doctype)
);
}
},
@@ -112,8 +128,13 @@ frappe.ui.form.on("Bank Statement Import", {
frm.disable_save();
if (frm.doc.status !== "Success") {
if (!frm.is_new() && frm.has_import_file()) {
let label = frm.doc.status === "Pending" ? __("Start Import") : __("Retry");
frm.page.set_primary_action(label, () => frm.events.start_import(frm));
let label =
frm.doc.status === "Pending"
? __("Start Import")
: __("Retry");
frm.page.set_primary_action(label, () =>
frm.events.start_import(frm)
);
} else {
frm.page.set_primary_action(__("Save"), () => frm.save());
}
@@ -155,24 +176,24 @@ frappe.ui.form.on("Bank Statement Import", {
message =
successful_records.length > 1
? __(
"Successfully imported {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
"Successfully imported {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
: __(
"Successfully imported {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
"Successfully imported {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
} else {
message =
successful_records.length > 1
? __(
"Successfully updated {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
"Successfully updated {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
: __(
"Successfully updated {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
"Successfully updated {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
}
}
frm.dashboard.set_headline(message);
@@ -215,7 +236,8 @@ frappe.ui.form.on("Bank Statement Import", {
},
download_template() {
let method = "/api/method/frappe.core.doctype.data_import.data_import.download_template";
let method =
"/api/method/frappe.core.doctype.data_import.data_import.download_template";
open_url_post(method, {
doctype: "Bank Transaction",
@@ -228,7 +250,7 @@ frappe.ui.form.on("Bank Statement Import", {
"description",
"reference_number",
"bank_account",
"currency",
"currency"
],
},
});
@@ -299,7 +321,10 @@ frappe.ui.form.on("Bank Statement Import", {
show_import_preview(frm, preview_data) {
let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
if (frm.import_preview && frm.import_preview.doctype === frm.doc.reference_doctype) {
if (
frm.import_preview &&
frm.import_preview.doctype === frm.doc.reference_doctype
) {
frm.import_preview.preview_data = preview_data;
frm.import_preview.import_log = import_log;
frm.import_preview.refresh();
@@ -315,10 +340,19 @@ frappe.ui.form.on("Bank Statement Import", {
frm,
events: {
remap_column(changed_map) {
let template_options = JSON.parse(frm.doc.template_options || "{}");
template_options.column_to_field_map = template_options.column_to_field_map || {};
Object.assign(template_options.column_to_field_map, changed_map);
frm.set_value("template_options", JSON.stringify(template_options));
let template_options = JSON.parse(
frm.doc.template_options || "{}"
);
template_options.column_to_field_map =
template_options.column_to_field_map || {};
Object.assign(
template_options.column_to_field_map,
changed_map
);
frm.set_value(
"template_options",
JSON.stringify(template_options)
);
frm.save().then(() => frm.trigger("import_file"));
},
},
@@ -352,7 +386,8 @@ frappe.ui.form.on("Bank Statement Import", {
let other_warnings = [];
for (let warning of warnings) {
if (warning.row) {
warnings_by_row[warning.row] = warnings_by_row[warning.row] || [];
warnings_by_row[warning.row] =
warnings_by_row[warning.row] || [];
warnings_by_row[warning.row].push(warning);
} else {
other_warnings.push(warning);
@@ -367,7 +402,9 @@ frappe.ui.form.on("Bank Statement Import", {
if (w.field) {
let label =
w.field.label +
(w.field.parent !== frm.doc.reference_doctype ? ` (${w.field.parent})` : "");
(w.field.parent !== frm.doc.reference_doctype
? ` (${w.field.parent})`
: "");
return `<li>${label}: ${w.message}</li>`;
}
return `<li>${w.message}</li>`;
@@ -386,9 +423,10 @@ frappe.ui.form.on("Bank Statement Import", {
.map((warning) => {
let header = "";
if (warning.col) {
let column_number = `<span class="text-uppercase">${__("Column {0}", [
warning.col,
])}</span>`;
let column_number = `<span class="text-uppercase">${__(
"Column {0}",
[warning.col]
)}</span>`;
let column_header = columns[warning.col].header_title;
header = `${column_number} (${column_header})`;
}
@@ -427,28 +465,36 @@ frappe.ui.form.on("Bank Statement Import", {
let html = "";
if (log.success) {
if (frm.doc.import_type === "Insert New Records") {
html = __("Successfully imported {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]);
html = __(
"Successfully imported {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]
);
} else {
html = __("Successfully updated {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]);
html = __(
"Successfully updated {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]
);
}
} else {
let messages = log.messages
.map(JSON.parse)
.map((m) => {
let title = m.title ? `<strong>${m.title}</strong>` : "";
let message = m.message ? `<div>${m.message}</div>` : "";
let title = m.title
? `<strong>${m.title}</strong>`
: "";
let message = m.message
? `<div>${m.message}</div>`
: "";
return title + message;
})
.join("");

View File

@@ -80,8 +80,7 @@ class BankStatementImport(DataImport):
from frappe.utils.background_jobs import is_job_enqueued
from frappe.utils.scheduler import is_scheduler_inactive
run_now = frappe.flags.in_test or frappe.conf.developer_mode
if is_scheduler_inactive() and not run_now:
if is_scheduler_inactive() and not frappe.flags.in_test:
frappe.throw(_("Scheduler is inactive. Cannot import data."), title=_("Scheduler Inactive"))
job_id = f"bank_statement_import::{self.name}"
@@ -98,7 +97,7 @@ class BankStatementImport(DataImport):
google_sheets_url=self.google_sheets_url,
bank=self.bank,
template_options=self.template_options,
now=run_now,
now=frappe.conf.developer_mode or frappe.flags.in_test,
)
return True

View File

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

View File

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

View File

@@ -3,7 +3,6 @@
import frappe
from frappe import _
from frappe.model.docstatus import DocStatus
from frappe.model.document import Document
from frappe.utils import flt
@@ -49,24 +48,6 @@ class BankTransaction(Document):
def validate(self):
self.validate_duplicate_references()
self.validate_currency()
def validate_currency(self):
"""
Bank Transaction should be on the same currency as the Bank Account.
"""
if self.currency and self.bank_account:
account = frappe.get_cached_value("Bank Account", self.bank_account, "account")
account_currency = frappe.get_cached_value("Account", account, "account_currency")
if self.currency != account_currency:
frappe.throw(
_(
"Transaction currency: {0} cannot be different from Bank Account({1}) currency: {2}"
).format(
frappe.bold(self.currency), frappe.bold(self.bank_account), frappe.bold(account_currency)
)
)
def set_status(self):
if self.docstatus == 2:
@@ -94,13 +75,10 @@ class BankTransaction(Document):
pe.append(reference)
def update_allocated_amount(self):
allocated_amount = (
self.allocated_amount = (
sum(p.allocated_amount for p in self.payment_entries) if self.payment_entries else 0.0
)
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"))
self.unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) - self.allocated_amount
def before_submit(self):
self.allocate_payment_entries()
@@ -437,21 +415,3 @@ def unclear_reference_payment(doctype, docname, bt_name):
bt = frappe.get_doc("Bank Transaction", bt_name)
set_voucher_clearance(doctype, docname, None, bt)
return docname
def remove_from_bank_transaction(doctype, docname):
"""Remove a (cancelled) voucher from all Bank Transactions."""
for bt_name in get_reconciled_bank_transactions(doctype, docname):
bt = frappe.get_doc("Bank Transaction", bt_name)
if bt.docstatus == DocStatus.cancelled():
continue
modified = False
for pe in bt.payment_entries:
if pe.payment_document == doctype and pe.payment_entry == docname:
bt.remove(pe)
modified = True
if modified:
bt.save()

View File

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

View File

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

View File

@@ -6,18 +6,18 @@ frappe.ui.form.on("Bisect Accounting Statements", {
frm.trigger("render_heatmap");
},
refresh(frm) {
frm.add_custom_button(__("Bisect Left"), () => {
frm.add_custom_button(__('Bisect Left'), () => {
frm.trigger("bisect_left");
});
frm.add_custom_button(__("Bisect Right"), () => {
frm.add_custom_button(__('Bisect Right'), () => {
frm.trigger("bisect_right");
});
frm.add_custom_button(__("Up"), () => {
frm.add_custom_button(__('Up'), () => {
frm.trigger("move_up");
});
frm.add_custom_button(__("Build Tree"), () => {
frm.add_custom_button(__('Build Tree'), () => {
frm.trigger("build_tree");
});
},
@@ -26,16 +26,16 @@ frappe.ui.form.on("Bisect Accounting Statements", {
bisect_heatmap.addClass("bisect_heatmap_location");
// milliseconds in a day
let msiad = 24 * 60 * 60 * 1000;
let msiad=24*60*60*1000;
let datapoints = {};
let fr_dt = new Date(frm.doc.from_date).getTime();
let to_dt = new Date(frm.doc.to_date).getTime();
let bisect_start = new Date(frm.doc.current_from_date).getTime();
let bisect_end = new Date(frm.doc.current_to_date).getTime();
for (let x = fr_dt; x <= to_dt; x += msiad) {
let epoch_in_seconds = x / 1000;
if (bisect_start <= x && x <= bisect_end) {
for(let x=fr_dt; x <= to_dt; x+=msiad){
let epoch_in_seconds = x/1000;
if ((bisect_start <= x) && (x <= bisect_end )) {
datapoints[epoch_in_seconds] = 1.0;
} else {
datapoints[epoch_in_seconds] = 0.0;
@@ -49,19 +49,19 @@ frappe.ui.form.on("Bisect Accounting Statements", {
start: new Date(frm.doc.from_date),
end: new Date(frm.doc.to_date),
},
countLabel: "Bisecting",
countLabel: 'Bisecting',
discreteDomains: 1,
});
},
bisect_left(frm) {
frm.call({
doc: frm.doc,
method: "bisect_left",
method: 'bisect_left',
freeze: true,
freeze_message: __("Bisecting Left ..."),
callback: (r) => {
frm.trigger("render_heatmap");
},
}
});
},
bisect_right(frm) {
@@ -69,10 +69,10 @@ frappe.ui.form.on("Bisect Accounting Statements", {
doc: frm.doc,
freeze: true,
freeze_message: __("Bisecting Right ..."),
method: "bisect_right",
method: 'bisect_right',
callback: (r) => {
frm.trigger("render_heatmap");
},
}
});
},
move_up(frm) {
@@ -80,10 +80,10 @@ frappe.ui.form.on("Bisect Accounting Statements", {
doc: frm.doc,
freeze: true,
freeze_message: __("Moving up in tree ..."),
method: "move_up",
method: 'move_up',
callback: (r) => {
frm.trigger("render_heatmap");
},
}
});
},
build_tree(frm) {
@@ -91,10 +91,10 @@ frappe.ui.form.on("Bisect Accounting Statements", {
doc: frm.doc,
freeze: true,
freeze_message: __("Rebuilding BTree for period ..."),
method: "build_tree",
method: 'build_tree',
callback: (r) => {
frm.trigger("render_heatmap");
},
}
});
},
});

View File

@@ -138,11 +138,10 @@ class BisectAccountingStatements(Document):
# set root as current node
root = frappe.db.get_all("Bisect Nodes", filters={"root": ["is", "not set"]})[0]
self.get_report_summary()
self.current_node = root.name
self.current_from_date = self.from_date
self.current_to_date = self.to_date
self.get_report_summary()
self.save()
def get_report_summary(self):

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
frappe.ui.form.on("Chart of Accounts Importer", {
frappe.ui.form.on('Chart of Accounts Importer', {
onload: function (frm) {
frm.set_value("company", "");
frm.set_value("import_file", "");
@@ -8,34 +8,31 @@ frappe.ui.form.on("Chart of Accounts Importer", {
frm.disable_save();
// make company mandatory
frm.set_df_property("company", "reqd", frm.doc.company ? 0 : 1);
frm.set_df_property("import_file_section", "hidden", frm.doc.company ? 0 : 1);
frm.set_df_property('company', 'reqd', frm.doc.company ? 0 : 1);
frm.set_df_property('import_file_section', 'hidden', frm.doc.company ? 0 : 1);
if (frm.doc.import_file) {
frappe.run_serially([
() => generate_tree_preview(frm),
() => create_import_button(frm),
() => frm.set_df_property("chart_preview", "hidden", 0),
() => frm.set_df_property('chart_preview', 'hidden', 0)
]);
}
frm.set_df_property(
"chart_preview",
"hidden",
$(frm.fields_dict["chart_tree"].wrapper).html() != "" ? 0 : 1
);
frm.set_df_property('chart_preview', 'hidden',
$(frm.fields_dict['chart_tree'].wrapper).html()!="" ? 0 : 1);
},
download_template: function (frm) {
download_template: function(frm) {
var d = new frappe.ui.Dialog({
title: __("Download Template"),
fields: [
{
label: "File Type",
label : "File Type",
fieldname: "file_type",
fieldtype: "Select",
reqd: 1,
options: ["Excel", "CSV"],
options: ["Excel", "CSV"]
},
{
label: "Template Type",
@@ -44,27 +41,21 @@ 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,
@@ -72,25 +63,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();
},
@@ -98,7 +89,7 @@ frappe.ui.form.on("Chart of Accounts Importer", {
import_file: function (frm) {
if (!frm.doc.import_file) {
frm.page.set_indicator("");
$(frm.fields_dict["chart_tree"].wrapper).empty(); // empty wrapper on removing file
$(frm.fields_dict['chart_tree'].wrapper).empty(); // empty wrapper on removing file
}
},
@@ -108,97 +99,89 @@ frappe.ui.form.on("Chart of Accounts Importer", {
frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.validate_company",
args: {
company: frm.doc.company,
company: frm.doc.company
},
callback: function (r) {
if (r.message === false) {
callback: function(r) {
if(r.message===false) {
frm.set_value("company", "");
frappe.throw(
__(
"Transactions against the Company already exist! Chart of Accounts can only be imported for a Company with no transactions."
)
);
frappe.throw(__("Transactions against the Company already exist! Chart of Accounts can only be imported for a Company with no transactions."));
} else {
frm.trigger("refresh");
}
},
}
});
}
},
}
});
var create_import_button = function (frm) {
frm.page
.set_primary_action(__("Import"), function () {
return frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
args: {
file_name: frm.doc.import_file,
company: frm.doc.company,
},
freeze: true,
freeze_message: __("Creating Accounts..."),
callback: function (r) {
if (!r.exc) {
clearInterval(frm.page["interval"]);
frm.page.set_indicator(__("Import Successful"), "blue");
create_reset_button(frm);
}
},
});
})
.addClass("btn btn-primary");
};
var create_reset_button = function (frm) {
frm.page
.set_primary_action(__("Reset"), function () {
frm.page.clear_primary_action();
delete frm.page["show_import_button"];
frm.reload_doc();
})
.addClass("btn btn-primary");
};
var validate_coa = function (frm) {
if (frm.doc.import_file) {
let parent = __("All Accounts");
var create_import_button = function(frm) {
frm.page.set_primary_action(__("Import"), function () {
return frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa",
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
args: {
file_name: frm.doc.import_file,
parent: parent,
doctype: "Chart of Accounts Importer",
file_type: frm.doc.file_type,
for_validate: 1,
company: frm.doc.company
},
callback: function (r) {
if (r.message["show_import_button"]) {
frm.page["show_import_button"] = Boolean(r.message["show_import_button"]);
freeze: true,
freeze_message: __("Creating Accounts..."),
callback: function(r) {
if (!r.exc) {
clearInterval(frm.page["interval"]);
frm.page.set_indicator(__('Import Successful'), 'blue');
create_reset_button(frm);
}
}
});
}).addClass('btn btn-primary');
};
var create_reset_button = function(frm) {
frm.page.set_primary_action(__("Reset"), function () {
frm.page.clear_primary_action();
delete frm.page["show_import_button"];
frm.reload_doc();
}).addClass('btn btn-primary');
};
var validate_coa = function(frm) {
if (frm.doc.import_file) {
let parent = __('All Accounts');
return frappe.call({
'method': 'erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa',
'args': {
file_name: frm.doc.import_file,
parent: parent,
doctype: 'Chart of Accounts Importer',
file_type: frm.doc.file_type,
for_validate: 1
},
callback: function(r) {
if (r.message['show_import_button']) {
frm.page['show_import_button'] = Boolean(r.message['show_import_button']);
}
}
});
}
};
var generate_tree_preview = function (frm) {
let parent = __("All Accounts");
$(frm.fields_dict["chart_tree"].wrapper).empty(); // empty wrapper to load new data
var generate_tree_preview = function(frm) {
let parent = __('All Accounts');
$(frm.fields_dict['chart_tree'].wrapper).empty(); // empty wrapper to load new data
// generate tree structure based on the csv data
return new frappe.ui.Tree({
parent: $(frm.fields_dict["chart_tree"].wrapper),
parent: $(frm.fields_dict['chart_tree'].wrapper),
label: parent,
expandable: true,
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa",
method: 'erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa',
args: {
file_name: frm.doc.import_file,
parent: parent,
doctype: "Chart of Accounts Importer",
file_type: frm.doc.file_type,
doctype: 'Chart of Accounts Importer',
file_type: frm.doc.file_type
},
onclick: function (node) {
onclick: function(node) {
parent = node.value;
},
}
});
};

View File

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

View File

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

View File

@@ -41,7 +41,7 @@
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Cost Center Number",
"read_only_depends_on": "eval:!doc.__islocal"
"read_only": 1
},
{
"fieldname": "parent_cost_center",
@@ -170,4 +170,4 @@
"sort_field": "modified",
"sort_order": "ASC",
"states": []
}
}

View File

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

View File

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

View File

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

View File

@@ -80,7 +80,7 @@
{
"fieldname": "valid_upto",
"fieldtype": "Date",
"label": "Valid Up To"
"label": "Valid Upto"
},
{
"depends_on": "eval: doc.coupon_type == \"Promotional\"",
@@ -115,7 +115,7 @@
"read_only": 1
}
],
"modified": "2024-01-24 02:20:26.145996",
"modified": "2019-10-19 14:48:14.602481",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Coupon Code",

View File

@@ -1,27 +1,28 @@
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Currency Exchange Settings", {
service_provider: function (frm) {
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");
@@ -29,13 +30,13 @@ function add_param(frm, api, params, result) {
frm.doc.api_endpoint = api;
$.each(params, function (key, value) {
$.each(params, function(key, value) {
row = frm.add_child("req_params");
row.key = key;
row.value = value;
});
$.each(result, function (key, value) {
$.each(result, function(key, value) {
row = frm.add_child("result_key");
row.key = value;
});

View File

@@ -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,8 +51,7 @@ frappe.ui.form.on("Dunning", {
__("Payment"),
function () {
frm.events.make_payment_entry(frm);
},
__("Create")
}, __("Create")
);
frm.page.set_inner_btn_group_as_primary(__("Create"));
}
@@ -70,7 +69,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",
@@ -79,12 +78,9 @@ 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) {
@@ -94,8 +90,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) {
@@ -129,16 +125,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");
@@ -170,7 +166,8 @@ frappe.ui.form.on("Dunning", {
get_dunning_letter_text: function (frm) {
if (frm.doc.dunning_type) {
frappe.call({
method: "erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
method:
"erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
args: {
dunning_type: frm.doc.dunning_type,
language: frm.doc.language,
@@ -207,7 +204,10 @@ 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,16 +215,15 @@ 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;
@@ -241,7 +240,8 @@ frappe.ui.form.on("Dunning", {
},
make_payment_entry: function (frm) {
return frappe.call({
method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
method:
"erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
args: {
dt: frm.doc.doctype,
dn: frm.doc.name,
@@ -257,5 +257,5 @@ frappe.ui.form.on("Dunning", {
frappe.ui.form.on("Overdue Payment", {
interest: function (frm) {
frm.trigger("calculate_totals");
},
});
}
});

View File

@@ -85,14 +85,7 @@ class Dunning(AccountsController):
frappe.throw(
_(
"The currency of invoice {} ({}) is different from the currency of this dunning ({})."
).format(
frappe.get_desk_link(
"Sales Invoice",
row.sales_invoice,
),
invoice_currency,
self.currency,
)
).format(row.sales_invoice, invoice_currency, self.currency)
)
def validate_overdue_payments(self):

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
"allow_import": 1,
"autoname": "field:year",
"creation": "2013-01-22 16:50:25",
"description": "Represents a Financial Year. All accounting entries and other major transactions are tracked against the Fiscal Year.",
"description": "**Fiscal Year** represents a Financial Year. All accounting entries and other major transactions are tracked against **Fiscal Year**.",
"doctype": "DocType",
"document_type": "Setup",
"engine": "InnoDB",
@@ -82,11 +82,10 @@
"icon": "fa fa-calendar",
"idx": 1,
"links": [],
"modified": "2024-01-30 12:35:38.645968",
"modified": "2020-11-05 12:16:53.081573",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Fiscal Year",
"naming_rule": "By fieldname",
"owner": "Administrator",
"permissions": [
{
@@ -119,18 +118,9 @@
{
"read": 1,
"role": "Employee"
},
{
"read": 1,
"role": "Accounts Manager"
},
{
"read": 1,
"role": "Stock Manager"
}
],
"show_name_in_global_search": 1,
"sort_field": "name",
"sort_order": "DESC",
"states": []
"sort_order": "DESC"
}

View File

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

View File

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

View File

@@ -17,7 +17,9 @@
"account_currency",
"debit_in_account_currency",
"credit_in_account_currency",
"against_type",
"against",
"against_link",
"against_voucher_type",
"against_voucher",
"voucher_type",
@@ -129,6 +131,13 @@
"label": "Credit Amount in Account Currency",
"options": "account_currency"
},
{
"fieldname": "against_type",
"fieldtype": "Link",
"in_filter": 1,
"label": "Against Type",
"options": "DocType"
},
{
"fieldname": "against",
"fieldtype": "Text",
@@ -137,6 +146,13 @@
"oldfieldname": "against",
"oldfieldtype": "Text"
},
{
"fieldname": "against_link",
"fieldtype": "Dynamic Link",
"in_filter": 1,
"label": "Against",
"options": "against_type"
},
{
"fieldname": "against_voucher_type",
"fieldtype": "Link",
@@ -290,7 +306,7 @@
"idx": 1,
"in_create": 1,
"links": [],
"modified": "2023-09-26 12:03:23.031733",
"modified": "2023-12-18 15:38:14.006208",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",

View File

@@ -13,9 +13,16 @@ import erpnext
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_checks_for_pl_and_bs_accounts,
)
from erpnext.accounts.doctype.accounting_dimension_filter.accounting_dimension_filter import (
get_dimension_filter_map,
)
from erpnext.accounts.party import validate_party_frozen_disabled, validate_party_gle_currency
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
from erpnext.exceptions import InvalidAccountCurrency
from erpnext.exceptions import (
InvalidAccountCurrency,
InvalidAccountDimensionError,
MandatoryAccountDimensionError,
)
exclude_from_linked_with = True
@@ -91,6 +98,7 @@ class GLEntry(Document):
if not self.flags.from_repost and self.voucher_type != "Period Closing Voucher":
self.validate_account_details(adv_adj)
self.validate_dimensions_for_pl_and_bs()
self.validate_allowed_dimensions()
validate_balance_type(self.account, adv_adj)
validate_frozen_account(self.account, adv_adj)
@@ -200,6 +208,42 @@ 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"

View File

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

View File

@@ -153,7 +153,9 @@ class InvoiceDiscounting(AccountsController):
"account": inv.debit_to,
"party_type": "Customer",
"party": d.customer,
"against_type": "Account",
"against": self.accounts_receivable_credit,
"against_link": self.accounts_receivable_credit,
"credit": outstanding_in_company_currency,
"credit_in_account_currency": outstanding_in_company_currency
if inv.party_account_currency == company_currency
@@ -173,7 +175,9 @@ class InvoiceDiscounting(AccountsController):
"account": self.accounts_receivable_credit,
"party_type": "Customer",
"party": d.customer,
"against_type": "Account",
"against": inv.debit_to,
"against_link": inv.debit_to,
"debit": outstanding_in_company_currency,
"debit_in_account_currency": outstanding_in_company_currency
if ar_credit_account_currency == company_currency

View File

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

View File

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

View File

@@ -4,82 +4,39 @@
frappe.provide("erpnext.accounts");
frappe.provide("erpnext.journal_entry");
frappe.ui.form.on("Journal Entry", {
setup: function (frm) {
setup: function(frm) {
frm.add_fetch("bank_account", "account", "account");
frm.ignore_doctypes_on_cancel_all = [
"Sales Invoice",
"Purchase Invoice",
"Journal Entry",
"Repost Payment Ledger",
"Asset",
"Asset Movement",
"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"];
},
refresh: function (frm) {
refresh: function(frm) {
erpnext.toggle_naming_series();
if (frm.doc.repost_required && frm.doc.docstatus === 1) {
frm.set_intro(
__(
"Accounting entries for this Journal Entry need to be reposted. Please click on 'Repost' button to update."
)
);
frm.add_custom_button(__("Repost Accounting Entries"), () => {
frm.call({
doc: frm.doc,
method: "repost_accounting_entries",
freeze: true,
freeze_message: __("Reposting..."),
callback: (r) => {
if (!r.exc) {
frappe.msgprint(__("Accounting Entries are reposted."));
frm.refresh();
}
},
});
})
.removeClass("btn-default")
.addClass("btn-warning");
if(frm.doc.docstatus > 0) {
frm.add_custom_button(__('Ledger'), function() {
frappe.route_options = {
"voucher_no": frm.doc.name,
"from_date": frm.doc.posting_date,
"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'),
"company": frm.doc.company,
"finance_book": frm.doc.finance_book,
"group_by": '',
"show_cancelled_entries": frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, __('View'));
}
if (frm.doc.docstatus > 0) {
frm.add_custom_button(
__("Ledger"),
function () {
frappe.route_options = {
voucher_no: frm.doc.name,
from_date: frm.doc.posting_date,
to_date: moment(frm.doc.modified).format("YYYY-MM-DD"),
company: frm.doc.company,
finance_book: frm.doc.finance_book,
group_by: "",
show_cancelled_entries: frm.doc.docstatus === 2,
};
frappe.set_route("query-report", "General Ledger");
},
__("View")
);
}
if (frm.doc.docstatus == 1) {
frm.add_custom_button(
__("Reverse Journal Entry"),
function () {
return erpnext.journal_entry.reverse_journal_entry(frm);
},
__("Actions")
);
if(frm.doc.docstatus==1) {
frm.add_custom_button(__('Reverse Journal Entry'), function() {
return erpnext.journal_entry.reverse_journal_entry(frm);
}, __('Actions'));
}
if (frm.doc.__islocal) {
frm.add_custom_button(__("Quick Entry"), function () {
frm.add_custom_button(__('Quick Entry'), function() {
return erpnext.journal_entry.quick_entry(frm);
});
}
@@ -87,63 +44,52 @@ 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) {
@@ -151,106 +97,103 @@ frappe.ui.form.on("Journal Entry", {
var doc = frappe.model.sync(r.message)[0];
frappe.set_route("Form", doc.doctype, doc.name);
}
},
}
});
});
d.show();
},
multi_currency: function (frm) {
multi_currency: function(frm) {
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
},
posting_date: function (frm) {
if (!frm.doc.multi_currency || !frm.doc.posting_date) return;
posting_date: function(frm) {
if(!frm.doc.multi_currency || !frm.doc.posting_date) return;
$.each(frm.doc.accounts || [], function (i, row) {
$.each(frm.doc.accounts || [], function(i, row) {
erpnext.journal_entry.set_exchange_rate(frm, row.doctype, row.name);
});
})
},
company: function (frm) {
company: function(frm) {
frappe.call({
method: "frappe.client.get_value",
args: {
doctype: "Company",
filters: { name: frm.doc.company },
fieldname: "cost_center",
filters: {"name": frm.doc.company},
fieldname: "cost_center"
},
callback: function (r) {
if (r.message) {
$.each(frm.doc.accounts || [], function (i, jvd) {
callback: function(r){
if(r.message){
$.each(frm.doc.accounts || [], function(i, jvd) {
frappe.model.set_value(jvd.doctype, jvd.name, "cost_center", r.message.cost_center);
});
}
},
}
});
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
},
voucher_type: function (frm) {
if (!frm.doc.company) return null;
voucher_type: function(frm){
if (
!(frm.doc.accounts || []).length ||
((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)
) {
if (in_list(["Bank Entry", "Cash Entry"], frm.doc.voucher_type)) {
if(!frm.doc.company) return null;
if((!(frm.doc.accounts || []).length) || ((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)) {
if(in_list(["Bank Entry", "Cash Entry"], frm.doc.voucher_type)) {
return frappe.call({
type: "GET",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
args: {
account_type:
frm.doc.voucher_type == "Bank Entry"
? "Bank"
: frm.doc.voucher_type == "Cash Entry"
? "Cash"
: null,
company: frm.doc.company,
"account_type": (frm.doc.voucher_type=="Bank Entry" ?
"Bank" : (frm.doc.voucher_type=="Cash Entry" ? "Cash" : null)),
"company": frm.doc.company
},
callback: function (r) {
if (r.message) {
callback: function(r) {
if(r.message) {
// If default company bank account not set
if (!$.isEmptyObject(r.message)) {
if(!$.isEmptyObject(r.message)){
update_jv_details(frm.doc, [r.message]);
}
}
},
}
});
}
}
},
from_template: function (frm) {
if (frm.doc.from_template) {
frappe.db.get_doc("Journal Entry Template", frm.doc.from_template).then((doc) => {
frappe.model.clear_table(frm.doc, "accounts");
frm.set_value({
company: doc.company,
voucher_type: doc.voucher_type,
naming_series: doc.naming_series,
is_opening: doc.is_opening,
multi_currency: doc.multi_currency,
from_template: function(frm){
if (frm.doc.from_template){
frappe.db.get_doc("Journal Entry Template", frm.doc.from_template)
.then((doc) => {
frappe.model.clear_table(frm.doc, "accounts");
frm.set_value({
"company": doc.company,
"voucher_type": doc.voucher_type,
"naming_series": doc.naming_series,
"is_opening": doc.is_opening,
"multi_currency": doc.multi_currency
})
update_jv_details(frm.doc, doc.accounts);
});
update_jv_details(frm.doc, doc.accounts);
});
}
},
}
});
var update_jv_details = function (doc, r) {
$.each(r, function (i, d) {
var update_jv_details = function(doc, r) {
$.each(r, function(i, d) {
var row = frappe.model.add_child(doc, "Journal Entry Account", "accounts");
frappe.model.set_value(row.doctype, row.name, "account", d.account);
frappe.model.set_value(row.doctype, row.name, "account", d.account)
frappe.model.set_value(row.doctype, row.name, "balance", d.balance)
});
refresh_field("accounts");
};
}
erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Controller {
onload() {
this.load_defaults();
this.setup_queries();
this.setup_balance_formatter();
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
}
@@ -260,67 +203,79 @@ 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("against_account_link", "accounts", function(doc, cdt, cdn) {
return erpnext.journal_entry.against_account_query(me.frm);
});
me.frm.set_query("against_type", "accounts", function(){
return {
query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_type",
}
})
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");
@@ -328,11 +283,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";
}
@@ -343,49 +298,64 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
return out;
});
}
setup_balance_formatter() {
const formatter = function(value, df, options, doc) {
var currency = frappe.meta.get_field_currency(df, doc);
var dr_or_cr = value ? ('<label>' + (value > 0.0 ? __("Dr") : __("Cr")) + '</label>') : "";
return "<div style='text-align: right'>"
+ ((value==null || value==="") ? "" : format_currency(Math.abs(value), currency))
+ " " + dr_or_cr
+ "</div>";
};
this.frm.fields_dict.accounts.grid.update_docfield_property('balance', 'formatter', formatter);
this.frm.fields_dict.accounts.grid.update_docfield_property('party_balance', 'formatter', formatter);
}
reference_name(doc, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn);
if (d.reference_name) {
if (d.reference_type === "Purchase Invoice" && !flt(d.debit)) {
this.get_outstanding("Purchase Invoice", d.reference_name, doc.company, d);
} else if (d.reference_type === "Sales Invoice" && !flt(d.credit)) {
this.get_outstanding("Sales Invoice", d.reference_name, doc.company, d);
} else if (d.reference_type === "Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
this.get_outstanding("Journal Entry", d.reference_name, doc.company, d);
if(d.reference_name) {
if (d.reference_type==="Purchase Invoice" && !flt(d.debit)) {
this.get_outstanding('Purchase Invoice', d.reference_name, doc.company, d);
} else if (d.reference_type==="Sales Invoice" && !flt(d.credit)) {
this.get_outstanding('Sales Invoice', d.reference_name, doc.company, d);
} else if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
this.get_outstanding('Journal Entry', d.reference_name, doc.company, d);
}
}
}
get_outstanding(doctype, docname, company, child) {
var args = {
doctype: doctype,
docname: docname,
party: child.party,
account: child.account,
account_currency: child.account_currency,
company: company,
};
"doctype": doctype,
"docname": docname,
"party": child.party,
"account": child.account,
"account_currency": child.account_currency,
"company": company
}
return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_outstanding",
args: { args: args },
callback: function (r) {
if (r.message) {
$.each(r.message, function (field, value) {
args: { args: args},
callback: function(r) {
if(r.message) {
$.each(r.message, function(field, value) {
frappe.model.set_value(child.doctype, child.name, field, value);
});
})
}
},
}
});
}
accounts_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
$.each(doc.accounts, function (i, d) {
if (d.account && d.party && d.party_type) {
$.each(doc.accounts, function(i, d) {
if(d.account && d.party && d.party_type) {
row.account = d.account;
row.party = d.party;
row.party_type = d.party_type;
@@ -393,8 +363,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 {
@@ -404,141 +374,132 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
}
cur_frm.cscript.update_totals(doc);
erpnext.accounts.dimensions.copy_dimension_from_first_row(this.frm, cdt, cdn, "accounts");
erpnext.accounts.dimensions.copy_dimension_from_first_row(this.frm, cdt, cdn, 'accounts');
}
};
cur_frm.script_manager.make(erpnext.accounts.JournalEntry);
cur_frm.cscript.update_totals = function (doc) {
var td = 0.0;
var tc = 0.0;
cur_frm.cscript.update_totals = function(doc) {
var td=0.0; var tc =0.0;
var accounts = doc.accounts || [];
for (var i in accounts) {
for(var i in accounts) {
td += flt(accounts[i].debit, precision("debit", accounts[i]));
tc += flt(accounts[i].credit, precision("credit", accounts[i]));
}
doc = locals[doc.doctype][doc.name];
doc.total_debit = td;
doc.total_credit = tc;
doc.difference = flt(td - tc, precision("difference"));
refresh_many(["total_debit", "total_credit", "difference"]);
};
doc.difference = flt((td - tc), precision("difference"));
refresh_many(['total_debit','total_credit','difference']);
}
cur_frm.cscript.get_balance = function (doc, dt, dn) {
cur_frm.cscript.get_balance = function(doc,dt,dn) {
cur_frm.cscript.update_totals(doc);
cur_frm.call("get_balance", null, () => {
cur_frm.refresh();
});
};
cur_frm.call('get_balance', null, () => { cur_frm.refresh(); });
}
cur_frm.cscript.validate = function (doc, cdt, cdn) {
cur_frm.cscript.validate = function(doc,cdt,cdn) {
cur_frm.cscript.update_totals(doc);
};
}
frappe.ui.form.on("Journal Entry Account", {
party: function (frm, cdt, cdn) {
party: function(frm, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn);
if (!d.account && d.party_type && d.party) {
if (!frm.doc.company) frappe.throw(__("Please select Company"));
if(!d.account && d.party_type && d.party) {
if(!frm.doc.company) frappe.throw(__("Please select Company"));
return frm.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_party_account_and_currency",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_party_account_and_balance",
child: d,
args: {
company: frm.doc.company,
party_type: d.party_type,
party: d.party,
},
cost_center: d.cost_center
}
});
}
},
cost_center: function (frm, dt, dn) {
erpnext.journal_entry.set_account_details(frm, dt, dn);
cost_center: function(frm, dt, dn) {
erpnext.journal_entry.set_account_balance(frm, dt, dn);
},
account: function (frm, dt, dn) {
erpnext.journal_entry.set_account_details(frm, dt, dn);
account: function(frm, dt, dn) {
erpnext.journal_entry.set_account_balance(frm, dt, dn);
},
debit_in_account_currency: function (frm, cdt, cdn) {
debit_in_account_currency: function(frm, cdt, cdn) {
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
},
credit_in_account_currency: function (frm, cdt, cdn) {
credit_in_account_currency: function(frm, cdt, cdn) {
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
},
debit: function (frm, dt, dn) {
debit: function(frm, dt, dn) {
cur_frm.cscript.update_totals(frm.doc);
},
credit: function (frm, dt, dn) {
credit: function(frm, dt, dn) {
cur_frm.cscript.update_totals(frm.doc);
},
exchange_rate: function (frm, cdt, cdn) {
exchange_rate: function(frm, cdt, cdn) {
var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
var row = locals[cdt][cdn];
if (row.account_currency == company_currency || !frm.doc.multi_currency) {
if(row.account_currency == company_currency || !frm.doc.multi_currency) {
frappe.model.set_value(cdt, cdn, "exchange_rate", 1);
}
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
},
});
}
})
frappe.ui.form.on("Journal Entry Account", "accounts_remove", function (frm) {
frappe.ui.form.on("Journal Entry Account", "accounts_remove", function(frm) {
cur_frm.cscript.update_totals(frm.doc);
});
$.extend(erpnext.journal_entry, {
toggle_fields_based_on_currency: function (frm) {
toggle_fields_based_on_currency: function(frm) {
var fields = ["currency_section", "account_currency", "exchange_rate", "debit", "credit"];
var grid = frm.get_field("accounts").grid;
if (grid) grid.set_column_disp(fields, frm.doc.multi_currency);
if(grid) grid.set_column_disp(fields, frm.doc.multi_currency);
// dynamic label
var field_label_map = {
debit_in_account_currency: "Debit",
credit_in_account_currency: "Credit",
"debit_in_account_currency": "Debit",
"credit_in_account_currency": "Credit"
};
$.each(field_label_map, function (fieldname, label) {
frm.fields_dict.accounts.grid.update_docfield_property(
fieldname,
"label",
frm.doc.multi_currency ? label + " in Account Currency" : label
'label',
frm.doc.multi_currency ? (label + " in Account Currency") : label
);
});
})
},
set_debit_credit_in_company_currency: function (frm, cdt, cdn) {
set_debit_credit_in_company_currency: function(frm, cdt, cdn) {
var row = locals[cdt][cdn];
frappe.model.set_value(
cdt,
cdn,
"debit",
flt(flt(row.debit_in_account_currency) * row.exchange_rate, precision("debit", row))
);
frappe.model.set_value(cdt, cdn, "debit",
flt(flt(row.debit_in_account_currency)*row.exchange_rate, precision("debit", row)));
frappe.model.set_value(
cdt,
cdn,
"credit",
flt(flt(row.credit_in_account_currency) * row.exchange_rate, precision("credit", row))
);
frappe.model.set_value(cdt, cdn, "credit",
flt(flt(row.credit_in_account_currency)*row.exchange_rate, precision("credit", row)));
cur_frm.cscript.update_totals(frm.doc);
},
set_exchange_rate: function (frm, cdt, cdn) {
set_exchange_rate: function(frm, cdt, cdn) {
var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
var row = locals[cdt][cdn];
if (row.account_currency == company_currency || !frm.doc.multi_currency) {
if(row.account_currency == company_currency || !frm.doc.multi_currency) {
row.exchange_rate = 1;
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
} else if (!row.exchange_rate || row.exchange_rate == 1 || row.account_type == "Bank") {
@@ -553,70 +514,50 @@ $.extend(erpnext.journal_entry, {
reference_name: cstr(row.reference_name),
debit: flt(row.debit_in_account_currency),
credit: flt(row.credit_in_account_currency),
exchange_rate: row.exchange_rate,
exchange_rate: row.exchange_rate
},
callback: function (r) {
if (r.message) {
callback: function(r) {
if(r.message) {
row.exchange_rate = r.message;
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
}
},
});
}
})
} else {
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
}
refresh_field("exchange_rate", cdn, "accounts");
},
quick_entry: function (frm) {
quick_entry: function(frm) {
var naming_series_options = frm.fields_dict.naming_series.df.options;
var naming_series_default =
frm.fields_dict.naming_series.df.default || naming_series_options.split("\n")[0];
var naming_series_default = frm.fields_dict.naming_series.df.default || naming_series_options.split("\n")[0];
var dialog = new frappe.ui.Dialog({
title: __("Quick Journal Entry"),
fields: [
{ fieldtype: "Currency", fieldname: "debit", label: __("Amount"), reqd: 1 },
{
fieldtype: "Link",
fieldname: "debit_account",
label: __("Debit Account"),
reqd: 1,
{fieldtype: "Currency", fieldname: "debit", label: __("Amount"), reqd: 1},
{fieldtype: "Link", fieldname: "debit_account", label: __("Debit Account"), reqd: 1,
options: "Account",
get_query: function () {
get_query: function() {
return erpnext.journal_entry.account_query(frm);
},
}
},
{
fieldtype: "Link",
fieldname: "credit_account",
label: __("Credit Account"),
reqd: 1,
{fieldtype: "Link", fieldname: "credit_account", label: __("Credit Account"), reqd: 1,
options: "Account",
get_query: function () {
get_query: function() {
return erpnext.journal_entry.account_query(frm);
},
}
},
{
fieldtype: "Date",
fieldname: "posting_date",
label: __("Date"),
reqd: 1,
default: frm.doc.posting_date,
},
{ fieldtype: "Small Text", fieldname: "user_remark", label: __("User Remark") },
{
fieldtype: "Select",
fieldname: "naming_series",
label: __("Series"),
reqd: 1,
options: naming_series_options,
default: naming_series_default,
},
],
{fieldtype: "Date", fieldname: "posting_date", label: __("Date"), reqd: 1,
default: frm.doc.posting_date},
{fieldtype: "Small Text", fieldname: "user_remark", label: __("User Remark")},
{fieldtype: "Select", fieldname: "naming_series", label: __("Series"), reqd: 1,
options: naming_series_options, default: naming_series_default},
]
});
dialog.set_primary_action(__("Save"), function () {
dialog.set_primary_action(__("Save"), function() {
var btn = this;
var values = dialog.get_values();
@@ -633,21 +574,11 @@ $.extend(erpnext.journal_entry, {
var debit_row = frm.fields_dict.accounts.grid.add_new_row();
frappe.model.set_value(debit_row.doctype, debit_row.name, "account", values.debit_account);
frappe.model.set_value(
debit_row.doctype,
debit_row.name,
"debit_in_account_currency",
values.debit
);
frappe.model.set_value(debit_row.doctype, debit_row.name, "debit_in_account_currency", values.debit);
var credit_row = frm.fields_dict.accounts.grid.add_new_row();
frappe.model.set_value(credit_row.doctype, credit_row.name, "account", values.credit_account);
frappe.model.set_value(
credit_row.doctype,
credit_row.name,
"credit_in_account_currency",
values.debit
);
frappe.model.set_value(credit_row.doctype, credit_row.name, "credit_in_account_currency", values.debit);
frm.save();
@@ -657,39 +588,51 @@ $.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 () {
against_account_query: function(frm) {
if (frm.doc.against_type != "Account"){
return { filters: {} };
}
else {
let filters = { company: frm.doc.company, is_group: 0 };
if(!frm.doc.multi_currency) {
$.extend(filters, {
account_currency: ['in', [frappe.get_doc(":Company", frm.doc.company).default_currency, null]]
});
}
return { filters: filters };
}
},
reverse_journal_entry: function() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_reverse_journal_entry",
frm: cur_frm,
});
frm: cur_frm
})
},
});
$.extend(erpnext.journal_entry, {
set_account_details: function (frm, dt, dn) {
set_account_balance: function(frm, dt, dn) {
var d = locals[dt][dn];
if (d.account) {
if (!frm.doc.company) frappe.throw(__("Please select Company first"));
if (!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
if(d.account) {
if(!frm.doc.company) frappe.throw(__("Please select Company first"));
if(!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_details_and_party_type",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_balance_and_party_type",
args: {
account: d.account,
date: frm.doc.posting_date,
@@ -697,14 +640,15 @@ $.extend(erpnext.journal_entry, {
debit: flt(d.debit_in_account_currency),
credit: flt(d.credit_in_account_currency),
exchange_rate: d.exchange_rate,
cost_center: d.cost_center
},
callback: function (r) {
if (r.message) {
callback: function(r) {
if(r.message) {
$.extend(d, r.message);
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, dt, dn);
refresh_field("accounts");
refresh_field('accounts');
}
},
}
});
}
},

View File

@@ -64,8 +64,7 @@
"stock_entry",
"subscription_section",
"auto_repeat",
"amended_from",
"repost_required"
"amended_from"
],
"fields": [
{
@@ -544,15 +543,6 @@
"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",
@@ -568,7 +558,6 @@
}
],
"modified": "2023-11-23 12:11:04.128015",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry",

View File

@@ -13,10 +13,6 @@ 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,
)
@@ -144,6 +140,7 @@ class JournalEntry(AccountsController):
self.set_print_format_fields()
self.validate_credit_debit_note()
self.validate_empty_accounts_table()
self.set_account_and_party_balance()
self.validate_inter_company_accounts()
self.validate_depr_entry_voucher_type()
@@ -153,24 +150,6 @@ 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 and not frappe.job:
msgprint(_("The task has been enqueued as a background job."), alert=True)
self.queue_action("submit", timeout=4600)
else:
return self._submit()
def cancel(self):
if len(self.accounts) > 100 and not frappe.job:
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()
@@ -180,15 +159,6 @@ 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()
@@ -216,12 +186,9 @@ class JournalEntry(AccountsController):
def update_advance_paid(self):
advance_paid = frappe._dict()
advance_payment_doctypes = frappe.get_hooks(
"advance_payment_receivable_doctypes"
) + frappe.get_hooks("advance_payment_payable_doctypes")
for d in self.get("accounts"):
if d.is_advance:
if d.reference_type in advance_payment_doctypes:
if d.reference_type in frappe.get_hooks("advance_payment_doctypes"):
advance_paid.setdefault(d.reference_type, []).append(d.reference_name)
for voucher_type, order_list in advance_paid.items():
@@ -337,6 +304,7 @@ class JournalEntry(AccountsController):
"account": tax_withholding_details.get("account_head"),
rev_debit_or_credit: tax_withholding_details.get("tax_amount"),
"against_account": parties[0],
"against_account_link": parties[0],
},
)
@@ -578,28 +546,17 @@ class JournalEntry(AccountsController):
elif d.party_type == "Supplier" and flt(d.credit) > 0:
frappe.throw(_("Row {0}: Advance against Supplier must be debit").format(d.idx))
def system_generated_gain_loss(self):
return (
self.voucher_type == "Exchange Gain Or Loss"
and self.multi_currency
and self.is_system_generated
)
def validate_against_jv(self):
for d in self.get("accounts"):
if d.reference_type == "Journal Entry":
account_root_type = frappe.get_cached_value("Account", d.account, "root_type")
if account_root_type == "Asset" and flt(d.debit) > 0 and not self.system_generated_gain_loss():
if account_root_type == "Asset" and flt(d.debit) > 0:
frappe.throw(
_(
"Row #{0}: For {1}, you can select reference document only if account gets credited"
).format(d.idx, d.account)
)
elif (
account_root_type == "Liability"
and flt(d.credit) > 0
and not self.system_generated_gain_loss()
):
elif account_root_type == "Liability" and flt(d.credit) > 0:
frappe.throw(
_(
"Row #{0}: For {1}, you can select reference document only if account gets debited"
@@ -631,7 +588,7 @@ class JournalEntry(AccountsController):
for jvd in against_entries:
if flt(jvd[dr_or_cr]) > 0:
valid = True
if not valid and not self.system_generated_gain_loss():
if not valid:
frappe.throw(
_("Against Journal Entry {0} does not have any unmatched {1} entry").format(
d.reference_name, dr_or_cr
@@ -794,27 +751,90 @@ class JournalEntry(AccountsController):
)
def set_against_account(self):
accounts_debited, accounts_credited = [], []
if self.voucher_type in ("Deferred Revenue", "Deferred Expense"):
for d in self.get("accounts"):
if d.reference_type == "Sales Invoice":
field = "customer"
against_type = "Customer"
else:
field = "supplier"
against_type = "Supplier"
d.against_account = frappe.db.get_value(d.reference_type, d.reference_name, field)
against_account = frappe.db.get_value(d.reference_type, d.reference_name, against_type.lower())
d.against_type = against_type
d.against_account_link = against_account
else:
for d in self.get("accounts"):
if flt(d.debit) > 0:
accounts_debited.append(d.party or d.account)
if flt(d.credit) > 0:
accounts_credited.append(d.party or d.account)
self.get_debited_credited_accounts()
if len(self.accounts_credited) > 1 and len(self.accounts_debited) > 1:
self.auto_set_against_accounts()
return
self.get_against_accounts()
for d in self.get("accounts"):
if flt(d.debit) > 0:
d.against_account = ", ".join(list(set(accounts_credited)))
if flt(d.credit) > 0:
d.against_account = ", ".join(list(set(accounts_debited)))
def auto_set_against_accounts(self):
for i in range(0, len(self.accounts), 2):
acc = self.accounts[i]
against_acc = self.accounts[i + 1]
if acc.debit_in_account_currency > 0:
current_val = acc.debit_in_account_currency * flt(acc.exchange_rate)
against_val = against_acc.credit_in_account_currency * flt(against_acc.exchange_rate)
else:
current_val = acc.credit_in_account_currency * flt(acc.exchange_rate)
against_val = against_acc.debit_in_account_currency * flt(against_acc.exchange_rate)
if current_val == against_val:
acc.against_type = against_acc.party_type or "Account"
against_acc.against_type = acc.party_type or "Account"
acc.against_account_link = against_acc.party or against_acc.account
against_acc.against_account_link = acc.party or acc.account
else:
frappe.msgprint(
_(
"Unable to automatically determine {0} accounts. Set them up in the {1} table if needed."
).format(frappe.bold("against"), frappe.bold("Accounting Entries")),
alert=True,
)
break
def get_against_accounts(self):
self.against_accounts = []
self.split_account = {}
self.get_debited_credited_accounts()
if self.separate_against_account_entries:
no_of_credited_acc, no_of_debited_acc = len(self.accounts_credited), len(self.accounts_debited)
if no_of_credited_acc <= 1 and no_of_debited_acc <= 1:
self.set_against_accounts_for_single_dr_cr()
self.separate_against_account_entries = 0
elif no_of_credited_acc == 1:
self.against_accounts = self.accounts_debited
self.split_account = self.accounts_credited[0]
elif no_of_debited_acc == 1:
self.against_accounts = self.accounts_credited
self.split_account = self.accounts_debited[0]
def get_debited_credited_accounts(self):
self.accounts_debited, self.accounts_credited = [], []
self.separate_against_account_entries = 1
for d in self.get("accounts"):
if flt(d.debit) > 0:
self.accounts_debited.append(d)
elif flt(d.credit) > 0:
self.accounts_credited.append(d)
if d.against_account_link:
self.separate_against_account_entries = 0
break
def set_against_accounts_for_single_dr_cr(self):
against_account = None
for d in self.accounts:
if flt(d.debit) > 0:
against_account = self.accounts_credited[0]
elif flt(d.credit) > 0:
against_account = self.accounts_debited[0]
if against_account:
d.against_type = against_account.party_type or "Account"
d.against_account = against_account.party or against_account.account
d.against_account_link = against_account.party or against_account.account
def validate_debit_credit_amount(self):
if not (self.voucher_type == "Exchange Gain Or Loss" and self.multi_currency):
@@ -1011,42 +1031,108 @@ class JournalEntry(AccountsController):
def build_gl_map(self):
gl_map = []
conversion_rate_map = self.get_conversion_rate_map()
transaction_currency_map = self.get_transaction_currency_map()
company_currency = erpnext.get_company_currency(self.company)
self.get_against_accounts()
for d in self.get("accounts"):
if d.debit or d.credit or (self.voucher_type == "Exchange Gain Or Loss"):
r = [d.user_remark, self.remark]
r = [x for x in r if x]
remarks = "\n".join(r)
gl_map.append(
self.get_gl_dict(
{
"account": d.account,
"party_type": d.party_type,
"due_date": self.due_date,
"party": d.party,
"against": d.against_account,
"debit": flt(d.debit, d.precision("debit")),
"credit": flt(d.credit, d.precision("credit")),
"account_currency": d.account_currency,
"debit_in_account_currency": flt(
d.debit_in_account_currency, d.precision("debit_in_account_currency")
),
"credit_in_account_currency": flt(
d.credit_in_account_currency, d.precision("credit_in_account_currency")
),
"against_voucher_type": d.reference_type,
"against_voucher": d.reference_name,
"remarks": remarks,
"voucher_detail_no": d.reference_detail_no,
"cost_center": d.cost_center,
"project": d.project,
"finance_book": self.finance_book,
},
item=d,
)
gl_dict = self.get_gl_dict(
{
"account": d.account,
"party_type": d.party_type,
"due_date": self.due_date,
"party": d.party,
"debit": flt(d.debit, d.precision("debit")),
"credit": flt(d.credit, d.precision("credit")),
"account_currency": d.account_currency,
"debit_in_account_currency": flt(
d.debit_in_account_currency, d.precision("debit_in_account_currency")
),
"credit_in_account_currency": flt(
d.credit_in_account_currency, d.precision("credit_in_account_currency")
),
"against_voucher_type": d.reference_type,
"against_voucher": d.reference_name,
"remarks": remarks,
"voucher_detail_no": d.reference_detail_no,
"cost_center": d.cost_center,
"project": d.project,
"finance_book": self.finance_book,
"conversion_rate": conversion_rate_map.get(d.against_account_link, 1)
if d.account_currency == company_currency
else 1,
"currency": transaction_currency_map.get(d.against_account_link, d.account_currency)
if d.account_currency == company_currency
else d.account_currency,
},
item=d,
)
if not self.separate_against_account_entries:
gl_dict.update(
{
"against_type": d.against_type,
"against_link": d.against_account_link,
}
)
gl_map.append(gl_dict)
elif d in self.against_accounts:
gl_dict.update(
{
"against_type": self.split_account.get("party_type") or "Account",
"against": self.split_account.get("party") or self.split_account.get("account"),
"against_link": self.split_account.get("party") or self.split_account.get("account"),
}
)
gl_map.append(gl_dict)
else:
for against_account in self.against_accounts:
against_account = against_account.as_dict()
debit = against_account.credit or against_account.credit_in_account_currency
credit = against_account.debit or against_account.debit_in_account_currency
gl_dict = gl_dict.copy()
gl_dict.update(
{
"against_type": against_account.party_type or "Account",
"against": against_account.party or against_account.account,
"against_link": against_account.party or against_account.account,
"debit": flt(debit, d.precision("debit")),
"credit": flt(credit, d.precision("credit")),
"account_currency": d.account_currency,
"debit_in_account_currency": flt(
debit / d.exchange_rate, d.precision("debit_in_account_currency")
),
"credit_in_account_currency": flt(
credit / d.exchange_rate, d.precision("credit_in_account_currency")
),
}
)
gl_map.append(gl_dict)
return gl_map
def get_transaction_currency_map(self):
transaction_currency_map = {}
for account in self.get("accounts"):
transaction_currency_map.setdefault(account.party or account.account, account.account_currency)
return transaction_currency_map
def get_conversion_rate_map(self):
conversion_rate_map = {}
for account in self.get("accounts"):
conversion_rate_map.setdefault(account.party or account.account, account.exchange_rate)
return conversion_rate_map
def make_gl_entries(self, cancel=0, adv_adj=0):
from erpnext.accounts.general_ledger import make_gl_entries
@@ -1179,11 +1265,24 @@ 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, ignore_permissions=False
):
def get_default_bank_cash_account(company, account_type=None, mode_of_payment=None, account=None):
from erpnext.accounts.doctype.sales_invoice.sales_invoice import get_bank_cash_account
if mode_of_payment:
@@ -1221,7 +1320,7 @@ def get_default_bank_cash_account(
return frappe._dict(
{
"account": account,
"balance": get_balance_on(account, ignore_account_permission=ignore_permissions),
"balance": get_balance_on(account),
"account_currency": account_details.account_currency,
"account_type": account_details.account_type,
}
@@ -1346,6 +1445,8 @@ 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"),
@@ -1493,23 +1594,30 @@ def get_outstanding(args):
@frappe.whitelist()
def get_party_account_and_currency(company, party_type, party):
def get_party_account_and_balance(company, party_type, party, cost_center=None):
if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1)
account = get_party_account(party_type, party, company)
account_balance = get_balance_on(account=account, cost_center=cost_center)
party_balance = get_balance_on(
party_type=party_type, party=party, company=company, cost_center=cost_center
)
return {
"account": account,
"balance": account_balance,
"party_balance": party_balance,
"account_currency": frappe.get_cached_value("Account", account, "account_currency"),
}
@frappe.whitelist()
def get_account_details_and_party_type(
account, date, company, debit=None, credit=None, exchange_rate=None
def get_account_balance_and_party_type(
account, date, company, debit=None, credit=None, exchange_rate=None, cost_center=None
):
"""Returns dict of account details and party type to be set in Journal Entry on selection of account."""
"""Returns dict of account balance and party type to be set in Journal Entry on selection of account."""
if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1)
@@ -1529,6 +1637,7 @@ def get_account_details_and_party_type(
party_type = ""
grid_values = {
"balance": get_balance_on(account, date, cost_center=cost_center),
"party_type": party_type,
"account_type": account_details.account_type,
"account_currency": account_details.account_currency or company_currency,
@@ -1646,3 +1755,10 @@ def make_reverse_journal_entry(source_name, target_doc=None):
)
return doclist
@frappe.whitelist()
def get_against_type(doctype, txt, searchfield, start, page_len, filters):
against_types = frappe.db.get_list("Party Type", pluck="name") + ["Account"]
doctype = frappe.qb.DocType("DocType")
return frappe.qb.from_(doctype).select(doctype.name).where(doctype.name.isin(against_types)).run()

View File

@@ -1,8 +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 === 1) {
return [__(doc.voucher_type), "blue", `voucher_type,=,${doc.voucher_type}`];
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]
}
},
}
};

View File

@@ -166,37 +166,43 @@ class TestJournalEntry(unittest.TestCase):
jv.get("accounts")[1].credit_in_account_currency = 5000
jv.submit()
self.voucher_no = jv.name
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.fields = [
"account",
"account_currency",
"debit",
"debit_in_account_currency",
"credit",
"credit_in_account_currency",
]
self.assertTrue(gl_entries)
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",
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": {
"account_currency": "INR",
"debit": 0,
"debit_in_account_currency": 0,
"credit": 5000,
"credit_in_account_currency": 5000,
},
}
self.check_gl_entries()
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])
# cancel
jv.cancel()
@@ -222,37 +228,43 @@ class TestJournalEntry(unittest.TestCase):
rjv.posting_date = nowdate()
rjv.submit()
self.voucher_no = rjv.name
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.fields = [
"account",
"account_currency",
"debit",
"credit",
"debit_in_account_currency",
"credit_in_account_currency",
]
self.assertTrue(gl_entries)
self.expected_gle = [
{
"account": "_Test Bank USD - _TC",
expected_values = {
"_Test Bank USD - _TC": {
"account_currency": "USD",
"debit": 0,
"debit_in_account_currency": 0,
"credit": 5000,
"credit_in_account_currency": 100,
},
{
"account": "Sales - _TC",
"Sales - _TC": {
"account_currency": "INR",
"debit": 5000,
"debit_in_account_currency": 5000,
"credit": 0,
"credit_in_account_currency": 0,
},
]
}
self.check_gl_entries()
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])
def test_disallow_change_in_account_currency_for_a_party(self):
# create jv in USD
@@ -332,25 +344,23 @@ class TestJournalEntry(unittest.TestCase):
jv.insert()
jv.submit()
self.voucher_no = jv.name
expected_values = {
"_Test Cash - _TC": {"cost_center": cost_center},
"_Test Bank - _TC": {"cost_center": cost_center},
}
self.fields = [
"account",
"cost_center",
]
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.expected_gle = [
{
"account": "_Test Bank - _TC",
"cost_center": cost_center,
},
{
"account": "_Test Cash - _TC",
"cost_center": cost_center,
},
]
self.assertTrue(gl_entries)
self.check_gl_entries()
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
def test_jv_with_project(self):
from erpnext.projects.doctype.project.test_project import make_project
@@ -377,22 +387,23 @@ class TestJournalEntry(unittest.TestCase):
jv.insert()
jv.submit()
self.voucher_no = jv.name
expected_values = {
"_Test Cash - _TC": {"project": project_name},
"_Test Bank - _TC": {"project": project_name},
}
self.fields = ["account", "project"]
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.expected_gle = [
{
"account": "_Test Bank - _TC",
"project": project_name,
},
{
"account": "_Test Cash - _TC",
"project": project_name,
},
]
self.assertTrue(gl_entries)
self.check_gl_entries()
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["project"], gle.project)
def test_jv_account_and_party_balance_with_cost_centre(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
@@ -415,79 +426,6 @@ 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,

View File

@@ -9,10 +9,12 @@
"field_order": [
"account",
"account_type",
"balance",
"col_break1",
"bank_account",
"party_type",
"party",
"party_balance",
"accounting_dimensions_section",
"cost_center",
"dimension_col_break",
@@ -35,7 +37,9 @@
"col_break3",
"is_advance",
"user_remark",
"against_account"
"against_type",
"against_account",
"against_account_link"
],
"fields": [
{
@@ -62,7 +66,17 @@
"print_hide": 1
},
{
"allow_on_submit": 1,
"fieldname": "balance",
"fieldtype": "Currency",
"label": "Account Balance",
"no_copy": 1,
"oldfieldname": "balance",
"oldfieldtype": "Data",
"options": "account_currency",
"print_hide": 1,
"read_only": 1
},
{
"default": ":Company",
"description": "If Income or Expense",
"fieldname": "cost_center",
@@ -95,6 +109,14 @@
"label": "Party",
"options": "party_type"
},
{
"fieldname": "party_balance",
"fieldtype": "Currency",
"label": "Party Balance",
"options": "account_currency",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "currency_section",
"fieldtype": "Section Break",
@@ -203,7 +225,6 @@
"no_copy": 1
},
{
"allow_on_submit": 1,
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
@@ -231,14 +252,21 @@
"print_hide": 1
},
{
"fieldname": "against_account",
"fieldtype": "Text",
"hidden": 1,
"fieldname": "against_account",
"fieldtype": "Text",
"hidden": 1,
"label": "Against Account",
"no_copy": 1,
"oldfieldname": "against_account",
"oldfieldtype": "Text",
"print_hide": 1
},
{
"fieldname": "against_account_link",
"fieldtype": "Dynamic Link",
"label": "Against Account",
"no_copy": 1,
"oldfieldname": "against_account",
"oldfieldtype": "Text",
"print_hide": 1
"options": "against_type"
},
{
"collapsible": 1,
@@ -262,12 +290,18 @@
"hidden": 1,
"label": "Reference Detail No",
"no_copy": 1
},
{
"fieldname": "against_type",
"fieldtype": "Link",
"label": "Against Type",
"options": "DocType"
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-02-05 01:10:50.224840",
"modified": "2023-12-02 23:21:22.205409",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry Account",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,77 +1,173 @@
{
"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"
],
"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",
"fields": [
{
"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,
"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
},
{
"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": "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": "percentages",
"fieldtype": "Table",
"label": "Monthly Distribution Percentages",
"oldfieldname": "budget_distribution_details",
"oldfieldtype": "Table",
"options": "Monthly Distribution Percentage"
"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
}
],
"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",
],
"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",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"share": 1,
"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,
"write": 1
},
},
{
"permlevel": 2,
"read": 1,
"report": 1,
"role": "Accounts Manager"
"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
}
],
"sort_field": "modified",
"sort_order": "DESC",
"states": []
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_seen": 0
}

View File

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

View File

@@ -270,7 +270,7 @@ def start_import(invoices):
errors, "<a href='/app/List/Error Log' class='variant-click'>Error Log</a>"
),
indicator="red",
title=_("Error Occurred"),
title=_("Error Occured"),
)
return names

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -87,14 +87,12 @@
"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",
@@ -749,20 +747,6 @@
"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,

View File

@@ -13,7 +13,6 @@ 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,
@@ -178,7 +177,6 @@ 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:
@@ -191,7 +189,7 @@ class PaymentEntry(AccountsController):
def set_liability_account(self):
# Auto setting liability account should only be done during 'draft' status
if self.docstatus > 0 or self.payment_type == "Internal Transfer":
if self.docstatus > 0:
return
if not frappe.db.get_value(
@@ -471,10 +469,7 @@ class PaymentEntry(AccountsController):
)
def set_missing_ref_details(
self,
force: bool = False,
update_ref_details_only_for: list | None = None,
ref_exchange_rate: float | None = None,
self, force: bool = False, update_ref_details_only_for: list | None = None
) -> None:
for d in self.get("references"):
if d.allocated_amount:
@@ -487,8 +482,6 @@ 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:
@@ -792,21 +785,6 @@ 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 self.party_type != "Supplier":
return
@@ -947,10 +925,7 @@ class PaymentEntry(AccountsController):
def calculate_base_allocated_amount_for_reference(self, d) -> float:
base_allocated_amount = 0
advance_payment_doctypes = frappe.get_hooks(
"advance_payment_receivable_doctypes"
) + frappe.get_hooks("advance_payment_payable_doctypes")
if d.reference_doctype in advance_payment_doctypes:
if d.reference_doctype in frappe.get_hooks("advance_payment_doctypes"):
# When referencing Sales/Purchase Order, use the source/target exchange rate depending on payment type.
# This is so there are no Exchange Gain/Loss generated for such doctypes
@@ -1037,19 +1012,19 @@ class PaymentEntry(AccountsController):
)
base_party_amount = flt(self.base_total_allocated_amount) + flt(base_unallocated_amount)
included_taxes = self.get_included_taxes()
if self.payment_type == "Receive":
self.difference_amount = base_party_amount - self.base_received_amount + included_taxes
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 - included_taxes
self.difference_amount = self.base_paid_amount - base_party_amount
else:
self.difference_amount = self.base_paid_amount - flt(self.base_received_amount) - included_taxes
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()
self.difference_amount = flt(
self.difference_amount - total_deductions, self.precision("difference_amount")
self.difference_amount - total_deductions - included_taxes, self.precision("difference_amount")
)
def get_included_taxes(self):
@@ -1169,7 +1144,9 @@ class PaymentEntry(AccountsController):
"account": self.party_account,
"party_type": self.party_type,
"party": self.party,
"against_type": "Account",
"against": against_account,
"against_link": against_account,
"account_currency": self.party_account_currency,
"cost_center": self.cost_center,
},
@@ -1271,13 +1248,7 @@ 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",
"Sales Order",
"Purchase Order",
):
if ref.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Journal Entry"):
self.add_advance_gl_for_reference(gl_entries, ref)
def add_advance_gl_for_reference(self, gl_entries, invoice):
@@ -1291,15 +1262,14 @@ class PaymentEntry(AccountsController):
"voucher_detail_no": invoice.name,
}
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)
posting_date = frappe.db.get_value(
invoice.reference_doctype, invoice.reference_name, "posting_date"
)
if getdate(posting_date) < getdate(self.posting_date):
posting_date = self.posting_date
dr_or_cr = "credit" if invoice.reference_doctype in ["Sales Invoice", "Sales Order"] else "debit"
dr_or_cr = "credit" if invoice.reference_doctype == "Sales Invoice" 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
@@ -1341,7 +1311,9 @@ class PaymentEntry(AccountsController):
{
"account": self.paid_from,
"account_currency": self.paid_from_account_currency,
"against_type": self.party_type if self.payment_type == "Pay" else "Account",
"against": self.party if self.payment_type == "Pay" else self.paid_to,
"against_link": self.party if self.payment_type == "Pay" else self.paid_to,
"credit_in_account_currency": self.paid_amount,
"credit": self.base_paid_amount,
"cost_center": self.cost_center,
@@ -1356,7 +1328,9 @@ class PaymentEntry(AccountsController):
{
"account": self.paid_to,
"account_currency": self.paid_to_account_currency,
"against_type": self.party_type if self.payment_type == "Receive" else "Account",
"against": self.party if self.payment_type == "Receive" else self.paid_from,
"against_link": self.party if self.payment_type == "Receive" else self.paid_from,
"debit_in_account_currency": self.received_amount,
"debit": self.base_received_amount,
"cost_center": self.cost_center,
@@ -1380,6 +1354,7 @@ class PaymentEntry(AccountsController):
rev_dr_or_cr = "credit" if dr_or_cr == "debit" else "debit"
against = self.party or self.paid_to
against_type = self.party_type or "Account"
payment_account = self.get_party_account_for_taxes()
tax_amount = d.tax_amount
base_tax_amount = d.base_tax_amount
@@ -1388,7 +1363,9 @@ class PaymentEntry(AccountsController):
self.get_gl_dict(
{
"account": d.account_head,
"against_type": against_type,
"against": against,
"against_link": against,
dr_or_cr: tax_amount,
dr_or_cr + "_in_account_currency": base_tax_amount
if account_currency == self.company_currency
@@ -1413,7 +1390,9 @@ class PaymentEntry(AccountsController):
self.get_gl_dict(
{
"account": payment_account,
"against_type": against_type,
"against": against,
"against_link": against,
rev_dr_or_cr: tax_amount,
rev_dr_or_cr + "_in_account_currency": base_tax_amount
if account_currency == self.company_currency
@@ -1438,7 +1417,9 @@ class PaymentEntry(AccountsController):
{
"account": d.account,
"account_currency": account_currency,
"against_type": self.party_type or "Account",
"against": self.party or self.paid_from,
"against_link": self.party or self.paid_from,
"debit_in_account_currency": d.amount,
"debit": d.amount,
"cost_center": d.cost_center,
@@ -1455,11 +1436,8 @@ class PaymentEntry(AccountsController):
def update_advance_paid(self):
if self.payment_type in ("Receive", "Pay") and self.party:
advance_payment_doctypes = frappe.get_hooks(
"advance_payment_receivable_doctypes"
) + frappe.get_hooks("advance_payment_payable_doctypes")
for d in self.get("references"):
if d.allocated_amount and d.reference_doctype in advance_payment_doctypes:
if d.allocated_amount and d.reference_doctype in frappe.get_hooks("advance_payment_doctypes"):
frappe.get_doc(
d.reference_doctype, d.reference_name, for_update=True
).set_total_advance_paid()
@@ -1706,13 +1684,6 @@ 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"],
@@ -1946,12 +1917,6 @@ 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"
@@ -2204,11 +2169,6 @@ 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)
@@ -2237,7 +2197,6 @@ def get_payment_entry(
party_type=None,
payment_type=None,
reference_date=None,
ignore_permissions=False,
):
doc = frappe.get_doc(dt, dn)
over_billing_allowance = frappe.db.get_single_value("Accounts Settings", "over_billing_allowance")
@@ -2260,14 +2219,14 @@ def get_payment_entry(
)
# bank or cash
bank = get_bank_cash_account(doc, bank_account, ignore_permissions=ignore_permissions)
bank = get_bank_cash_account(doc, bank_account)
# if default bank or cash account is not set in company master and party has default company bank account, fetch it
if party_type in ["Customer", "Supplier"] and not bank:
party_bank_account = get_party_bank_account(party_type, doc.get(scrub(party_type)))
if party_bank_account:
account = frappe.db.get_value("Bank Account", party_bank_account, "account")
bank = get_bank_cash_account(doc, account, ignore_permissions=ignore_permissions)
bank = get_bank_cash_account(doc, account)
paid_amount, received_amount = set_paid_amount_and_received_amount(
dt, party_account_currency, bank, outstanding_amount, payment_type, bank_amount, doc
@@ -2407,13 +2366,9 @@ def update_accounting_dimensions(pe, doc):
pe.set(dimension, doc.get(dimension))
def get_bank_cash_account(doc, bank_account, ignore_permissions=False):
def get_bank_cash_account(doc, bank_account):
bank = get_default_bank_cash_account(
doc.company,
"Bank",
mode_of_payment=doc.get("mode_of_payment"),
account=bank_account,
ignore_permissions=ignore_permissions,
doc.company, "Bank", mode_of_payment=doc.get("mode_of_payment"), account=bank_account
)
if not bank:

View File

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

View File

@@ -1070,8 +1070,6 @@ 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
)
@@ -1086,7 +1084,6 @@ 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,

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