Compare commits
1 Commits
future_sub
...
ankush-pat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f784b17564 |
@@ -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
|
||||
|
||||
@@ -124,7 +124,6 @@
|
||||
"beforeEach": true,
|
||||
"onScan": true,
|
||||
"extend_cscript": true,
|
||||
"localforage": true,
|
||||
"Plaid": true
|
||||
"localforage": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,13 +28,4 @@ b147b85e6ac19a9220cd1e2958a6ebd99373283a
|
||||
494bd9ef78313436f0424b918f200dab8fc7c20b
|
||||
|
||||
# bulk format python code with black
|
||||
baec607ff5905b1c67531096a9cf50ec7ff00a5d
|
||||
|
||||
# bulk refactor with sourcery
|
||||
eb9ee3f79b94e594fc6dfa4f6514580e125eee8c
|
||||
|
||||
# js formatting
|
||||
ec74a5e56617bbd76ac402451468fd4668af543d
|
||||
|
||||
# ruff formatting
|
||||
a308792ee7fda18a681e9181f4fd00b36385bc23
|
||||
baec607ff5905b1c67531096a9cf50ec7ff00a5d
|
||||
15
.github/helper/documentation.py
vendored
15
.github/helper/documentation.py
vendored
@@ -1,7 +1,7 @@
|
||||
import sys
|
||||
import requests
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import requests
|
||||
|
||||
WEBSITE_REPOS = [
|
||||
"erpnext_com",
|
||||
@@ -36,7 +36,11 @@ def is_documentation_link(word: str) -> bool:
|
||||
|
||||
|
||||
def contains_documentation_link(body: str) -> bool:
|
||||
return any(is_documentation_link(word) for line in body.splitlines() for word in line.split())
|
||||
return any(
|
||||
is_documentation_link(word)
|
||||
for line in body.splitlines()
|
||||
for word in line.split()
|
||||
)
|
||||
|
||||
|
||||
def check_pull_request(number: str) -> "tuple[int, str]":
|
||||
@@ -49,7 +53,12 @@ def check_pull_request(number: str) -> "tuple[int, str]":
|
||||
head_sha = (payload.get("head") or {}).get("sha")
|
||||
body = (payload.get("body") or "").lower()
|
||||
|
||||
if not title.startswith("feat") or not head_sha or "no-docs" in body or "backport" in body:
|
||||
if (
|
||||
not title.startswith("feat")
|
||||
or not head_sha
|
||||
or "no-docs" in body
|
||||
or "backport" in body
|
||||
):
|
||||
return 0, "Skipping documentation checks... 🏃"
|
||||
|
||||
if contains_documentation_link(body):
|
||||
|
||||
18
.github/helper/install.sh
vendored
18
.github/helper/install.sh
vendored
@@ -4,9 +4,7 @@ set -e
|
||||
|
||||
cd ~ || exit
|
||||
|
||||
sudo apt update
|
||||
sudo apt remove mysql-server mysql-client
|
||||
sudo apt install libcups2-dev redis-server mariadb-client-10.6
|
||||
sudo apt update && sudo apt install redis-server libcups2-dev
|
||||
|
||||
pip install frappe-bench
|
||||
|
||||
@@ -27,14 +25,14 @@ fi
|
||||
|
||||
|
||||
if [ "$DB" == "mariadb" ];then
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL character_set_server = 'utf8mb4'"
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL character_set_server = 'utf8mb4'"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
|
||||
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE DATABASE test_frappe"
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE DATABASE test_frappe"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -proot -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
|
||||
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "FLUSH PRIVILEGES"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -proot -e "FLUSH PRIVILEGES"
|
||||
fi
|
||||
|
||||
if [ "$DB" == "postgres" ];then
|
||||
@@ -70,6 +68,6 @@ if [ "$TYPE" == "server" ]; then bench setup requirements --dev; fi
|
||||
|
||||
wait $wkpid
|
||||
|
||||
bench start &>> ~/frappe-bench/bench_start.log &
|
||||
bench start &> bench_run_logs.txt &
|
||||
CI=Yes bench build --app frappe &
|
||||
bench --site test_site reinstall --yes
|
||||
|
||||
34
.github/helper/translation.py
vendored
34
.github/helper/translation.py
vendored
@@ -2,9 +2,7 @@ import re
|
||||
import sys
|
||||
|
||||
errors_encounter = 0
|
||||
pattern = re.compile(
|
||||
r"_\(([\"']{,3})(?P<message>((?!\1).)*)\1(\s*,\s*context\s*=\s*([\"'])(?P<py_context>((?!\5).)*)\5)*(\s*,(\s*?.*?\n*?)*(,\s*([\"'])(?P<js_context>((?!\11).)*)\11)*)*\)"
|
||||
)
|
||||
pattern = re.compile(r"_\(([\"']{,3})(?P<message>((?!\1).)*)\1(\s*,\s*context\s*=\s*([\"'])(?P<py_context>((?!\5).)*)\5)*(\s*,(\s*?.*?\n*?)*(,\s*([\"'])(?P<js_context>((?!\11).)*)\11)*)*\)")
|
||||
words_pattern = re.compile(r"_{1,2}\([\"'`]{1,3}.*?[a-zA-Z]")
|
||||
start_pattern = re.compile(r"_{1,2}\([f\"'`]{1,3}")
|
||||
f_string_pattern = re.compile(r"_\(f[\"']")
|
||||
@@ -12,14 +10,14 @@ starts_with_f_pattern = re.compile(r"_\(f")
|
||||
|
||||
# skip first argument
|
||||
files = sys.argv[1:]
|
||||
files_to_scan = [_file for _file in files if _file.endswith((".py", ".js"))]
|
||||
files_to_scan = [_file for _file in files if _file.endswith(('.py', '.js'))]
|
||||
|
||||
for _file in files_to_scan:
|
||||
with open(_file) as f:
|
||||
print(f"Checking: {_file}")
|
||||
with open(_file, 'r') as f:
|
||||
print(f'Checking: {_file}')
|
||||
file_lines = f.readlines()
|
||||
for line_number, line in enumerate(file_lines, 1):
|
||||
if "frappe-lint: disable-translate" in line:
|
||||
if 'frappe-lint: disable-translate' in line:
|
||||
continue
|
||||
|
||||
start_matches = start_pattern.search(line)
|
||||
@@ -30,9 +28,7 @@ for _file in files_to_scan:
|
||||
has_f_string = f_string_pattern.search(line)
|
||||
if has_f_string:
|
||||
errors_encounter += 1
|
||||
print(
|
||||
f"\nF-strings are not supported for translations at line number {line_number}\n{line.strip()[:100]}"
|
||||
)
|
||||
print(f'\nF-strings are not supported for translations at line number {line_number}\n{line.strip()[:100]}')
|
||||
continue
|
||||
else:
|
||||
continue
|
||||
@@ -40,29 +36,25 @@ for _file in files_to_scan:
|
||||
match = pattern.search(line)
|
||||
error_found = False
|
||||
|
||||
if not match and line.endswith((",\n", "[\n")):
|
||||
if not match and line.endswith((',\n', '[\n')):
|
||||
# concat remaining text to validate multiline pattern
|
||||
line = "".join(file_lines[line_number - 1 :])
|
||||
line = line[start_matches.start() + 1 :]
|
||||
line = "".join(file_lines[line_number - 1:])
|
||||
line = line[start_matches.start() + 1:]
|
||||
match = pattern.match(line)
|
||||
|
||||
if not match:
|
||||
error_found = True
|
||||
print(f"\nTranslation syntax error at line number {line_number}\n{line.strip()[:100]}")
|
||||
print(f'\nTranslation syntax error at line number {line_number}\n{line.strip()[:100]}')
|
||||
|
||||
if not error_found and not words_pattern.search(line):
|
||||
error_found = True
|
||||
print(
|
||||
f"\nTranslation is useless because it has no words at line number {line_number}\n{line.strip()[:100]}"
|
||||
)
|
||||
print(f'\nTranslation is useless because it has no words at line number {line_number}\n{line.strip()[:100]}')
|
||||
|
||||
if error_found:
|
||||
errors_encounter += 1
|
||||
|
||||
if errors_encounter > 0:
|
||||
print(
|
||||
'\nVisit "https://frappeframework.com/docs/user/en/translations" to learn about valid translation strings.'
|
||||
)
|
||||
print('\nVisit "https://frappeframework.com/docs/user/en/translations" to learn about valid translation strings.')
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("\nGood To Go!")
|
||||
print('\nGood To Go!')
|
||||
|
||||
40
.github/helper/update_pot_file.sh
vendored
40
.github/helper/update_pot_file.sh
vendored
@@ -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
|
||||
2
.github/workflows/backport.yml
vendored
2
.github/workflows/backport.yml
vendored
@@ -21,6 +21,6 @@ jobs:
|
||||
- name: Run backport
|
||||
uses: ./actions/backport
|
||||
with:
|
||||
token: ${{secrets.RELEASE_TOKEN}}
|
||||
token: ${{secrets.BACKPORT_BOT_TOKEN}}
|
||||
labelsToAdd: "backport"
|
||||
title: "{{originalTitle}}"
|
||||
|
||||
38
.github/workflows/generate-pot-file.yml
vendored
38
.github/workflows/generate-pot-file.yml
vendored
@@ -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 }}
|
||||
22
.github/workflows/initiate_release.yml
vendored
22
.github/workflows/initiate_release.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: ["14", "15"]
|
||||
version: ["13", "14"]
|
||||
|
||||
steps:
|
||||
- uses: octokit/request-action@v2.x
|
||||
@@ -30,3 +30,23 @@ jobs:
|
||||
head: version-${{ matrix.version }}-hotfix
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
beta-release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: octokit/request-action@v2.x
|
||||
with:
|
||||
route: POST /repos/{owner}/{repo}/pulls
|
||||
owner: frappe
|
||||
repo: erpnext
|
||||
title: |-
|
||||
"chore: release v15 beta"
|
||||
body: "Automated beta release."
|
||||
base: version-15-beta
|
||||
head: develop
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
12
.github/workflows/linters.yml
vendored
12
.github/workflows/linters.yml
vendored
@@ -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
|
||||
|
||||
|
||||
21
.github/workflows/lock.yml
vendored
21
.github/workflows/lock.yml
vendored
@@ -1,21 +0,0 @@
|
||||
name: 'Lock threads'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
|
||||
jobs:
|
||||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v5
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
issue-inactive-days: 14
|
||||
pr-inactive-days: 14
|
||||
79
.github/workflows/patch.yml
vendored
79
.github/workflows/patch.yml
vendored
@@ -23,16 +23,16 @@ jobs:
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mariadb:10.6
|
||||
image: mariadb:10.3
|
||||
env:
|
||||
MARIADB_ROOT_PASSWORD: 'root'
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: --health-cmd="mariadb-admin ping" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Check for valid Python & Merge Conflicts
|
||||
run: |
|
||||
@@ -43,12 +43,14 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: "actions/setup-python@v4"
|
||||
with:
|
||||
python-version: '3.11'
|
||||
python-version: |
|
||||
3.7
|
||||
3.10
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
check-latest: true
|
||||
@@ -57,7 +59,7 @@ jobs:
|
||||
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
||||
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
|
||||
@@ -66,7 +68,7 @@ jobs:
|
||||
${{ runner.os }}-
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
@@ -81,7 +83,7 @@ jobs:
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v2
|
||||
id: yarn-cache
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
@@ -100,61 +102,40 @@ jobs:
|
||||
- name: Run Patch Tests
|
||||
run: |
|
||||
cd ~/frappe-bench/
|
||||
bench remove-app payments --force
|
||||
jq 'del(.install_apps)' ~/frappe-bench/sites/test_site/site_config.json > tmp.json
|
||||
mv tmp.json ~/frappe-bench/sites/test_site/site_config.json
|
||||
|
||||
wget https://erpnext.com/files/v13-erpnext.sql.gz
|
||||
bench --site test_site --force restore ~/frappe-bench/v13-erpnext.sql.gz
|
||||
wget https://erpnext.com/files/v10-erpnext.sql.gz
|
||||
bench --site test_site --force restore ~/frappe-bench/v10-erpnext.sql.gz
|
||||
|
||||
git -C "apps/frappe" remote set-url upstream https://github.com/frappe/frappe.git
|
||||
git -C "apps/erpnext" remote set-url upstream https://github.com/frappe/erpnext.git
|
||||
|
||||
for version in $(seq 12 13)
|
||||
do
|
||||
echo "Updating to v$version"
|
||||
branch_name="version-$version-hotfix"
|
||||
|
||||
function update_to_version() {
|
||||
version=$1
|
||||
git -C "apps/frappe" fetch --depth 1 upstream $branch_name:$branch_name
|
||||
git -C "apps/erpnext" fetch --depth 1 upstream $branch_name:$branch_name
|
||||
|
||||
branch_name="version-$version-hotfix"
|
||||
echo "Updating to v$version"
|
||||
git -C "apps/frappe" checkout -q -f $branch_name
|
||||
git -C "apps/erpnext" checkout -q -f $branch_name
|
||||
|
||||
# Fetch and checkout branches
|
||||
git -C "apps/frappe" fetch --depth 1 upstream $branch_name:$branch_name
|
||||
git -C "apps/erpnext" fetch --depth 1 upstream $branch_name:$branch_name
|
||||
git -C "apps/frappe" checkout -q -f $branch_name
|
||||
git -C "apps/erpnext" checkout -q -f $branch_name
|
||||
rm -rf ~/frappe-bench/env
|
||||
bench setup env --python python3.7
|
||||
bench pip install -e ./apps/payments
|
||||
bench pip install -e ./apps/erpnext
|
||||
|
||||
# Resetup env and install apps
|
||||
pgrep honcho | xargs kill
|
||||
rm -rf ~/frappe-bench/env
|
||||
bench -v setup env
|
||||
bench pip install -e ./apps/erpnext
|
||||
bench start &>> ~/frappe-bench/bench_start.log &
|
||||
bench --site test_site migrate
|
||||
done
|
||||
|
||||
bench --site test_site migrate
|
||||
}
|
||||
|
||||
update_to_version 14
|
||||
update_to_version 15
|
||||
|
||||
echo "Updating to latest version"
|
||||
git -C "apps/frappe" checkout -q -f "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}"
|
||||
git -C "apps/erpnext" checkout -q -f "$GITHUB_SHA"
|
||||
|
||||
pgrep honcho | xargs kill
|
||||
rm -rf ~/frappe-bench/env
|
||||
bench -v setup env
|
||||
bench -v setup env --python python3.10
|
||||
bench pip install -e ./apps/payments
|
||||
bench pip install -e ./apps/erpnext
|
||||
bench start &>> ~/frappe-bench/bench_start.log &
|
||||
|
||||
bench --site test_site migrate
|
||||
|
||||
- name: Show bench output
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
cd ~/frappe-bench
|
||||
cat bench_start.log || true
|
||||
cd logs
|
||||
for f in ./*.log*; do
|
||||
echo "Printing log: $f";
|
||||
cat $f
|
||||
done
|
||||
bench --site test_site install-app payments
|
||||
|
||||
22
.github/workflows/patch_faux.yml
vendored
22
.github/workflows/patch_faux.yml
vendored
@@ -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"
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -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
|
||||
|
||||
24
.github/workflows/server-tests-mariadb-faux.yml
vendored
24
.github/workflows/server-tests-mariadb-faux.yml
vendored
@@ -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"
|
||||
36
.github/workflows/server-tests-mariadb.yml
vendored
36
.github/workflows/server-tests-mariadb.yml
vendored
@@ -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
|
||||
@@ -50,16 +47,16 @@ jobs:
|
||||
MARIADB_ROOT_PASSWORD: 'root'
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: --health-cmd="mariadb-admin ping" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.12'
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Check for valid Python & Merge Conflicts
|
||||
run: |
|
||||
@@ -70,7 +67,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
check-latest: true
|
||||
@@ -79,7 +76,7 @@ jobs:
|
||||
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
||||
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
|
||||
@@ -88,7 +85,7 @@ jobs:
|
||||
${{ runner.os }}-
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
@@ -103,7 +100,7 @@ jobs:
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v2
|
||||
id: yarn-cache
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
@@ -120,19 +117,14 @@ 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' }}
|
||||
|
||||
|
||||
- name: Show bench output
|
||||
if: ${{ always() }}
|
||||
run: cat ~/frappe-bench/bench_start.log || true
|
||||
CI_BUILD_ID: ${{ github.run_id }}
|
||||
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
|
||||
|
||||
- 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,18 +133,16 @@ jobs:
|
||||
name: Coverage Wrap Up
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
|
||||
- name: Upload coverage data
|
||||
uses: codecov/codecov-action@v4
|
||||
uses: codecov/codecov-action@v2
|
||||
with:
|
||||
name: MariaDB
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: true
|
||||
verbose: true
|
||||
|
||||
14
.github/workflows/server-tests-postgres.yml
vendored
14
.github/workflows/server-tests-postgres.yml
vendored
@@ -41,12 +41,12 @@ jobs:
|
||||
steps:
|
||||
|
||||
- name: Clone
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.12'
|
||||
python-version: '3.10'
|
||||
|
||||
- name: Check for valid Python & Merge Conflicts
|
||||
run: |
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
check-latest: true
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
||||
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
|
||||
@@ -75,7 +75,7 @@ jobs:
|
||||
${{ runner.os }}-
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v2
|
||||
id: yarn-cache
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,6 +2,7 @@
|
||||
*.py~
|
||||
.DS_Store
|
||||
conf.py
|
||||
locale
|
||||
latest_updates.json
|
||||
.wnf-lang-status
|
||||
*.egg-info
|
||||
|
||||
48
.mergify.yml
48
.mergify.yml
@@ -15,9 +15,6 @@ pull_request_rules:
|
||||
- or:
|
||||
- base=version-13
|
||||
- base=version-12
|
||||
- base=version-14
|
||||
- base=version-15
|
||||
- base=version-16
|
||||
actions:
|
||||
close:
|
||||
comment:
|
||||
@@ -25,6 +22,16 @@ pull_request_rules:
|
||||
@{{author}}, thanks for the contribution, but we do not accept pull requests on a stable branch. Please raise PR on an appropriate hotfix branch.
|
||||
https://github.com/frappe/erpnext/wiki/Pull-Request-Checklist#which-branch
|
||||
|
||||
- name: Auto-close PRs on pre-release branch
|
||||
conditions:
|
||||
- base=version-13-pre-release
|
||||
actions:
|
||||
close:
|
||||
comment:
|
||||
message: |
|
||||
@{{author}}, pre-release branch is not maintained anymore. Releases are directly done by merging hotfix branch to stable branches.
|
||||
|
||||
|
||||
- name: backport to develop
|
||||
conditions:
|
||||
- label="backport develop"
|
||||
@@ -45,13 +52,13 @@ pull_request_rules:
|
||||
assignees:
|
||||
- "{{ author }}"
|
||||
|
||||
- name: backport to version-15-hotfix
|
||||
- name: backport to version-14-pre-release
|
||||
conditions:
|
||||
- label="backport version-15-hotfix"
|
||||
- label="backport version-14-pre-release"
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- version-15-hotfix
|
||||
- version-14-pre-release
|
||||
assignees:
|
||||
- "{{ author }}"
|
||||
|
||||
@@ -65,6 +72,35 @@ pull_request_rules:
|
||||
assignees:
|
||||
- "{{ author }}"
|
||||
|
||||
- name: backport to version-13-pre-release
|
||||
conditions:
|
||||
- label="backport version-13-pre-release"
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- version-13-pre-release
|
||||
assignees:
|
||||
- "{{ author }}"
|
||||
|
||||
- name: backport to version-12-hotfix
|
||||
conditions:
|
||||
- label="backport version-12-hotfix"
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- version-12-hotfix
|
||||
assignees:
|
||||
- "{{ author }}"
|
||||
|
||||
- name: backport to version-12-pre-release
|
||||
conditions:
|
||||
- label="backport version-12-pre-release"
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- version-12-pre-release
|
||||
assignees:
|
||||
- "{{ author }}"
|
||||
|
||||
- name: Automatic merge on CI success and review
|
||||
conditions:
|
||||
|
||||
@@ -5,7 +5,7 @@ fail_fast: false
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.3.0
|
||||
rev: v4.0.1
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
files: "erpnext.*"
|
||||
@@ -15,27 +15,6 @@ repos:
|
||||
args: ['--branch', 'develop']
|
||||
- id: check-merge-conflict
|
||||
- id: check-ast
|
||||
- id: check-json
|
||||
- id: check-toml
|
||||
- id: check-yaml
|
||||
- id: debug-statements
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: v2.7.1
|
||||
hooks:
|
||||
- id: prettier
|
||||
types_or: [javascript, vue, scss]
|
||||
# Ignore any files that might contain jinja / bundles
|
||||
exclude: |
|
||||
(?x)^(
|
||||
erpnext/public/dist/.*|
|
||||
cypress/.*|
|
||||
.*node_modules.*|
|
||||
.*boilerplate.*|
|
||||
erpnext/public/js/controllers/.*|
|
||||
erpnext/templates/pages/order.js|
|
||||
erpnext/templates/includes/.*
|
||||
)$
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-eslint
|
||||
rev: v8.44.0
|
||||
@@ -55,15 +34,27 @@ repos:
|
||||
erpnext/templates/includes/.*
|
||||
)$
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.2.0
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 6.0.0
|
||||
hooks:
|
||||
- id: ruff
|
||||
name: "Run ruff linter and apply fixes"
|
||||
args: ["--fix"]
|
||||
- id: flake8
|
||||
additional_dependencies: [
|
||||
'flake8-bugbear',
|
||||
]
|
||||
args: ['--config', '.github/helper/.flake8_strict']
|
||||
exclude: ".*setup.py$"
|
||||
|
||||
- id: ruff-format
|
||||
name: "Format Python code"
|
||||
- repo: https://github.com/adityahase/black
|
||||
rev: 9cb0a69f4d0030cdf687eddf314468b39ed54119
|
||||
hooks:
|
||||
- id: black
|
||||
additional_dependencies: ['click==8.0.4']
|
||||
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.12.0
|
||||
hooks:
|
||||
- id: isort
|
||||
exclude: ".*setup.py$"
|
||||
|
||||
|
||||
ci:
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
<p>ERP made simple</p>
|
||||
</p>
|
||||
|
||||
[](https://github.com/frappe/erpnext/actions/workflows/server-tests-mariadb.yml)
|
||||
[](https://github.com/frappe/erpnext/actions/workflows/server-tests.yml)
|
||||
[](https://github.com/erpnext/erpnext_ui_tests/actions/workflows/ui-tests.yml)
|
||||
[](https://www.codetriage.com/frappe/erpnext)
|
||||
[](https://codecov.io/gh/frappe/erpnext)
|
||||
[](https://hub.docker.com/r/frappe/erpnext-worker)
|
||||
@@ -72,6 +73,8 @@ New passwords will be created for the ERPNext "Administrator" user, the MariaDB
|
||||
1. [Issue Guidelines](https://github.com/frappe/erpnext/wiki/Issue-Guidelines)
|
||||
1. [Report Security Vulnerabilities](https://erpnext.com/security)
|
||||
1. [Pull Request Requirements](https://github.com/frappe/erpnext/wiki/Contribution-Guidelines)
|
||||
1. [Translations](https://translate.erpnext.com)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
**/setup/setup_wizard/data/uom_data.json,erpnext.gettext.extractors.uom_data.extract
|
||||
|
@@ -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',
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
files:
|
||||
- source: /erpnext/locale/main.pot
|
||||
translation: /erpnext/locale/%two_letters_code%.po
|
||||
pull_request_title: "fix: sync translations from crowdin"
|
||||
pull_request_labels:
|
||||
- translation
|
||||
commit_message: "fix: %language% translations"
|
||||
append_commit_message: false
|
||||
@@ -3,7 +3,7 @@ import inspect
|
||||
|
||||
import frappe
|
||||
|
||||
__version__ = "16.0.0-dev"
|
||||
__version__ = "15.0.0-dev"
|
||||
|
||||
|
||||
def get_default_company(user=None):
|
||||
@@ -13,7 +13,7 @@ def get_default_company(user=None):
|
||||
if not user:
|
||||
user = frappe.session.user
|
||||
|
||||
companies = get_user_default_as_list("company", user)
|
||||
companies = get_user_default_as_list(user, "company")
|
||||
if companies:
|
||||
default_company = companies[0]
|
||||
else:
|
||||
@@ -36,8 +36,10 @@ def get_default_cost_center(company):
|
||||
|
||||
if not frappe.flags.company_cost_center:
|
||||
frappe.flags.company_cost_center = {}
|
||||
if company not in frappe.flags.company_cost_center:
|
||||
frappe.flags.company_cost_center[company] = frappe.get_cached_value("Company", company, "cost_center")
|
||||
if not company in frappe.flags.company_cost_center:
|
||||
frappe.flags.company_cost_center[company] = frappe.get_cached_value(
|
||||
"Company", company, "cost_center"
|
||||
)
|
||||
return frappe.flags.company_cost_center[company]
|
||||
|
||||
|
||||
@@ -45,7 +47,7 @@ def get_company_currency(company):
|
||||
"""Returns the default company currency"""
|
||||
if not frappe.flags.company_currency:
|
||||
frappe.flags.company_currency = {}
|
||||
if company not in frappe.flags.company_currency:
|
||||
if not company in frappe.flags.company_currency:
|
||||
frappe.flags.company_currency[company] = frappe.db.get_value(
|
||||
"Company", company, "default_currency", cache=True
|
||||
)
|
||||
@@ -79,7 +81,7 @@ def is_perpetual_inventory_enabled(company):
|
||||
if not hasattr(frappe.local, "enable_perpetual_inventory"):
|
||||
frappe.local.enable_perpetual_inventory = {}
|
||||
|
||||
if company not in frappe.local.enable_perpetual_inventory:
|
||||
if not company in frappe.local.enable_perpetual_inventory:
|
||||
frappe.local.enable_perpetual_inventory[company] = (
|
||||
frappe.get_cached_value("Company", company, "enable_perpetual_inventory") or 0
|
||||
)
|
||||
@@ -94,7 +96,7 @@ def get_default_finance_book(company=None):
|
||||
if not hasattr(frappe.local, "default_finance_book"):
|
||||
frappe.local.default_finance_book = {}
|
||||
|
||||
if company not in frappe.local.default_finance_book:
|
||||
if not company in frappe.local.default_finance_book:
|
||||
frappe.local.default_finance_book[company] = frappe.get_cached_value(
|
||||
"Company", company, "default_finance_book"
|
||||
)
|
||||
@@ -106,7 +108,7 @@ def get_party_account_type(party_type):
|
||||
if not hasattr(frappe.local, "party_account_types"):
|
||||
frappe.local.party_account_types = {}
|
||||
|
||||
if party_type not in frappe.local.party_account_types:
|
||||
if not party_type in frappe.local.party_account_types:
|
||||
frappe.local.party_account_types[party_type] = (
|
||||
frappe.db.get_value("Party Type", party_type, "account_type") or ""
|
||||
)
|
||||
|
||||
@@ -11,14 +11,14 @@ class ERPNextAddress(Address):
|
||||
def validate(self):
|
||||
self.validate_reference()
|
||||
self.update_compnay_address()
|
||||
super().validate()
|
||||
super(ERPNextAddress, self).validate()
|
||||
|
||||
def link_address(self):
|
||||
"""Link address based on owner"""
|
||||
if self.is_your_company_address:
|
||||
return
|
||||
|
||||
return super().link_address()
|
||||
return super(ERPNextAddress, self).link_address()
|
||||
|
||||
def update_compnay_address(self):
|
||||
for link in self.get("links"):
|
||||
@@ -26,11 +26,11 @@ class ERPNextAddress(Address):
|
||||
self.is_your_company_address = 1
|
||||
|
||||
def validate_reference(self):
|
||||
if self.is_your_company_address and not [row for row in self.links if row.link_doctype == "Company"]:
|
||||
if self.is_your_company_address and not [
|
||||
row for row in self.links if row.link_doctype == "Company"
|
||||
]:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Address needs to be linked to a Company. Please add a row for Company in the Links table."
|
||||
),
|
||||
_("Address needs to be linked to a Company. Please add a row for Company in the Links table."),
|
||||
title=_("Company Not Linked"),
|
||||
)
|
||||
|
||||
|
||||
@@ -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
|
||||
},
|
||||
],
|
||||
]
|
||||
};
|
||||
|
||||
@@ -37,7 +37,7 @@ def get(
|
||||
filters = frappe.parse_json(filters) or frappe.parse_json(chart.filters_json)
|
||||
|
||||
account = filters.get("account")
|
||||
filters.get("company")
|
||||
company = filters.get("company")
|
||||
|
||||
if not account and chart_name:
|
||||
frappe.throw(
|
||||
@@ -83,6 +83,7 @@ def build_result(account, dates, gl_entries):
|
||||
|
||||
# get balances in debit
|
||||
for entry in gl_entries:
|
||||
|
||||
# entry date is after the current pointer, so move the pointer forward
|
||||
while getdate(entry.posting_date) > result[date_index][0]:
|
||||
date_index += 1
|
||||
@@ -132,6 +133,8 @@ def get_dates_from_timegrain(from_date, to_date, timegrain):
|
||||
|
||||
dates = [get_period_ending(from_date, timegrain)]
|
||||
while getdate(dates[-1]) < getdate(to_date):
|
||||
date = get_period_ending(add_to_date(dates[-1], years=years, months=months, days=days), timegrain)
|
||||
date = get_period_ending(
|
||||
add_to_date(dates[-1], years=years, months=months, days=days), timegrain
|
||||
)
|
||||
dates.append(date)
|
||||
return dates
|
||||
|
||||
@@ -24,10 +24,14 @@ from erpnext.accounts.utils import get_account_currency
|
||||
def validate_service_stop_date(doc):
|
||||
"""Validates service_stop_date for Purchase Invoice and Sales Invoice"""
|
||||
|
||||
enable_check = "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
|
||||
enable_check = (
|
||||
"enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
|
||||
)
|
||||
|
||||
old_stop_dates = {}
|
||||
old_doc = frappe.db.get_all(f"{doc.doctype} Item", {"parent": doc.name}, ["name", "service_stop_date"])
|
||||
old_doc = frappe.db.get_all(
|
||||
"{0} Item".format(doc.doctype), {"parent": doc.name}, ["name", "service_stop_date"]
|
||||
)
|
||||
|
||||
for d in old_doc:
|
||||
old_stop_dates[d.name] = d.service_stop_date or ""
|
||||
@@ -58,14 +62,16 @@ def build_conditions(process_type, account, company):
|
||||
)
|
||||
|
||||
if account:
|
||||
conditions += f"AND {deferred_account}='{account}'"
|
||||
conditions += "AND %s='%s'" % (deferred_account, account)
|
||||
elif company:
|
||||
conditions += f"AND p.company = {frappe.db.escape(company)}"
|
||||
|
||||
return conditions
|
||||
|
||||
|
||||
def convert_deferred_expense_to_expense(deferred_process, start_date=None, end_date=None, conditions=""):
|
||||
def convert_deferred_expense_to_expense(
|
||||
deferred_process, start_date=None, end_date=None, conditions=""
|
||||
):
|
||||
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
|
||||
|
||||
if not start_date:
|
||||
@@ -75,14 +81,16 @@ def convert_deferred_expense_to_expense(deferred_process, start_date=None, end_d
|
||||
|
||||
# check for the purchase invoice for which GL entries has to be done
|
||||
invoices = frappe.db.sql_list(
|
||||
f"""
|
||||
"""
|
||||
select distinct item.parent
|
||||
from `tabPurchase Invoice Item` item, `tabPurchase Invoice` p
|
||||
where item.service_start_date<=%s and item.service_end_date>=%s
|
||||
and item.enable_deferred_expense = 1 and item.parent=p.name
|
||||
and item.docstatus = 1 and ifnull(item.amount, 0) > 0
|
||||
{conditions}
|
||||
""",
|
||||
{0}
|
||||
""".format(
|
||||
conditions
|
||||
),
|
||||
(end_date, start_date),
|
||||
) # nosec
|
||||
|
||||
@@ -95,7 +103,9 @@ def convert_deferred_expense_to_expense(deferred_process, start_date=None, end_d
|
||||
send_mail(deferred_process)
|
||||
|
||||
|
||||
def convert_deferred_revenue_to_income(deferred_process, start_date=None, end_date=None, conditions=""):
|
||||
def convert_deferred_revenue_to_income(
|
||||
deferred_process, start_date=None, end_date=None, conditions=""
|
||||
):
|
||||
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
|
||||
|
||||
if not start_date:
|
||||
@@ -105,14 +115,16 @@ def convert_deferred_revenue_to_income(deferred_process, start_date=None, end_da
|
||||
|
||||
# check for the sales invoice for which GL entries has to be done
|
||||
invoices = frappe.db.sql_list(
|
||||
f"""
|
||||
"""
|
||||
select distinct item.parent
|
||||
from `tabSales Invoice Item` item, `tabSales Invoice` p
|
||||
where item.service_start_date<=%s and item.service_end_date>=%s
|
||||
and item.enable_deferred_revenue = 1 and item.parent=p.name
|
||||
and item.docstatus = 1 and ifnull(item.amount, 0) > 0
|
||||
{conditions}
|
||||
""",
|
||||
{0}
|
||||
""".format(
|
||||
conditions
|
||||
),
|
||||
(end_date, start_date),
|
||||
) # nosec
|
||||
|
||||
@@ -220,7 +232,7 @@ def calculate_monthly_amount(
|
||||
if amount + already_booked_amount_in_account_currency > item.net_amount:
|
||||
amount = item.net_amount - already_booked_amount_in_account_currency
|
||||
|
||||
if get_first_day(start_date) != start_date or get_last_day(end_date) != end_date:
|
||||
if not (get_first_day(start_date) == start_date and get_last_day(end_date) == end_date):
|
||||
partial_month = flt(date_diff(end_date, start_date)) / flt(
|
||||
date_diff(get_last_day(end_date), get_first_day(start_date))
|
||||
)
|
||||
@@ -231,7 +243,9 @@ def calculate_monthly_amount(
|
||||
already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(
|
||||
doc, item
|
||||
)
|
||||
base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
|
||||
base_amount = flt(
|
||||
item.base_net_amount - already_booked_amount, item.precision("base_net_amount")
|
||||
)
|
||||
if account_currency == doc.company_currency:
|
||||
amount = base_amount
|
||||
else:
|
||||
@@ -251,13 +265,17 @@ def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, a
|
||||
if account_currency == doc.company_currency:
|
||||
amount = base_amount
|
||||
else:
|
||||
amount = flt(item.net_amount * total_booking_days / flt(total_days), item.precision("net_amount"))
|
||||
amount = flt(
|
||||
item.net_amount * total_booking_days / flt(total_days), item.precision("net_amount")
|
||||
)
|
||||
else:
|
||||
already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(
|
||||
doc, item
|
||||
)
|
||||
|
||||
base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
|
||||
base_amount = flt(
|
||||
item.base_net_amount - already_booked_amount, item.precision("base_net_amount")
|
||||
)
|
||||
if account_currency == doc.company_currency:
|
||||
amount = base_amount
|
||||
else:
|
||||
@@ -278,22 +296,26 @@ def get_already_booked_amount(doc, item):
|
||||
|
||||
gl_entries_details = frappe.db.sql(
|
||||
"""
|
||||
select sum({}) as total_credit, sum({}) as total_credit_in_account_currency, voucher_detail_no
|
||||
select sum({0}) as total_credit, sum({1}) as total_credit_in_account_currency, voucher_detail_no
|
||||
from `tabGL Entry` where company=%s and account=%s and voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
|
||||
and is_cancelled = 0
|
||||
group by voucher_detail_no
|
||||
""".format(total_credit_debit, total_credit_debit_currency),
|
||||
""".format(
|
||||
total_credit_debit, total_credit_debit_currency
|
||||
),
|
||||
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
journal_entry_details = frappe.db.sql(
|
||||
"""
|
||||
SELECT sum(c.{}) as total_credit, sum(c.{}) as total_credit_in_account_currency, reference_detail_no
|
||||
SELECT sum(c.{0}) as total_credit, sum(c.{1}) as total_credit_in_account_currency, reference_detail_no
|
||||
FROM `tabJournal Entry` p , `tabJournal Entry Account` c WHERE p.name = c.parent and
|
||||
p.company = %s and c.account=%s and c.reference_type=%s and c.reference_name=%s and c.reference_detail_no=%s
|
||||
and p.docstatus < 2 group by reference_detail_no
|
||||
""".format(total_credit_debit, total_credit_debit_currency),
|
||||
""".format(
|
||||
total_credit_debit, total_credit_debit_currency
|
||||
),
|
||||
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
|
||||
as_dict=True,
|
||||
)
|
||||
@@ -315,9 +337,11 @@ def get_already_booked_amount(doc, item):
|
||||
|
||||
|
||||
def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
||||
enable_check = "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
|
||||
enable_check = (
|
||||
"enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
|
||||
)
|
||||
|
||||
accounts_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto")
|
||||
accounts_frozen_upto = frappe.get_cached_value("Accounts Settings", "None", "acc_frozen_upto")
|
||||
|
||||
def _book_deferred_revenue_or_expense(
|
||||
item,
|
||||
@@ -416,7 +440,9 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
||||
via_journal_entry = cint(
|
||||
frappe.db.get_singles_value("Accounts Settings", "book_deferred_entries_via_journal_entry")
|
||||
)
|
||||
submit_journal_entry = cint(frappe.db.get_singles_value("Accounts Settings", "submit_journal_entries"))
|
||||
submit_journal_entry = cint(
|
||||
frappe.db.get_singles_value("Accounts Settings", "submit_journal_entries")
|
||||
)
|
||||
book_deferred_entries_based_on = frappe.db.get_singles_value(
|
||||
"Accounts Settings", "book_deferred_entries_based_on"
|
||||
)
|
||||
@@ -436,7 +462,9 @@ def process_deferred_accounting(posting_date=None):
|
||||
posting_date = today()
|
||||
|
||||
if not cint(
|
||||
frappe.db.get_singles_value("Accounts Settings", "automatically_process_deferred_accounting_entry")
|
||||
frappe.db.get_singles_value(
|
||||
"Accounts Settings", "automatically_process_deferred_accounting_entry"
|
||||
)
|
||||
):
|
||||
return
|
||||
|
||||
@@ -559,13 +587,16 @@ def book_revenue_via_journal_entry(
|
||||
deferred_process=None,
|
||||
submit="No",
|
||||
):
|
||||
|
||||
if amount == 0:
|
||||
return
|
||||
|
||||
journal_entry = frappe.new_doc("Journal Entry")
|
||||
journal_entry.posting_date = posting_date
|
||||
journal_entry.company = doc.company
|
||||
journal_entry.voucher_type = "Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense"
|
||||
journal_entry.voucher_type = (
|
||||
"Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense"
|
||||
)
|
||||
journal_entry.process_deferred_accounting = deferred_process
|
||||
|
||||
debit_entry = {
|
||||
@@ -614,6 +645,7 @@ def book_revenue_via_journal_entry(
|
||||
|
||||
|
||||
def get_deferred_booking_accounts(doctype, voucher_detail_no, dr_or_cr):
|
||||
|
||||
if doctype == "Sales Invoice":
|
||||
credit_account, debit_account = frappe.db.get_value(
|
||||
"Sales Invoice Item",
|
||||
|
||||
@@ -1,32 +1,33 @@
|
||||
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.ui.form.on("Account", {
|
||||
setup: function (frm) {
|
||||
frm.add_fetch("parent_account", "report_type", "report_type");
|
||||
frm.add_fetch("parent_account", "root_type", "root_type");
|
||||
frappe.ui.form.on('Account', {
|
||||
setup: function(frm) {
|
||||
frm.add_fetch('parent_account', 'report_type', 'report_type');
|
||||
frm.add_fetch('parent_account', 'root_type', 'root_type');
|
||||
},
|
||||
onload: function (frm) {
|
||||
frm.set_query("parent_account", function (doc) {
|
||||
onload: function(frm) {
|
||||
frm.set_query('parent_account', function(doc) {
|
||||
return {
|
||||
filters: {
|
||||
is_group: 1,
|
||||
company: doc.company,
|
||||
},
|
||||
"is_group": 1,
|
||||
"company": doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
refresh: function (frm) {
|
||||
frm.toggle_display("account_name", frm.is_new());
|
||||
refresh: function(frm) {
|
||||
frm.toggle_display('account_name', frm.is_new());
|
||||
|
||||
// hide fields if group
|
||||
frm.toggle_display(["tax_rate"], cint(frm.doc.is_group) == 0);
|
||||
frm.toggle_display(['account_type', 'tax_rate'], cint(frm.doc.is_group) == 0);
|
||||
|
||||
// disable fields
|
||||
frm.toggle_enable(["is_group", "company"], false);
|
||||
frm.toggle_enable(['is_group', 'company'], false);
|
||||
|
||||
if (cint(frm.doc.is_group) == 0) {
|
||||
frm.toggle_display("freeze_account", frm.doc.__onload && frm.doc.__onload.can_freeze_account);
|
||||
frm.toggle_display('freeze_account', frm.doc.__onload
|
||||
&& frm.doc.__onload.can_freeze_account);
|
||||
}
|
||||
|
||||
// read-only for root accounts
|
||||
@@ -37,147 +38,125 @@ frappe.ui.form.on("Account", {
|
||||
} else {
|
||||
// credit days and type if customer or supplier
|
||||
frm.set_intro(null);
|
||||
frm.trigger("account_type");
|
||||
frm.trigger('account_type');
|
||||
// show / hide convert buttons
|
||||
frm.trigger("add_toolbar_buttons");
|
||||
frm.trigger('add_toolbar_buttons');
|
||||
}
|
||||
if (frm.has_perm("write")) {
|
||||
frm.add_custom_button(
|
||||
__("Merge Account"),
|
||||
function () {
|
||||
frm.trigger("merge_account");
|
||||
},
|
||||
__("Actions")
|
||||
);
|
||||
frm.add_custom_button(
|
||||
__("Update Account Name / Number"),
|
||||
function () {
|
||||
frm.trigger("update_account_number");
|
||||
},
|
||||
__("Actions")
|
||||
);
|
||||
if (frm.has_perm('write')) {
|
||||
frm.add_custom_button(__('Merge Account'), function () {
|
||||
frm.trigger("merge_account");
|
||||
}, __('Actions'));
|
||||
frm.add_custom_button(__('Update Account Name / Number'), function () {
|
||||
frm.trigger("update_account_number");
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
},
|
||||
account_type: function (frm) {
|
||||
if (frm.doc.is_group == 0) {
|
||||
frm.toggle_display(["tax_rate"], frm.doc.account_type == "Tax");
|
||||
frm.toggle_display("warehouse", frm.doc.account_type == "Stock");
|
||||
frm.toggle_display(['tax_rate'], frm.doc.account_type == 'Tax');
|
||||
frm.toggle_display('warehouse', frm.doc.account_type == 'Stock');
|
||||
}
|
||||
},
|
||||
add_toolbar_buttons: function (frm) {
|
||||
frm.add_custom_button(
|
||||
__("Chart of Accounts"),
|
||||
() => {
|
||||
frappe.set_route("Tree", "Account");
|
||||
},
|
||||
__("View")
|
||||
);
|
||||
add_toolbar_buttons: function(frm) {
|
||||
frm.add_custom_button(__('Chart of Accounts'), () => {
|
||||
frappe.set_route("Tree", "Account");
|
||||
}, __('View'));
|
||||
|
||||
if (frm.doc.is_group == 1) {
|
||||
frm.add_custom_button(
|
||||
__("Convert to Non-Group"),
|
||||
function () {
|
||||
return frappe.call({
|
||||
doc: frm.doc,
|
||||
method: "convert_group_to_ledger",
|
||||
callback: function () {
|
||||
frm.refresh();
|
||||
},
|
||||
});
|
||||
},
|
||||
__("Actions")
|
||||
);
|
||||
} else if (cint(frm.doc.is_group) == 0 && frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
|
||||
frm.add_custom_button(
|
||||
__("General Ledger"),
|
||||
function () {
|
||||
frappe.route_options = {
|
||||
account: frm.doc.name,
|
||||
from_date: 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'));
|
||||
|
||||
frm.add_custom_button(
|
||||
__("Convert to Group"),
|
||||
function () {
|
||||
return frappe.call({
|
||||
doc: frm.doc,
|
||||
method: "convert_ledger_to_group",
|
||||
callback: function () {
|
||||
frm.refresh();
|
||||
},
|
||||
});
|
||||
},
|
||||
__("Actions")
|
||||
);
|
||||
} else if (cint(frm.doc.is_group) == 0
|
||||
&& frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
|
||||
frm.add_custom_button(__('General Ledger'), function () {
|
||||
frappe.route_options = {
|
||||
"account": frm.doc.name,
|
||||
"from_date": 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'), function () {
|
||||
return frappe.call({
|
||||
doc: frm.doc,
|
||||
method: 'convert_ledger_to_group',
|
||||
callback: function() {
|
||||
frm.refresh();
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
},
|
||||
|
||||
merge_account: function (frm) {
|
||||
merge_account: function(frm) {
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __("Merge with Existing Account"),
|
||||
title: __('Merge with Existing Account'),
|
||||
fields: [
|
||||
{
|
||||
label: "Name",
|
||||
fieldname: "name",
|
||||
fieldtype: "Data",
|
||||
reqd: 1,
|
||||
default: frm.doc.name,
|
||||
},
|
||||
"label" : "Name",
|
||||
"fieldname": "name",
|
||||
"fieldtype": "Data",
|
||||
"reqd": 1,
|
||||
"default": frm.doc.name
|
||||
}
|
||||
],
|
||||
primary_action: function () {
|
||||
primary_action: function() {
|
||||
var data = d.get_values();
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.account.account.merge_account",
|
||||
args: {
|
||||
old: frm.doc.name,
|
||||
new: data.name,
|
||||
is_group: frm.doc.is_group,
|
||||
root_type: frm.doc.root_type,
|
||||
company: frm.doc.company
|
||||
},
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
if (r.message) {
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
if(r.message) {
|
||||
frappe.set_route("Form", "Account", r.message);
|
||||
}
|
||||
d.hide();
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
},
|
||||
primary_action_label: __("Merge"),
|
||||
primary_action_label: __('Merge')
|
||||
});
|
||||
d.show();
|
||||
},
|
||||
|
||||
update_account_number: function (frm) {
|
||||
update_account_number: function(frm) {
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __("Update Account Number / Name"),
|
||||
title: __('Update Account Number / Name'),
|
||||
fields: [
|
||||
{
|
||||
label: "Account Name",
|
||||
fieldname: "account_name",
|
||||
fieldtype: "Data",
|
||||
reqd: 1,
|
||||
default: frm.doc.account_name,
|
||||
"label": "Account Name",
|
||||
"fieldname": "account_name",
|
||||
"fieldtype": "Data",
|
||||
"reqd": 1,
|
||||
"default": frm.doc.account_name
|
||||
},
|
||||
{
|
||||
label: "Account Number",
|
||||
fieldname: "account_number",
|
||||
fieldtype: "Data",
|
||||
default: frm.doc.account_number,
|
||||
},
|
||||
"label": "Account Number",
|
||||
"fieldname": "account_number",
|
||||
"fieldtype": "Data",
|
||||
"default": frm.doc.account_number
|
||||
}
|
||||
],
|
||||
primary_action: function () {
|
||||
primary_action: function() {
|
||||
var data = d.get_values();
|
||||
if (
|
||||
data.account_number === frm.doc.account_number &&
|
||||
data.account_name === frm.doc.account_name
|
||||
) {
|
||||
if(data.account_number === frm.doc.account_number && data.account_name === frm.doc.account_name) {
|
||||
d.hide();
|
||||
return;
|
||||
}
|
||||
@@ -187,11 +166,11 @@ frappe.ui.form.on("Account", {
|
||||
args: {
|
||||
account_number: data.account_number,
|
||||
account_name: data.account_name,
|
||||
name: frm.doc.name,
|
||||
name: frm.doc.name
|
||||
},
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
if (r.message) {
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
if(r.message) {
|
||||
frappe.set_route("Form", "Account", r.message);
|
||||
} else {
|
||||
frm.set_value("account_number", data.account_number);
|
||||
@@ -199,11 +178,11 @@ frappe.ui.form.on("Account", {
|
||||
}
|
||||
d.hide();
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
},
|
||||
primary_action_label: __("Update"),
|
||||
primary_action_label: __('Update')
|
||||
});
|
||||
d.show();
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
@@ -108,7 +108,6 @@
|
||||
"fieldname": "parent_account",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"in_preview": 1,
|
||||
"label": "Parent Account",
|
||||
"oldfieldname": "parent_account",
|
||||
"oldfieldtype": "Link",
|
||||
@@ -124,7 +123,7 @@
|
||||
"label": "Account Type",
|
||||
"oldfieldname": "account_type",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nCurrent Asset\nCurrent Liability\nDepreciation\nDirect Expense\nDirect Income\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nIndirect Expense\nIndirect Income\nLiability\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary"
|
||||
"options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary"
|
||||
},
|
||||
{
|
||||
"description": "Rate at which this tax is applied",
|
||||
@@ -193,7 +192,7 @@
|
||||
"idx": 1,
|
||||
"is_tree": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:05:55.866034",
|
||||
"modified": "2023-04-11 16:08:46.983677",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Account",
|
||||
@@ -244,14 +243,14 @@
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 1,
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"search_fields": "account_number",
|
||||
"show_name_in_global_search": 1,
|
||||
"show_preview_popup": 1,
|
||||
"sort_field": "creation",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
|
||||
@@ -18,80 +18,19 @@ class BalanceMismatchError(frappe.ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidAccountMergeError(frappe.ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class Account(NestedSet):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
account_currency: DF.Link | None
|
||||
account_name: DF.Data
|
||||
account_number: DF.Data | None
|
||||
account_type: DF.Literal[
|
||||
"",
|
||||
"Accumulated Depreciation",
|
||||
"Asset Received But Not Billed",
|
||||
"Bank",
|
||||
"Cash",
|
||||
"Chargeable",
|
||||
"Capital Work in Progress",
|
||||
"Cost of Goods Sold",
|
||||
"Current Asset",
|
||||
"Current Liability",
|
||||
"Depreciation",
|
||||
"Direct Expense",
|
||||
"Direct Income",
|
||||
"Equity",
|
||||
"Expense Account",
|
||||
"Expenses Included In Asset Valuation",
|
||||
"Expenses Included In Valuation",
|
||||
"Fixed Asset",
|
||||
"Income Account",
|
||||
"Indirect Expense",
|
||||
"Indirect Income",
|
||||
"Liability",
|
||||
"Payable",
|
||||
"Receivable",
|
||||
"Round Off",
|
||||
"Stock",
|
||||
"Stock Adjustment",
|
||||
"Stock Received But Not Billed",
|
||||
"Service Received But Not Billed",
|
||||
"Tax",
|
||||
"Temporary",
|
||||
]
|
||||
balance_must_be: DF.Literal["", "Debit", "Credit"]
|
||||
company: DF.Link
|
||||
disabled: DF.Check
|
||||
freeze_account: DF.Literal["No", "Yes"]
|
||||
include_in_gross: DF.Check
|
||||
is_group: DF.Check
|
||||
lft: DF.Int
|
||||
old_parent: DF.Data | None
|
||||
parent_account: DF.Link
|
||||
report_type: DF.Literal["", "Balance Sheet", "Profit and Loss"]
|
||||
rgt: DF.Int
|
||||
root_type: DF.Literal["", "Asset", "Liability", "Income", "Expense", "Equity"]
|
||||
tax_rate: DF.Float
|
||||
# end: auto-generated types
|
||||
|
||||
nsm_parent_field = "parent_account"
|
||||
|
||||
def on_update(self):
|
||||
if frappe.local.flags.ignore_update_nsm:
|
||||
return
|
||||
else:
|
||||
super().on_update()
|
||||
super(Account, self).on_update()
|
||||
|
||||
def onload(self):
|
||||
frozen_accounts_modifier = frappe.db.get_single_value("Accounts Settings", "frozen_accounts_modifier")
|
||||
frozen_accounts_modifier = frappe.db.get_value(
|
||||
"Accounts Settings", "Accounts Settings", "frozen_accounts_modifier"
|
||||
)
|
||||
if not frozen_accounts_modifier or frozen_accounts_modifier in frappe.get_roles():
|
||||
self.set_onload("can_freeze_account", True)
|
||||
|
||||
@@ -106,7 +45,6 @@ class Account(NestedSet):
|
||||
if frappe.local.flags.allow_unverified_charts:
|
||||
return
|
||||
self.validate_parent()
|
||||
self.validate_parent_child_account_type()
|
||||
self.validate_root_details()
|
||||
validate_field_number("Account", self.name, self.account_number, self.company, "account_number")
|
||||
self.validate_group_or_ledger()
|
||||
@@ -116,21 +54,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:
|
||||
if self.account_type in [
|
||||
"Direct Income",
|
||||
"Indirect Income",
|
||||
"Current Asset",
|
||||
"Current Liability",
|
||||
"Direct Expense",
|
||||
"Indirect Expense",
|
||||
]:
|
||||
parent_account_type = frappe.db.get_value("Account", self.parent_account, ["account_type"])
|
||||
if parent_account_type == self.account_type:
|
||||
throw(_("Only Parent can be of type {0}").format(self.account_type))
|
||||
|
||||
def validate_parent(self):
|
||||
"""Fetch Parent Details and validate parent account"""
|
||||
@@ -187,24 +110,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()
|
||||
|
||||
@@ -216,7 +121,9 @@ class Account(NestedSet):
|
||||
|
||||
def validate_root_company_and_sync_account_to_children(self):
|
||||
# ignore validation while creating new compnay or while syncing to child companies
|
||||
if frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation:
|
||||
if (
|
||||
frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation
|
||||
):
|
||||
return
|
||||
ancestors = get_root_company(self.company)
|
||||
if ancestors:
|
||||
@@ -414,7 +321,7 @@ class Account(NestedSet):
|
||||
if self.check_gle_exists():
|
||||
throw(_("Account with existing transaction can not be deleted"))
|
||||
|
||||
super().on_trash(True)
|
||||
super(Account, self).on_trash(True)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@@ -422,8 +329,9 @@ class Account(NestedSet):
|
||||
def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql(
|
||||
"""select name from tabAccount
|
||||
where is_group = 1 and docstatus != 2 and company = {}
|
||||
and {} like {} order by name limit {} offset {}""".format("%s", searchfield, "%s", "%s", "%s"),
|
||||
where is_group = 1 and docstatus != 2 and company = %s
|
||||
and %s like %s order by name limit %s offset %s"""
|
||||
% ("%s", searchfield, "%s", "%s", "%s"),
|
||||
(filters["company"], "%%%s%%" % txt, page_len, start),
|
||||
as_list=1,
|
||||
)
|
||||
@@ -537,34 +445,25 @@ def update_account_number(name, account_name, account_number=None, from_descenda
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def merge_account(old, new):
|
||||
def merge_account(old, new, is_group, root_type, company):
|
||||
# Validate properties before merging
|
||||
new_account = frappe.get_cached_doc("Account", new)
|
||||
old_account = frappe.get_cached_doc("Account", old)
|
||||
|
||||
if not new_account:
|
||||
throw(_("Account {0} does not exist").format(new))
|
||||
|
||||
if (
|
||||
cint(new_account.is_group),
|
||||
new_account.root_type,
|
||||
new_account.company,
|
||||
cstr(new_account.account_currency),
|
||||
) != (
|
||||
cint(old_account.is_group),
|
||||
old_account.root_type,
|
||||
old_account.company,
|
||||
cstr(old_account.account_currency),
|
||||
if (new_account.is_group, new_account.root_type, new_account.company) != (
|
||||
cint(is_group),
|
||||
root_type,
|
||||
company,
|
||||
):
|
||||
throw(
|
||||
msg=_(
|
||||
"""Merging is only possible if following properties are same in both records. Is Group, Root Type, Company and Account Currency"""
|
||||
),
|
||||
title=("Invalid Accounts"),
|
||||
exc=InvalidAccountMergeError,
|
||||
_(
|
||||
"""Merging is only possible if following properties are same in both records. Is Group, Root Type, Company"""
|
||||
)
|
||||
)
|
||||
|
||||
if old_account.is_group and new_account.parent_account == old:
|
||||
if is_group and new_account.parent_account == old:
|
||||
new_account.db_set("parent_account", frappe.get_cached_value("Account", old, "parent_account"))
|
||||
|
||||
frappe.rename_doc("Account", old, new, merge=1, force=1)
|
||||
@@ -589,5 +488,7 @@ def sync_update_account_number_in_child(
|
||||
if old_acc_number:
|
||||
filters["account_number"] = old_acc_number
|
||||
|
||||
for d in frappe.db.get_values("Account", filters=filters, fieldname=["company", "name"], as_dict=True):
|
||||
for d in frappe.db.get_values(
|
||||
"Account", filters=filters, fieldname=["company", "name"], as_dict=True
|
||||
):
|
||||
update_account_number(d["name"], account_name, account_number, from_descendant=True)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ def create_charts(
|
||||
"tax_rate",
|
||||
"account_currency",
|
||||
]:
|
||||
|
||||
account_number = cstr(child.get("account_number")).strip()
|
||||
account_name, account_name_in_db = add_suffix_if_duplicate(
|
||||
account_name, account_number, accounts
|
||||
@@ -38,9 +39,7 @@ def create_charts(
|
||||
|
||||
is_group = identify_is_group(child)
|
||||
report_type = (
|
||||
"Balance Sheet"
|
||||
if root_type in ["Asset", "Liability", "Equity"]
|
||||
else "Profit and Loss"
|
||||
"Balance Sheet" if root_type in ["Asset", "Liability", "Equity"] else "Profit and Loss"
|
||||
)
|
||||
|
||||
account = frappe.get_doc(
|
||||
@@ -75,7 +74,7 @@ def create_charts(
|
||||
# after all accounts are already inserted.
|
||||
frappe.local.flags.ignore_update_nsm = True
|
||||
_import_accounts(chart, None, None, root_account=True)
|
||||
rebuild_tree("Account")
|
||||
rebuild_tree("Account", "parent_account")
|
||||
frappe.local.flags.ignore_update_nsm = False
|
||||
|
||||
|
||||
@@ -142,7 +141,7 @@ def get_chart(chart_template, existing_company=None):
|
||||
for fname in os.listdir(path):
|
||||
fname = frappe.as_unicode(fname)
|
||||
if fname.endswith(".json"):
|
||||
with open(os.path.join(path, fname)) as f:
|
||||
with open(os.path.join(path, fname), "r") as f:
|
||||
chart = f.read()
|
||||
if chart and json.loads(chart).get("name") == chart_template:
|
||||
return json.loads(chart).get("tree")
|
||||
@@ -174,7 +173,7 @@ def get_charts_for_country(country, with_standard=False):
|
||||
for fname in os.listdir(path):
|
||||
fname = frappe.as_unicode(fname)
|
||||
if (fname.startswith(country_code) or fname.startswith(country)) and fname.endswith(".json"):
|
||||
with open(os.path.join(path, fname)) as f:
|
||||
with open(os.path.join(path, fname), "r") as f:
|
||||
_get_chart_name(f.read())
|
||||
|
||||
# if more than one charts, returned then add the standard
|
||||
@@ -232,8 +231,6 @@ def build_account_tree(tree, parent, all_accounts):
|
||||
tree[child.account_name]["account_type"] = child.account_type
|
||||
if child.tax_rate:
|
||||
tree[child.account_name]["tax_rate"] = child.tax_rate
|
||||
if child.account_currency:
|
||||
tree[child.account_name]["account_currency"] = child.account_currency
|
||||
if not parent:
|
||||
tree[child.account_name]["root_type"] = child.root_type
|
||||
|
||||
@@ -250,13 +247,7 @@ def validate_bank_account(coa, bank_account):
|
||||
|
||||
def _get_account_names(account_master):
|
||||
for account_name, child in account_master.items():
|
||||
if account_name not in [
|
||||
"account_number",
|
||||
"account_type",
|
||||
"root_type",
|
||||
"is_group",
|
||||
"tax_rate",
|
||||
]:
|
||||
if account_name not in ["account_number", "account_type", "root_type", "is_group", "tax_rate"]:
|
||||
accounts.append(account_name)
|
||||
|
||||
_get_account_names(child)
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
"""
|
||||
Import chart of accounts from OpenERP sources
|
||||
"""
|
||||
|
||||
import ast
|
||||
import json
|
||||
import os
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import frappe
|
||||
from frappe.utils.csvutils import read_csv_content
|
||||
|
||||
path = "/Users/nabinhait/projects/odoo/addons"
|
||||
|
||||
accounts = {}
|
||||
charts = {}
|
||||
all_account_types = []
|
||||
all_roots = {}
|
||||
|
||||
|
||||
def go():
|
||||
global accounts, charts
|
||||
default_account_types = get_default_account_types()
|
||||
|
||||
country_dirs = []
|
||||
for basepath, folders, files in os.walk(path):
|
||||
basename = os.path.basename(basepath)
|
||||
if basename.startswith("l10n_"):
|
||||
country_dirs.append(basename)
|
||||
|
||||
for country_dir in country_dirs:
|
||||
accounts, charts = {}, {}
|
||||
country_path = os.path.join(path, country_dir)
|
||||
manifest = ast.literal_eval(open(os.path.join(country_path, "__openerp__.py")).read())
|
||||
data_files = (
|
||||
manifest.get("data", []) + manifest.get("init_xml", []) + manifest.get("update_xml", [])
|
||||
)
|
||||
files_path = [os.path.join(country_path, d) for d in data_files]
|
||||
xml_roots = get_xml_roots(files_path)
|
||||
csv_content = get_csv_contents(files_path)
|
||||
prefix = country_dir if csv_content else None
|
||||
account_types = get_account_types(
|
||||
xml_roots.get("account.account.type", []), csv_content.get("account.account.type", []), prefix
|
||||
)
|
||||
account_types.update(default_account_types)
|
||||
|
||||
if xml_roots:
|
||||
make_maps_for_xml(xml_roots, account_types, country_dir)
|
||||
|
||||
if csv_content:
|
||||
make_maps_for_csv(csv_content, account_types, country_dir)
|
||||
make_account_trees()
|
||||
make_charts()
|
||||
|
||||
create_all_roots_file()
|
||||
|
||||
|
||||
def get_default_account_types():
|
||||
default_types_root = []
|
||||
default_types_root.append(
|
||||
ET.parse(os.path.join(path, "account", "data", "data_account_type.xml")).getroot()
|
||||
)
|
||||
return get_account_types(default_types_root, None, prefix="account")
|
||||
|
||||
|
||||
def get_xml_roots(files_path):
|
||||
xml_roots = frappe._dict()
|
||||
for filepath in files_path:
|
||||
fname = os.path.basename(filepath)
|
||||
if fname.endswith(".xml"):
|
||||
tree = ET.parse(filepath)
|
||||
root = tree.getroot()
|
||||
for node in root[0].findall("record"):
|
||||
if node.get("model") in [
|
||||
"account.account.template",
|
||||
"account.chart.template",
|
||||
"account.account.type",
|
||||
]:
|
||||
xml_roots.setdefault(node.get("model"), []).append(root)
|
||||
break
|
||||
return xml_roots
|
||||
|
||||
|
||||
def get_csv_contents(files_path):
|
||||
csv_content = {}
|
||||
for filepath in files_path:
|
||||
fname = os.path.basename(filepath)
|
||||
for file_type in ["account.account.template", "account.account.type", "account.chart.template"]:
|
||||
if fname.startswith(file_type) and fname.endswith(".csv"):
|
||||
with open(filepath, "r") as csvfile:
|
||||
try:
|
||||
csv_content.setdefault(file_type, []).append(read_csv_content(csvfile.read()))
|
||||
except Exception as e:
|
||||
continue
|
||||
return csv_content
|
||||
|
||||
|
||||
def get_account_types(root_list, csv_content, prefix=None):
|
||||
types = {}
|
||||
account_type_map = {
|
||||
"cash": "Cash",
|
||||
"bank": "Bank",
|
||||
"tr_cash": "Cash",
|
||||
"tr_bank": "Bank",
|
||||
"receivable": "Receivable",
|
||||
"tr_receivable": "Receivable",
|
||||
"account rec": "Receivable",
|
||||
"payable": "Payable",
|
||||
"tr_payable": "Payable",
|
||||
"equity": "Equity",
|
||||
"stocks": "Stock",
|
||||
"stock": "Stock",
|
||||
"tax": "Tax",
|
||||
"tr_tax": "Tax",
|
||||
"tax-out": "Tax",
|
||||
"tax-in": "Tax",
|
||||
"charges_personnel": "Chargeable",
|
||||
"fixed asset": "Fixed Asset",
|
||||
"cogs": "Cost of Goods Sold",
|
||||
}
|
||||
for root in root_list:
|
||||
for node in root[0].findall("record"):
|
||||
if node.get("model") == "account.account.type":
|
||||
data = {}
|
||||
for field in node.findall("field"):
|
||||
if (
|
||||
field.get("name") == "code"
|
||||
and field.text.lower() != "none"
|
||||
and account_type_map.get(field.text)
|
||||
):
|
||||
data["account_type"] = account_type_map[field.text]
|
||||
|
||||
node_id = prefix + "." + node.get("id") if prefix else node.get("id")
|
||||
types[node_id] = data
|
||||
|
||||
if csv_content and csv_content[0][0] == "id":
|
||||
for row in csv_content[1:]:
|
||||
row_dict = dict(zip(csv_content[0], row))
|
||||
data = {}
|
||||
if row_dict.get("code") and account_type_map.get(row_dict["code"]):
|
||||
data["account_type"] = account_type_map[row_dict["code"]]
|
||||
if data and data.get("id"):
|
||||
node_id = prefix + "." + data.get("id") if prefix else data.get("id")
|
||||
types[node_id] = data
|
||||
return types
|
||||
|
||||
|
||||
def make_maps_for_xml(xml_roots, account_types, country_dir):
|
||||
"""make maps for `charts` and `accounts`"""
|
||||
for model, root_list in xml_roots.items():
|
||||
for root in root_list:
|
||||
for node in root[0].findall("record"):
|
||||
if node.get("model") == "account.account.template":
|
||||
data = {}
|
||||
for field in node.findall("field"):
|
||||
if field.get("name") == "name":
|
||||
data["name"] = field.text
|
||||
if field.get("name") == "parent_id":
|
||||
parent_id = field.get("ref") or field.get("eval")
|
||||
data["parent_id"] = parent_id
|
||||
|
||||
if field.get("name") == "user_type":
|
||||
value = field.get("ref")
|
||||
if account_types.get(value, {}).get("account_type"):
|
||||
data["account_type"] = account_types[value]["account_type"]
|
||||
if data["account_type"] not in all_account_types:
|
||||
all_account_types.append(data["account_type"])
|
||||
|
||||
data["children"] = []
|
||||
accounts[node.get("id")] = data
|
||||
|
||||
if node.get("model") == "account.chart.template":
|
||||
data = {}
|
||||
for field in node.findall("field"):
|
||||
if field.get("name") == "name":
|
||||
data["name"] = field.text
|
||||
if field.get("name") == "account_root_id":
|
||||
data["account_root_id"] = field.get("ref")
|
||||
data["id"] = country_dir
|
||||
charts.setdefault(node.get("id"), {}).update(data)
|
||||
|
||||
|
||||
def make_maps_for_csv(csv_content, account_types, country_dir):
|
||||
for content in csv_content.get("account.account.template", []):
|
||||
for row in content[1:]:
|
||||
data = dict(zip(content[0], row))
|
||||
account = {
|
||||
"name": data.get("name"),
|
||||
"parent_id": data.get("parent_id:id") or data.get("parent_id/id"),
|
||||
"children": [],
|
||||
}
|
||||
user_type = data.get("user_type/id") or data.get("user_type:id")
|
||||
if account_types.get(user_type, {}).get("account_type"):
|
||||
account["account_type"] = account_types[user_type]["account_type"]
|
||||
if account["account_type"] not in all_account_types:
|
||||
all_account_types.append(account["account_type"])
|
||||
|
||||
accounts[data.get("id")] = account
|
||||
if not account.get("parent_id") and data.get("chart_template_id:id"):
|
||||
chart_id = data.get("chart_template_id:id")
|
||||
charts.setdefault(chart_id, {}).update({"account_root_id": data.get("id")})
|
||||
|
||||
for content in csv_content.get("account.chart.template", []):
|
||||
for row in content[1:]:
|
||||
if row:
|
||||
data = dict(zip(content[0], row))
|
||||
charts.setdefault(data.get("id"), {}).update(
|
||||
{
|
||||
"account_root_id": data.get("account_root_id:id") or data.get("account_root_id/id"),
|
||||
"name": data.get("name"),
|
||||
"id": country_dir,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def make_account_trees():
|
||||
"""build tree hierarchy"""
|
||||
for id in accounts.keys():
|
||||
account = accounts[id]
|
||||
|
||||
if account.get("parent_id"):
|
||||
if accounts.get(account["parent_id"]):
|
||||
# accounts[account["parent_id"]]["children"].append(account)
|
||||
accounts[account["parent_id"]][account["name"]] = account
|
||||
del account["parent_id"]
|
||||
del account["name"]
|
||||
|
||||
# remove empty children
|
||||
for id in accounts.keys():
|
||||
if "children" in accounts[id] and not accounts[id].get("children"):
|
||||
del accounts[id]["children"]
|
||||
|
||||
|
||||
def make_charts():
|
||||
"""write chart files in app/setup/doctype/company/charts"""
|
||||
for chart_id in charts:
|
||||
src = charts[chart_id]
|
||||
if not src.get("name") or not src.get("account_root_id"):
|
||||
continue
|
||||
|
||||
if not src["account_root_id"] in accounts:
|
||||
continue
|
||||
|
||||
filename = src["id"][5:] + "_" + chart_id
|
||||
|
||||
print("building " + filename)
|
||||
chart = {}
|
||||
chart["name"] = src["name"]
|
||||
chart["country_code"] = src["id"][5:]
|
||||
chart["tree"] = accounts[src["account_root_id"]]
|
||||
|
||||
for key, val in chart["tree"].items():
|
||||
if key in ["name", "parent_id"]:
|
||||
chart["tree"].pop(key)
|
||||
if type(val) == dict:
|
||||
val["root_type"] = ""
|
||||
if chart:
|
||||
fpath = os.path.join(
|
||||
"erpnext", "erpnext", "accounts", "doctype", "account", "chart_of_accounts", filename + ".json"
|
||||
)
|
||||
|
||||
with open(fpath, "r") as chartfile:
|
||||
old_content = chartfile.read()
|
||||
if not old_content or (
|
||||
json.loads(old_content).get("is_active", "No") == "No"
|
||||
and json.loads(old_content).get("disabled", "No") == "No"
|
||||
):
|
||||
with open(fpath, "w") as chartfile:
|
||||
chartfile.write(json.dumps(chart, indent=4, sort_keys=True))
|
||||
|
||||
all_roots.setdefault(filename, chart["tree"].keys())
|
||||
|
||||
|
||||
def create_all_roots_file():
|
||||
with open("all_roots.txt", "w") as f:
|
||||
for filename, roots in sorted(all_roots.items()):
|
||||
f.write(filename)
|
||||
f.write("\n----------------------\n")
|
||||
for r in sorted(roots):
|
||||
f.write(r.encode("utf-8"))
|
||||
f.write("\n")
|
||||
f.write("\n\n\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
go()
|
||||
@@ -26,7 +26,7 @@
|
||||
"0360 Bauliche Investitionen in fremden (gepachteten) Betriebs- und Geschäftsgebäuden": {"account_type": "Fixed Asset"},
|
||||
"0370 Bauliche Investitionen in fremden (gepachteten) Wohn- und Sozialgebäuden": {"account_type": "Fixed Asset"},
|
||||
"0390 Kumulierte Abschreibungen zu Grundstücken ": {"account_type": "Fixed Asset"},
|
||||
"0400 Maschinen und Geräte ": {"account_type": "Fixed Asset"},
|
||||
"0400 Maschinen und Geräte ": {"account_type": "Fixed Asset"},
|
||||
"0500 Maschinenwerkzeuge ": {"account_type": "Fixed Asset"},
|
||||
"0510 Allgemeine Werkzeuge und Handwerkzeuge ": {"account_type": "Fixed Asset"},
|
||||
"0520 Prototypen, Formen, Modelle ": {"account_type": "Fixed Asset"},
|
||||
@@ -65,41 +65,42 @@
|
||||
"0980 Geleistete Anzahlungen auf Finanzanlagen ": {"account_type": "Fixed Asset"},
|
||||
"0990 Kumulierte Abschreibungen zu Finanzanlagen ": {"account_type": "Fixed Asset"},
|
||||
"root_type": "Asset"
|
||||
},
|
||||
},
|
||||
"Klasse 1 Aktiva: Vorr\u00e4te": {
|
||||
"1000 Bezugsverrechnung": {"account_type": "Stock"},
|
||||
"1100 Rohstoffe": {"account_type": "Stock"},
|
||||
"1200 Bezogene Teile": {"account_type": "Stock"},
|
||||
"1300 Hilfsstoffe": {"account_type": "Stock"},
|
||||
"1350 Betriebsstoffe": {"account_type": "Stock"},
|
||||
"1360 Vorrat Energietraeger": {"account_type": "Stock"},
|
||||
"1360 Vorrat Energietraeger": {"account_type": "Stock"},
|
||||
"1400 Unfertige Erzeugnisse": {"account_type": "Stock"},
|
||||
"1500 Fertige Erzeugnisse": {"account_type": "Stock"},
|
||||
"1600 Handelswarenvorrat": {"account_type": "Stock Received But Not Billed"},
|
||||
"1700 Noch nicht abrechenbare Leistungen": {"account_type": "Stock"},
|
||||
"1900 Wertberichtigungen": {"account_type": "Stock"},
|
||||
"1800 Geleistete Anzahlungen": {"account_type": "Stock"},
|
||||
"1900 Wertberichtigungen": {"account_type": "Stock"},
|
||||
"root_type": "Asset"
|
||||
},
|
||||
},
|
||||
"Klasse 3 Passiva: Verbindlichkeiten": {
|
||||
"3000 Allgemeine Verbindlichkeiten (Schuld)": {"account_type": "Payable"},
|
||||
"3010 R\u00fcckstellungen f\u00fcr Pensionen": {"account_type": "Payable"},
|
||||
"3020 Steuerr\u00fcckstellungen": {"account_type": "Tax"},
|
||||
"3041 Sonstige R\u00fcckstellungen": {"account_type": "Payable"},
|
||||
"3041 Sonstige R\u00fcckstellungen": {"account_type": "Payable"},
|
||||
"3110 Verbindlichkeiten gegen\u00fcber Bank": {"account_type": "Payable"},
|
||||
"3150 Verbindlichkeiten Darlehen": {"account_type": "Payable"},
|
||||
"3185 Verbindlichkeiten Kreditkarte": {"account_type": "Payable"},
|
||||
"3185 Verbindlichkeiten Kreditkarte": {"account_type": "Payable"},
|
||||
"3380 Verbindlichkeiten aus der Annahme gezogener Wechsel u. d. Ausstellungen eigener Wechsel": {
|
||||
"account_type": "Payable"
|
||||
},
|
||||
"3400 Verbindlichkeiten gegen\u00fc. verb. Untern., Verbindl. gegen\u00fc. Untern., mit denen eine Beteiligungsverh\u00e4lnis besteht": {},
|
||||
"3460 Verbindlichkeiten gegenueber Gesellschaftern": {"account_type": "Payable"},
|
||||
"3470 Einlagen stiller Gesellschafter": {"account_type": "Payable"},
|
||||
"3585 Verbindlichkeiten Lohnsteuer": {"account_type": "Tax"},
|
||||
"3590 Verbindlichkeiten Kommunalabgaben": {"account_type": "Tax"},
|
||||
"3595 Verbindlichkeiten Dienstgeberbeitrag": {"account_type": "Tax"},
|
||||
"3585 Verbindlichkeiten Lohnsteuer": {"account_type": "Tax"},
|
||||
"3590 Verbindlichkeiten Kommunalabgaben": {"account_type": "Tax"},
|
||||
"3595 Verbindlichkeiten Dienstgeberbeitrag": {"account_type": "Tax"},
|
||||
"3600 Verbindlichkeiten Sozialversicherung": {"account_type": "Payable"},
|
||||
"3640 Verbindlichkeiten Loehne und Gehaelter": {"account_type": "Payable"},
|
||||
"3640 Verbindlichkeiten Loehne und Gehaelter": {"account_type": "Payable"},
|
||||
"3700 Sonstige Verbindlichkeiten": {"account_type": "Payable"},
|
||||
"3900 Passive Rechnungsabgrenzungsposten": {"account_type": "Payable"},
|
||||
"3100 Anleihen (einschlie\u00dflich konvertibler)": {"account_type": "Payable"},
|
||||
@@ -118,13 +119,13 @@
|
||||
},
|
||||
"3515 Umsatzsteuer Inland 10%": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
},
|
||||
"3520 Umsatzsteuer aus i.g. Erwerb 20%": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"3525 Umsatzsteuer aus i.g. Erwerb 10%": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
},
|
||||
"3560 Umsatzsteuer-Evidenzkonto f\u00fcr erhaltene Anzahlungen auf Bestellungen": {},
|
||||
"3360 Verbindlichkeiten aus Lieferungen u. Leistungen EU": {
|
||||
"account_type": "Payable"
|
||||
@@ -140,7 +141,7 @@
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"root_type": "Liability"
|
||||
},
|
||||
},
|
||||
"Klasse 2 Aktiva: Umlaufverm\u00f6gen, Rechnungsabgrenzungen": {
|
||||
"2030 Forderungen aus Lieferungen und Leistungen Inland (0% USt, umsatzsteuerfrei)": {
|
||||
"account_type": "Receivable"
|
||||
@@ -153,7 +154,7 @@
|
||||
},
|
||||
"2040 Forderungen aus Lieferungen und Leistungen Inland (sonstiger USt-Satz)": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
},
|
||||
"2100 Forderungen aus Lieferungen und Leistungen EU": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
@@ -191,7 +192,7 @@
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2570 Einfuhrumsatzsteuer (bezahlt)": {"account_type": "Tax"},
|
||||
|
||||
|
||||
"2460 Eingeforderte aber noch nicht eingezahlte Einlagen": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
@@ -242,10 +243,10 @@
|
||||
},
|
||||
"2800 Guthaben bei Bank": {
|
||||
"account_type": "Bank"
|
||||
},
|
||||
},
|
||||
"2801 Guthaben bei Bank - Sparkonto": {
|
||||
"account_type": "Bank"
|
||||
},
|
||||
},
|
||||
"2810 Guthaben bei Paypal": {
|
||||
"account_type": "Bank"
|
||||
},
|
||||
@@ -263,19 +264,19 @@
|
||||
},
|
||||
"2895 Schwebende Geldbewegugen": {
|
||||
"account_type": "Bank"
|
||||
},
|
||||
},
|
||||
"2513 Vorsteuer Inland 5%": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"2515 Vorsteuer Inland 20%": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
},
|
||||
"2520 Vorsteuer aus innergemeinschaftlichem Erwerb 10%": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"2525 Vorsteuer aus innergemeinschaftlichem Erwerb 20%": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
},
|
||||
"2530 Vorsteuer \u00a719/Art 19 ( reverse charge ) ": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
@@ -285,16 +286,16 @@
|
||||
"root_type": "Asset"
|
||||
},
|
||||
"Klasse 4: Betriebliche Erträge": {
|
||||
"4000 Erlöse 20 %": {"account_type": "Income Account"},
|
||||
"4020 Erl\u00f6se 0 % steuerbefreit": {"account_type": "Income Account"},
|
||||
"4000 Erlöse 20 %": {"account_type": "Income Account"},
|
||||
"4020 Erl\u00f6se 0 % steuerbefreit": {"account_type": "Income Account"},
|
||||
"4010 Erl\u00f6se 10 %": {"account_type": "Income Account"},
|
||||
"4030 Erl\u00f6se 13 %": {"account_type": "Income Account"},
|
||||
"4040 Erl\u00f6se 0 % innergemeinschaftliche Lieferungen": {"account_type": "Income Account"},
|
||||
"4400 Erl\u00f6sreduktion 0 % steuerbefreit": {"account_type": "Expense Account"},
|
||||
"4030 Erl\u00f6se 13 %": {"account_type": "Income Account"},
|
||||
"4040 Erl\u00f6se 0 % innergemeinschaftliche Lieferungen": {"account_type": "Income Account"},
|
||||
"4400 Erl\u00f6sreduktion 0 % steuerbefreit": {"account_type": "Expense Account"},
|
||||
"4410 Erl\u00f6sreduktion 10 %": {"account_type": "Expense Account"},
|
||||
"4420 Erl\u00f6sreduktion 20 %": {"account_type": "Expense Account"},
|
||||
"4430 Erl\u00f6sreduktion 13 %": {"account_type": "Expense Account"},
|
||||
"4440 Erl\u00f6sreduktion 0 % innergemeinschaftliche Lieferungen": {"account_type": "Expense Account"},
|
||||
"4430 Erl\u00f6sreduktion 13 %": {"account_type": "Expense Account"},
|
||||
"4440 Erl\u00f6sreduktion 0 % innergemeinschaftliche Lieferungen": {"account_type": "Expense Account"},
|
||||
"4500 Ver\u00e4nderungen des Bestandes an fertigen und unfertigen Erzeugn. sowie an noch nicht abrechenbaren Leistungen": {"account_type": "Income Account"},
|
||||
"4580 Aktivierte Eigenleistungen": {"account_type": "Income Account"},
|
||||
"4600 Erl\u00f6se aus dem Abgang vom Anlageverm\u00f6gen, ausgen. Finanzanlagen": {"account_type": "Income Account"},
|
||||
@@ -303,15 +304,15 @@
|
||||
"4700 Ertr\u00e4ge aus der Aufl\u00f6sung von R\u00fcckstellungen": {"account_type": "Income Account"},
|
||||
"4800 \u00dcbrige betriebliche Ertr\u00e4ge": {"account_type": "Income Account"},
|
||||
"root_type": "Income"
|
||||
},
|
||||
},
|
||||
"Klasse 5: Aufwand f\u00fcr Material und Leistungen": {
|
||||
"5000 Einkauf Partnerleistungen": {"account_type": "Cost of Goods Sold"},
|
||||
"5000 Einkauf Partnerleistungen": {"account_type": "Cost of Goods Sold"},
|
||||
"5100 Verbrauch an Rohstoffen": {"account_type": "Cost of Goods Sold"},
|
||||
"5200 Verbrauch von bezogenen Fertig- und Einzelteilen": {"account_type": "Cost of Goods Sold"},
|
||||
"5300 Verbrauch von Hilfsstoffen": {"account_type": "Cost of Goods Sold"},
|
||||
"5340 Verbrauch Verpackungsmaterial": {"account_type": "Cost of Goods Sold"},
|
||||
"5470 Verbrauch von Kleinmaterial": {"account_type": "Cost of Goods Sold"},
|
||||
"5450 Verbrauch von Reinigungsmaterial": {"account_type": "Cost of Goods Sold"},
|
||||
"5450 Verbrauch von Reinigungsmaterial": {"account_type": "Cost of Goods Sold"},
|
||||
"5400 Verbrauch von Betriebsstoffen": {"account_type": "Cost of Goods Sold"},
|
||||
"5500 Verbrauch von Werkzeugen und anderen Erzeugungshilfsmittel": {"account_type": "Cost of Goods Sold"},
|
||||
"5600 Verbrauch von Brenn- und Treibstoffen, Energie und Wasser": {"account_type": "Cost of Goods Sold"},
|
||||
@@ -339,7 +340,7 @@
|
||||
"6700 Sonstige Sozialaufwendungen": {"account_type": "Payable"},
|
||||
"6900 Aufwandsstellenrechnung Personal": {"account_type": "Payable"},
|
||||
"root_type": "Expense"
|
||||
},
|
||||
},
|
||||
"Klasse 7: Abschreibungen und sonstige betriebliche Aufwendungen": {
|
||||
"7010 Abschreibungen auf das Anlageverm\u00f6gen (ausgenommen Finanzanlagen)": {"account_type": "Depreciation"},
|
||||
"7100 Sonstige Steuern und Geb\u00fchren": {"account_type": "Tax"},
|
||||
@@ -348,7 +349,7 @@
|
||||
"7310 Fahrrad - Aufwand": {"account_type": "Expense Account"},
|
||||
"7320 Kfz - Aufwand": {"account_type": "Expense Account"},
|
||||
"7330 LKW - Aufwand": {"account_type": "Expense Account"},
|
||||
"7340 Lastenrad - Aufwand": {"account_type": "Expense Account"},
|
||||
"7340 Lastenrad - Aufwand": {"account_type": "Expense Account"},
|
||||
"7350 Reise- und Fahraufwand": {"account_type": "Expense Account"},
|
||||
"7360 Tag- und N\u00e4chtigungsgelder": {"account_type": "Expense Account"},
|
||||
"7380 Nachrichtenaufwand": {"account_type": "Expense Account"},
|
||||
@@ -408,7 +409,7 @@
|
||||
"8990 Gewinnabfuhr bzw. Verlust\u00fcberrechnung aus Ergebnisabf\u00fchrungsvertr\u00e4gen": {"account_type": "Expense Account"},
|
||||
"8350 nicht ausgenutzte Lieferantenskonti": {"account_type": "Expense Account"},
|
||||
"root_type": "Income"
|
||||
},
|
||||
},
|
||||
"Klasse 9 Passiva: Eigenkapital, R\u00fccklagen, stille Einlagen, Abschlusskonten": {
|
||||
"9000 Gezeichnetes bzw. gewidmetes Kapital": {
|
||||
"account_type": "Equity"
|
||||
@@ -434,5 +435,5 @@
|
||||
},
|
||||
"root_type": "Equity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,20 +437,12 @@
|
||||
},
|
||||
"Sales": {
|
||||
"Sales from Other Regions": {
|
||||
"Sales from Other Region": {
|
||||
"account_type": "Income Account"
|
||||
}
|
||||
"Sales from Other Region": {}
|
||||
},
|
||||
"Sales of same region": {
|
||||
"Management Consultancy Fees 1": {
|
||||
"account_type": "Income Account"
|
||||
},
|
||||
"Sales Account": {
|
||||
"account_type": "Income Account"
|
||||
},
|
||||
"Sales of I/C": {
|
||||
"account_type": "Income Account"
|
||||
}
|
||||
"Management Consultancy Fees 1": {},
|
||||
"Sales Account": {},
|
||||
"Sales of I/C": {}
|
||||
}
|
||||
},
|
||||
"root_type": "Income"
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -33,9 +33,7 @@
|
||||
},
|
||||
"Stocks": {
|
||||
"Mati\u00e8res premi\u00e8res": {},
|
||||
"Stock de produits fini": {
|
||||
"account_type": "Stock"
|
||||
},
|
||||
"Stock de produits fini": {},
|
||||
"Stock exp\u00e9di\u00e9 non-factur\u00e9": {},
|
||||
"Travaux en cours": {},
|
||||
"account_type": "Stock"
|
||||
@@ -397,11 +395,9 @@
|
||||
},
|
||||
"Produits": {
|
||||
"Revenus de ventes": {
|
||||
"Escomptes de volume sur ventes": {},
|
||||
" Escomptes de volume sur ventes": {},
|
||||
"Autres produits d'exploitation": {},
|
||||
"Ventes": {
|
||||
"account_type": "Income Account"
|
||||
},
|
||||
"Ventes": {},
|
||||
"Ventes avec des provinces harmonis\u00e9es": {},
|
||||
"Ventes avec des provinces non-harmonis\u00e9es": {},
|
||||
"Ventes \u00e0 l'\u00e9tranger": {}
|
||||
|
||||
@@ -53,13 +53,8 @@
|
||||
},
|
||||
"II. Forderungen und sonstige Vermögensgegenstände": {
|
||||
"is_group": 1,
|
||||
"Forderungen aus Lieferungen und Leistungen mit Kontokorrent": {
|
||||
"Ford. a. Lieferungen und Leistungen": {
|
||||
"account_number": "1400",
|
||||
"account_type": "Receivable",
|
||||
"is_group": 1
|
||||
},
|
||||
"Forderungen aus Lieferungen und Leistungen ohne Kontokorrent": {
|
||||
"account_number": "1410",
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"Durchlaufende Posten": {
|
||||
@@ -185,13 +180,8 @@
|
||||
},
|
||||
"IV. Verbindlichkeiten aus Lieferungen und Leistungen": {
|
||||
"is_group": 1,
|
||||
"Verbindlichkeiten aus Lieferungen und Leistungen mit Kontokorrent": {
|
||||
"Verbindlichkeiten aus Lieferungen u. Leistungen": {
|
||||
"account_number": "1600",
|
||||
"account_type": "Payable",
|
||||
"is_group": 1
|
||||
},
|
||||
"Verbindlichkeiten aus Lieferungen und Leistungen ohne Kontokorrent": {
|
||||
"account_number": "1610",
|
||||
"account_type": "Payable"
|
||||
}
|
||||
},
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,4 @@
|
||||
{
|
||||
"country_code": "hu",
|
||||
"name": "Hungary - Chart of Accounts for Microenterprises",
|
||||
"tree": {
|
||||
"SZ\u00c1MLAOSZT\u00c1LY BEFEKTETETT ESZK\u00d6Z\u00d6K": {
|
||||
"account_number": 1,
|
||||
@@ -1653,4 +1651,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,8 @@
|
||||
"Persediaan Barang": {
|
||||
"Persediaan Barang": {
|
||||
"account_number": "1141.000",
|
||||
"account_type": "Stock"
|
||||
"account_type": "Stock",
|
||||
"is_group": 1
|
||||
},
|
||||
"Uang Muka Pembelian": {
|
||||
"Uang Muka Pembelian": {
|
||||
@@ -669,8 +670,7 @@
|
||||
},
|
||||
"Penjualan Barang Dagangan": {
|
||||
"Penjualan": {
|
||||
"account_number": "4110.000",
|
||||
"account_type": "Income Account"
|
||||
"account_number": "4110.000"
|
||||
},
|
||||
"Potongan Penjualan": {
|
||||
"account_number": "4130.000"
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -109,7 +109,8 @@
|
||||
}
|
||||
},
|
||||
"INVENTARIOS": {
|
||||
"account_type": "Stock"
|
||||
"account_type": "Stock",
|
||||
"is_group": 1
|
||||
}
|
||||
},
|
||||
"ACTIVO LARGO PLAZO": {
|
||||
@@ -397,18 +398,10 @@
|
||||
"INGRESOS POR SERVICIOS 1": {}
|
||||
},
|
||||
"VENTAS": {
|
||||
"VENTAS EXPORTACION": {
|
||||
"account_type": "Income Account"
|
||||
},
|
||||
"VENTAS INMUEBLES": {
|
||||
"account_type": "Income Account"
|
||||
},
|
||||
"VENTAS NACIONALES": {
|
||||
"account_type": "Income Account"
|
||||
},
|
||||
"VENTAS NACIONALES AL DETAL": {
|
||||
"account_type": "Income Account"
|
||||
}
|
||||
"VENTAS EXPORTACION": {},
|
||||
"VENTAS INMUEBLES": {},
|
||||
"VENTAS NACIONALES": {},
|
||||
"VENTAS NACIONALES AL DETAL": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"country_code": "ni",
|
||||
"name": "Nicaragua - Catálogo de Cuentas",
|
||||
"name": "Nicaragua - Catalogo de Cuentas",
|
||||
"tree": {
|
||||
"Activo": {
|
||||
"Activo Corriente": {
|
||||
@@ -491,4 +491,4 @@
|
||||
"root_type": "Liability"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -6,13 +6,8 @@ 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,
|
||||
merge_account,
|
||||
update_account_number,
|
||||
)
|
||||
from erpnext.accounts.doctype.account.account import merge_account, update_account_number
|
||||
from erpnext.stock import get_company_default_inventory_account, get_warehouse_account
|
||||
|
||||
test_dependencies = ["Company"]
|
||||
@@ -52,53 +47,49 @@ class TestAccount(unittest.TestCase):
|
||||
frappe.delete_doc("Account", "1211-11-4 - 6 - Debtors 1 - Test - - _TC")
|
||||
|
||||
def test_merge_account(self):
|
||||
create_account(
|
||||
account_name="Current Assets",
|
||||
is_group=1,
|
||||
parent_account="Application of Funds (Assets) - _TC",
|
||||
company="_Test Company",
|
||||
)
|
||||
|
||||
create_account(
|
||||
account_name="Securities and Deposits",
|
||||
is_group=1,
|
||||
parent_account="Current Assets - _TC",
|
||||
company="_Test Company",
|
||||
)
|
||||
|
||||
create_account(
|
||||
account_name="Earnest Money",
|
||||
parent_account="Securities and Deposits - _TC",
|
||||
company="_Test Company",
|
||||
)
|
||||
|
||||
create_account(
|
||||
account_name="Cash In Hand",
|
||||
is_group=1,
|
||||
parent_account="Current Assets - _TC",
|
||||
company="_Test Company",
|
||||
)
|
||||
|
||||
create_account(
|
||||
account_name="Receivable INR",
|
||||
parent_account="Current Assets - _TC",
|
||||
company="_Test Company",
|
||||
account_currency="INR",
|
||||
)
|
||||
|
||||
create_account(
|
||||
account_name="Receivable USD",
|
||||
parent_account="Current Assets - _TC",
|
||||
company="_Test Company",
|
||||
account_currency="USD",
|
||||
)
|
||||
if not frappe.db.exists("Account", "Current Assets - _TC"):
|
||||
acc = frappe.new_doc("Account")
|
||||
acc.account_name = "Current Assets"
|
||||
acc.is_group = 1
|
||||
acc.parent_account = "Application of Funds (Assets) - _TC"
|
||||
acc.company = "_Test Company"
|
||||
acc.insert()
|
||||
if not frappe.db.exists("Account", "Securities and Deposits - _TC"):
|
||||
acc = frappe.new_doc("Account")
|
||||
acc.account_name = "Securities and Deposits"
|
||||
acc.parent_account = "Current Assets - _TC"
|
||||
acc.is_group = 1
|
||||
acc.company = "_Test Company"
|
||||
acc.insert()
|
||||
if not frappe.db.exists("Account", "Earnest Money - _TC"):
|
||||
acc = frappe.new_doc("Account")
|
||||
acc.account_name = "Earnest Money"
|
||||
acc.parent_account = "Securities and Deposits - _TC"
|
||||
acc.company = "_Test Company"
|
||||
acc.insert()
|
||||
if not frappe.db.exists("Account", "Cash In Hand - _TC"):
|
||||
acc = frappe.new_doc("Account")
|
||||
acc.account_name = "Cash In Hand"
|
||||
acc.is_group = 1
|
||||
acc.parent_account = "Current Assets - _TC"
|
||||
acc.company = "_Test Company"
|
||||
acc.insert()
|
||||
if not frappe.db.exists("Account", "Accumulated Depreciation - _TC"):
|
||||
acc = frappe.new_doc("Account")
|
||||
acc.account_name = "Accumulated Depreciation"
|
||||
acc.parent_account = "Fixed Assets - _TC"
|
||||
acc.company = "_Test Company"
|
||||
acc.account_type = "Accumulated Depreciation"
|
||||
acc.insert()
|
||||
|
||||
doc = frappe.get_doc("Account", "Securities and Deposits - _TC")
|
||||
parent = frappe.db.get_value("Account", "Earnest Money - _TC", "parent_account")
|
||||
|
||||
self.assertEqual(parent, "Securities and Deposits - _TC")
|
||||
|
||||
merge_account("Securities and Deposits - _TC", "Cash In Hand - _TC")
|
||||
|
||||
merge_account(
|
||||
"Securities and Deposits - _TC", "Cash In Hand - _TC", doc.is_group, doc.root_type, doc.company
|
||||
)
|
||||
parent = frappe.db.get_value("Account", "Earnest Money - _TC", "parent_account")
|
||||
|
||||
# Parent account of the child account changes after merging
|
||||
@@ -107,28 +98,30 @@ class TestAccount(unittest.TestCase):
|
||||
# Old account doesn't exist after merging
|
||||
self.assertFalse(frappe.db.exists("Account", "Securities and Deposits - _TC"))
|
||||
|
||||
doc = frappe.get_doc("Account", "Current Assets - _TC")
|
||||
|
||||
# Raise error as is_group property doesn't match
|
||||
self.assertRaises(
|
||||
InvalidAccountMergeError,
|
||||
frappe.ValidationError,
|
||||
merge_account,
|
||||
"Current Assets - _TC",
|
||||
"Accumulated Depreciation - _TC",
|
||||
doc.is_group,
|
||||
doc.root_type,
|
||||
doc.company,
|
||||
)
|
||||
|
||||
doc = frappe.get_doc("Account", "Capital Stock - _TC")
|
||||
|
||||
# Raise error as root_type property doesn't match
|
||||
self.assertRaises(
|
||||
InvalidAccountMergeError,
|
||||
frappe.ValidationError,
|
||||
merge_account,
|
||||
"Capital Stock - _TC",
|
||||
"Software - _TC",
|
||||
)
|
||||
|
||||
# Raise error as currency doesn't match
|
||||
self.assertRaises(
|
||||
InvalidAccountMergeError,
|
||||
merge_account,
|
||||
"Receivable INR - _TC",
|
||||
"Receivable USD - _TC",
|
||||
"Softwares - _TC",
|
||||
doc.is_group,
|
||||
doc.root_type,
|
||||
doc.company,
|
||||
)
|
||||
|
||||
def test_account_sync(self):
|
||||
@@ -261,20 +254,28 @@ class TestAccount(unittest.TestCase):
|
||||
acc.insert()
|
||||
|
||||
self.assertTrue(
|
||||
frappe.db.exists("Account", {"account_name": "Test Group Account", "company": "_Test Company 4"})
|
||||
frappe.db.exists(
|
||||
"Account", {"account_name": "Test Group Account", "company": "_Test Company 4"}
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
frappe.db.exists("Account", {"account_name": "Test Group Account", "company": "_Test Company 5"})
|
||||
frappe.db.exists(
|
||||
"Account", {"account_name": "Test Group Account", "company": "_Test Company 5"}
|
||||
)
|
||||
)
|
||||
|
||||
# Try renaming child company account
|
||||
acc_tc_5 = frappe.db.get_value(
|
||||
"Account", {"account_name": "Test Group Account", "company": "_Test Company 5"}
|
||||
)
|
||||
self.assertRaises(frappe.ValidationError, update_account_number, acc_tc_5, "Test Modified Account")
|
||||
self.assertRaises(
|
||||
frappe.ValidationError, update_account_number, acc_tc_5, "Test Modified Account"
|
||||
)
|
||||
|
||||
# Rename child company account with allow_account_creation_against_child_company enabled
|
||||
frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 1)
|
||||
frappe.db.set_value(
|
||||
"Company", "_Test Company 5", "allow_account_creation_against_child_company", 1
|
||||
)
|
||||
|
||||
update_account_number(acc_tc_5, "Test Modified Account")
|
||||
self.assertTrue(
|
||||
@@ -283,7 +284,9 @@ class TestAccount(unittest.TestCase):
|
||||
)
|
||||
)
|
||||
|
||||
frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 0)
|
||||
frappe.db.set_value(
|
||||
"Company", "_Test Company 5", "allow_account_creation_against_child_company", 0
|
||||
)
|
||||
|
||||
to_delete = [
|
||||
"Test Group Account - _TC3",
|
||||
@@ -308,24 +311,13 @@ class TestAccount(unittest.TestCase):
|
||||
self.assertEqual(acc.account_currency, "INR")
|
||||
|
||||
# Make a JV against this account
|
||||
make_journal_entry("Test Currency Account - _TC", "Miscellaneous Expenses - _TC", 100, submit=True)
|
||||
make_journal_entry(
|
||||
"Test Currency Account - _TC", "Miscellaneous Expenses - _TC", 100, submit=True
|
||||
)
|
||||
|
||||
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
|
||||
@@ -408,20 +400,11 @@ def create_account(**kwargs):
|
||||
"Account", filters={"account_name": kwargs.get("account_name"), "company": kwargs.get("company")}
|
||||
)
|
||||
if account:
|
||||
account = frappe.get_doc("Account", account)
|
||||
account.update(
|
||||
dict(
|
||||
is_group=kwargs.get("is_group", 0),
|
||||
parent_account=kwargs.get("parent_account"),
|
||||
)
|
||||
)
|
||||
account.save()
|
||||
return account.name
|
||||
return account
|
||||
else:
|
||||
account = frappe.get_doc(
|
||||
dict(
|
||||
doctype="Account",
|
||||
is_group=kwargs.get("is_group", 0),
|
||||
account_name=kwargs.get("account_name"),
|
||||
account_type=kwargs.get("account_type"),
|
||||
parent_account=kwargs.get("parent_account"),
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
"icon": "fa fa-list",
|
||||
"in_create": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:05:56.710541",
|
||||
"modified": "2023-03-06 08:56:36.393237",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Account Closing Balance",
|
||||
@@ -158,7 +158,7 @@
|
||||
"role": "Auditor"
|
||||
}
|
||||
],
|
||||
"sort_field": "creation",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
@@ -11,41 +11,22 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||
|
||||
|
||||
class AccountClosingBalance(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
account: DF.Link | None
|
||||
account_currency: DF.Link | None
|
||||
closing_date: DF.Date | None
|
||||
company: DF.Link | None
|
||||
cost_center: DF.Link | None
|
||||
credit: DF.Currency
|
||||
credit_in_account_currency: DF.Currency
|
||||
debit: DF.Currency
|
||||
debit_in_account_currency: DF.Currency
|
||||
finance_book: DF.Link | None
|
||||
is_period_closing_voucher_entry: DF.Check
|
||||
period_closing_voucher: DF.Link | None
|
||||
project: DF.Link | None
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def make_closing_entries(closing_entries, voucher_name, company, closing_date):
|
||||
accounting_dimensions = get_accounting_dimensions()
|
||||
|
||||
previous_closing_entries = get_previous_closing_entries(company, closing_date, accounting_dimensions)
|
||||
previous_closing_entries = get_previous_closing_entries(
|
||||
company, closing_date, accounting_dimensions
|
||||
)
|
||||
combined_entries = closing_entries + previous_closing_entries
|
||||
|
||||
merged_entries = aggregate_with_last_account_closing_balance(combined_entries, accounting_dimensions)
|
||||
merged_entries = aggregate_with_last_account_closing_balance(
|
||||
combined_entries, accounting_dimensions
|
||||
)
|
||||
|
||||
for _key, value in merged_entries.items():
|
||||
for key, value in merged_entries.items():
|
||||
cle = frappe.new_doc("Account Closing Balance")
|
||||
cle.update(value)
|
||||
cle.update(value["dimensions"])
|
||||
@@ -56,7 +37,6 @@ def make_closing_entries(closing_entries, voucher_name, company, closing_date):
|
||||
}
|
||||
)
|
||||
cle.flags.ignore_permissions = True
|
||||
cle.flags.ignore_links = True
|
||||
cle.submit()
|
||||
|
||||
|
||||
|
||||
@@ -1,89 +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'});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
label: function (frm) {
|
||||
frm.set_value("fieldname", frappe.model.scrub(frm.doc.label));
|
||||
},
|
||||
document_type: function(frm) {
|
||||
|
||||
document_type: function (frm) {
|
||||
frm.set_value("label", frm.doc.document_type);
|
||||
frm.set_value('label', frm.doc.document_type);
|
||||
frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type));
|
||||
|
||||
frappe.db.get_value(
|
||||
"Accounting Dimension",
|
||||
{ document_type: frm.doc.document_type },
|
||||
"document_type",
|
||||
(r) => {
|
||||
if (r && r.document_type) {
|
||||
frm.set_df_property(
|
||||
"document_type",
|
||||
"description",
|
||||
"Document type is already set as dimension"
|
||||
);
|
||||
}
|
||||
frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => {
|
||||
if (r && r.document_type) {
|
||||
frm.set_df_property('document_type', 'description', "Document type is already set as dimension");
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Accounting Dimension Detail", {
|
||||
dimension_defaults_add: function (frm, cdt, cdn) {
|
||||
frappe.ui.form.on('Accounting Dimension Detail', {
|
||||
dimension_defaults_add: function(frm, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
row.reference_document = frm.doc.document_type;
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:05:56.890002",
|
||||
"modified": "2021-02-08 16:37:53.936656",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounting Dimension",
|
||||
@@ -80,8 +80,7 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"sort_field": "creation",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -11,37 +11,13 @@ 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
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
from erpnext.accounts.doctype.accounting_dimension_detail.accounting_dimension_detail import (
|
||||
AccountingDimensionDetail,
|
||||
)
|
||||
|
||||
dimension_defaults: DF.Table[AccountingDimensionDetail]
|
||||
disabled: DF.Check
|
||||
document_type: DF.Link
|
||||
fieldname: DF.Data | None
|
||||
label: DF.Data | None
|
||||
# end: auto-generated types
|
||||
|
||||
def before_insert(self):
|
||||
self.set_fieldname_and_label()
|
||||
|
||||
def validate(self):
|
||||
if self.document_type in (
|
||||
*core_doctypes_list,
|
||||
if self.document_type in core_doctypes_list + (
|
||||
"Accounting Dimension",
|
||||
"Project",
|
||||
"Cost Center",
|
||||
@@ -49,10 +25,13 @@ class AccountingDimension(Document):
|
||||
"Company",
|
||||
"Account",
|
||||
):
|
||||
|
||||
msg = _("Not allowed to create accounting dimension for {0}").format(self.document_type)
|
||||
frappe.throw(msg)
|
||||
|
||||
exists = frappe.db.get_value("Accounting Dimension", {"document_type": self.document_type}, ["name"])
|
||||
exists = frappe.db.get_value(
|
||||
"Accounting Dimension", {"document_type": self.document_type}, ["name"]
|
||||
)
|
||||
|
||||
if exists and self.is_new():
|
||||
frappe.throw(_("Document Type already used as a dimension"))
|
||||
@@ -108,9 +87,9 @@ 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:
|
||||
|
||||
if (doc_count + 1) % 2 == 0:
|
||||
insert_after_field = "dimension_col_break"
|
||||
else:
|
||||
@@ -123,7 +102,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)
|
||||
@@ -145,7 +123,7 @@ def add_dimension_to_budget_doctype(df, doc):
|
||||
df.update(
|
||||
{
|
||||
"insert_after": "cost_center",
|
||||
"depends_on": f"eval:doc.budget_against == '{doc.document_type}'",
|
||||
"depends_on": "eval:doc.budget_against == '{0}'".format(doc.document_type),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -179,17 +157,19 @@ def delete_accounting_dimension(doc):
|
||||
frappe.db.sql(
|
||||
"""
|
||||
DELETE FROM `tabCustom Field`
|
||||
WHERE fieldname = {}
|
||||
AND dt IN ({})""".format("%s", ", ".join(["%s"] * len(doclist))), # nosec
|
||||
tuple([doc.fieldname, *doclist]),
|
||||
WHERE fieldname = %s
|
||||
AND dt IN (%s)"""
|
||||
% ("%s", ", ".join(["%s"] * len(doclist))), # nosec
|
||||
tuple([doc.fieldname] + doclist),
|
||||
)
|
||||
|
||||
frappe.db.sql(
|
||||
"""
|
||||
DELETE FROM `tabProperty Setter`
|
||||
WHERE field_name = {}
|
||||
AND doc_type IN ({})""".format("%s", ", ".join(["%s"] * len(doclist))), # nosec
|
||||
tuple([doc.fieldname, *doclist]),
|
||||
WHERE field_name = %s
|
||||
AND doc_type IN (%s)"""
|
||||
% ("%s", ", ".join(["%s"] * len(doclist))), # nosec
|
||||
tuple([doc.fieldname] + doclist),
|
||||
)
|
||||
|
||||
budget_against_property = frappe.get_doc("Property Setter", "Budget-budget_against-options")
|
||||
@@ -238,6 +218,7 @@ def get_doctypes_with_dimensions():
|
||||
|
||||
|
||||
def get_accounting_dimensions(as_list=True, filters=None):
|
||||
|
||||
if not filters:
|
||||
filters = {"disabled": 0}
|
||||
|
||||
@@ -255,19 +236,18 @@ def get_accounting_dimensions(as_list=True, filters=None):
|
||||
|
||||
|
||||
def get_checks_for_pl_and_bs_accounts():
|
||||
if frappe.flags.accounting_dimensions_details is None:
|
||||
# nosemgrep
|
||||
frappe.flags.accounting_dimensions_details = frappe.db.sql(
|
||||
"""SELECT p.label, p.disabled, p.fieldname, c.default_dimension, c.company, c.mandatory_for_pl, c.mandatory_for_bs
|
||||
FROM `tabAccounting Dimension`p ,`tabAccounting Dimension Detail` c
|
||||
WHERE p.name = c.parent""",
|
||||
as_dict=1,
|
||||
)
|
||||
dimensions = frappe.db.sql(
|
||||
"""SELECT p.label, p.disabled, p.fieldname, c.default_dimension, c.company, c.mandatory_for_pl, c.mandatory_for_bs
|
||||
FROM `tabAccounting Dimension`p ,`tabAccounting Dimension Detail` c
|
||||
WHERE p.name = c.parent""",
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
return frappe.flags.accounting_dimensions_details
|
||||
return dimensions
|
||||
|
||||
|
||||
def get_dimension_with_children(doctype, dimensions):
|
||||
|
||||
if isinstance(dimensions, str):
|
||||
dimensions = [dimensions]
|
||||
|
||||
@@ -275,7 +255,9 @@ def get_dimension_with_children(doctype, dimensions):
|
||||
|
||||
for dimension in dimensions:
|
||||
lft, rgt = frappe.db.get_value(doctype, dimension, ["lft", "rgt"])
|
||||
children = frappe.get_all(doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, order_by="lft")
|
||||
children = frappe.get_all(
|
||||
doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, order_by="lft"
|
||||
)
|
||||
all_dimensions += [c.name for c in children]
|
||||
|
||||
return all_dimensions
|
||||
@@ -283,17 +265,20 @@ def get_dimension_with_children(doctype, dimensions):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_dimensions(with_cost_center_and_project=False):
|
||||
c = frappe.qb.DocType("Accounting Dimension Detail")
|
||||
p = frappe.qb.DocType("Accounting Dimension")
|
||||
dimension_filters = (
|
||||
frappe.qb.from_(p).select(p.label, p.fieldname, p.document_type).where(p.disabled == 0).run(as_dict=1)
|
||||
dimension_filters = frappe.db.sql(
|
||||
"""
|
||||
SELECT label, fieldname, document_type
|
||||
FROM `tabAccounting Dimension`
|
||||
WHERE disabled = 0
|
||||
""",
|
||||
as_dict=1,
|
||||
)
|
||||
default_dimensions = (
|
||||
frappe.qb.from_(c)
|
||||
.inner_join(p)
|
||||
.on(c.parent == p.name)
|
||||
.select(p.fieldname, c.company, c.default_dimension)
|
||||
.run(as_dict=1)
|
||||
|
||||
default_dimensions = frappe.db.sql(
|
||||
"""SELECT p.fieldname, c.company, c.default_dimension
|
||||
FROM `tabAccounting Dimension Detail` c, `tabAccounting Dimension` p
|
||||
WHERE c.parent = p.name""",
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
if isinstance(with_cost_center_and_project, str):
|
||||
@@ -316,30 +301,3 @@ def get_dimensions(with_cost_center_and_project=False):
|
||||
default_dimensions_map[dimension.company][dimension.fieldname] = dimension.default_dimension
|
||||
|
||||
return dimension_filters, default_dimensions_map
|
||||
|
||||
|
||||
def create_accounting_dimensions_for_doctype(doctype):
|
||||
accounting_dimensions = frappe.db.get_all(
|
||||
"Accounting Dimension", fields=["fieldname", "label", "document_type", "disabled"]
|
||||
)
|
||||
|
||||
if not accounting_dimensions:
|
||||
return
|
||||
|
||||
for d in accounting_dimensions:
|
||||
field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname})
|
||||
|
||||
if field:
|
||||
continue
|
||||
|
||||
df = {
|
||||
"fieldname": d.fieldname,
|
||||
"label": d.label,
|
||||
"fieldtype": "Link",
|
||||
"options": d.document_type,
|
||||
"insert_after": "accounting_dimensions_section",
|
||||
}
|
||||
|
||||
create_custom_field(doctype, df, ignore_validate=True)
|
||||
|
||||
frappe.clear_cache(doctype=doctype)
|
||||
|
||||
@@ -78,30 +78,18 @@ class TestAccountingDimension(unittest.TestCase):
|
||||
|
||||
def tearDown(self):
|
||||
disable_dimension()
|
||||
frappe.flags.accounting_dimensions_details = None
|
||||
frappe.flags.dimension_filter_map = None
|
||||
|
||||
|
||||
def create_dimension():
|
||||
frappe.set_user("Administrator")
|
||||
|
||||
if not frappe.db.exists("Accounting Dimension", {"document_type": "Department"}):
|
||||
dimension = frappe.get_doc(
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Accounting Dimension",
|
||||
"document_type": "Department",
|
||||
}
|
||||
)
|
||||
dimension.append(
|
||||
"dimension_defaults",
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"reference_document": "Department",
|
||||
"default_dimension": "_Test Department - _TC",
|
||||
},
|
||||
)
|
||||
dimension.insert()
|
||||
dimension.save()
|
||||
).insert()
|
||||
else:
|
||||
dimension = frappe.get_doc("Accounting Dimension", "Department")
|
||||
dimension.disabled = 0
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2019-07-16 17:53:18.718831",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
@@ -74,15 +73,13 @@
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:05:57.056874",
|
||||
"modified": "2019-08-15 11:59:09.389891",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounting Dimension Detail",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "creation",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -7,24 +7,4 @@ from frappe.model.document import Document
|
||||
|
||||
|
||||
class AccountingDimensionDetail(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
automatically_post_balancing_accounting_entry: DF.Check
|
||||
company: DF.Link | None
|
||||
default_dimension: DF.DynamicLink | None
|
||||
mandatory_for_bs: DF.Check
|
||||
mandatory_for_pl: DF.Check
|
||||
offsetting_account: DF.Link | None
|
||||
parent: DF.Data
|
||||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
reference_document: DF.Link | None
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
@@ -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");
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:05:57.199186",
|
||||
"modified": "2023-06-07 14:59:41.869117",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounting Dimension Filter",
|
||||
@@ -139,7 +139,7 @@
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "creation",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
|
||||
@@ -8,28 +8,6 @@ from frappe.model.document import Document
|
||||
|
||||
|
||||
class AccountingDimensionFilter(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
from erpnext.accounts.doctype.allowed_dimension.allowed_dimension import AllowedDimension
|
||||
from erpnext.accounts.doctype.applicable_on_account.applicable_on_account import (
|
||||
ApplicableOnAccount,
|
||||
)
|
||||
|
||||
accounting_dimension: DF.Literal
|
||||
accounts: DF.Table[ApplicableOnAccount]
|
||||
allow_or_restrict: DF.Literal["Allow", "Restrict"]
|
||||
apply_restriction_on_values: DF.Check
|
||||
company: DF.Link
|
||||
dimensions: DF.Table[AllowedDimension]
|
||||
disabled: DF.Check
|
||||
# end: auto-generated types
|
||||
|
||||
def before_save(self):
|
||||
# If restriction is not applied on values, then remove all the dimensions and set allow_or_restrict to Restrict
|
||||
if not self.apply_restriction_on_values:
|
||||
@@ -66,39 +44,37 @@ class AccountingDimensionFilter(Document):
|
||||
|
||||
|
||||
def get_dimension_filter_map():
|
||||
if not frappe.flags.get("dimension_filter_map"):
|
||||
filters = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
a.applicable_on_account, d.dimension_value, p.accounting_dimension,
|
||||
p.allow_or_restrict, a.is_mandatory
|
||||
FROM
|
||||
`tabApplicable On Account` a,
|
||||
`tabAccounting Dimension Filter` p
|
||||
LEFT JOIN `tabAllowed Dimension` d ON d.parent = p.name
|
||||
WHERE
|
||||
p.name = a.parent
|
||||
AND p.disabled = 0
|
||||
""",
|
||||
as_dict=1,
|
||||
filters = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
a.applicable_on_account, d.dimension_value, p.accounting_dimension,
|
||||
p.allow_or_restrict, a.is_mandatory
|
||||
FROM
|
||||
`tabApplicable On Account` a,
|
||||
`tabAccounting Dimension Filter` p
|
||||
LEFT JOIN `tabAllowed Dimension` d ON d.parent = p.name
|
||||
WHERE
|
||||
p.name = a.parent
|
||||
AND p.disabled = 0
|
||||
""",
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
dimension_filter_map = {}
|
||||
|
||||
for f in filters:
|
||||
f.fieldname = scrub(f.accounting_dimension)
|
||||
|
||||
build_map(
|
||||
dimension_filter_map,
|
||||
f.fieldname,
|
||||
f.applicable_on_account,
|
||||
f.dimension_value,
|
||||
f.allow_or_restrict,
|
||||
f.is_mandatory,
|
||||
)
|
||||
|
||||
dimension_filter_map = {}
|
||||
|
||||
for f in filters:
|
||||
f.fieldname = scrub(f.accounting_dimension)
|
||||
|
||||
build_map(
|
||||
dimension_filter_map,
|
||||
f.fieldname,
|
||||
f.applicable_on_account,
|
||||
f.dimension_value,
|
||||
f.allow_or_restrict,
|
||||
f.is_mandatory,
|
||||
)
|
||||
frappe.flags.dimension_filter_map = dimension_filter_map
|
||||
|
||||
return frappe.flags.dimension_filter_map
|
||||
return dimension_filter_map
|
||||
|
||||
|
||||
def build_map(map_object, dimension, account, filter_value, allow_or_restrict, is_mandatory):
|
||||
|
||||
@@ -47,8 +47,6 @@ class TestAccountingDimensionFilter(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
disable_dimension_filter()
|
||||
disable_dimension()
|
||||
frappe.flags.accounting_dimensions_details = None
|
||||
frappe.flags.dimension_filter_map = None
|
||||
|
||||
for si in self.invoice_list:
|
||||
si.load_from_db()
|
||||
@@ -57,7 +55,9 @@ class TestAccountingDimensionFilter(unittest.TestCase):
|
||||
|
||||
|
||||
def create_accounting_dimension_filter():
|
||||
if not frappe.db.get_value("Accounting Dimension Filter", {"accounting_dimension": "Cost Center"}):
|
||||
if not frappe.db.get_value(
|
||||
"Accounting Dimension Filter", {"accounting_dimension": "Cost Center"}
|
||||
):
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Accounting Dimension Filter",
|
||||
|
||||
@@ -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",
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,112 +1,317 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "field:period_name",
|
||||
"creation": "2018-04-13 18:50:14.672323",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"period_name",
|
||||
"start_date",
|
||||
"end_date",
|
||||
"column_break_4",
|
||||
"company",
|
||||
"section_break_7",
|
||||
"closed_documents"
|
||||
],
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "field:period_name",
|
||||
"beta": 0,
|
||||
"creation": "2018-04-13 18:50:14.672323",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "period_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Period Name",
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "period_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Period Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "start_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Start Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "end_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "End Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "start_date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Start Date",
|
||||
"reqd": 1
|
||||
},
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_7",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "end_date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "End Date",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_7",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "closed_documents",
|
||||
"fieldtype": "Table",
|
||||
"label": "Closed Documents",
|
||||
"options": "Closed Document",
|
||||
"reqd": 1
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "closed_documents",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Closed Documents",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Closed Document",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:05:57.388109",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounting Period",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-08-01 19:14:47.593753",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounting Period",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"share": 1,
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User",
|
||||
"share": 1,
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -16,23 +16,6 @@ class ClosedAccountingPeriod(frappe.ValidationError):
|
||||
|
||||
|
||||
class AccountingPeriod(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
from erpnext.accounts.doctype.closed_document.closed_document import ClosedDocument
|
||||
|
||||
closed_documents: DF.Table[ClosedDocument]
|
||||
company: DF.Link
|
||||
end_date: DF.Date
|
||||
period_name: DF.Data
|
||||
start_date: DF.Date
|
||||
# end: auto-generated types
|
||||
|
||||
def validate(self):
|
||||
self.validate_overlap()
|
||||
|
||||
@@ -84,10 +67,7 @@ class AccountingPeriod(Document):
|
||||
for doctype_for_closing in self.get_doctypes_for_closing():
|
||||
self.append(
|
||||
"closed_documents",
|
||||
{
|
||||
"document_type": doctype_for_closing.document_type,
|
||||
"closed": doctype_for_closing.closed,
|
||||
},
|
||||
{"document_type": doctype_for_closing.document_type, "closed": doctype_for_closing.closed},
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,9 @@ class TestAccountingPeriod(unittest.TestCase):
|
||||
ap1 = create_accounting_period(period_name="Test Accounting Period 2")
|
||||
ap1.save()
|
||||
|
||||
doc = create_sales_invoice(do_not_save=1, cost_center="_Test Company - _TC", warehouse="Stores - _TC")
|
||||
doc = create_sales_invoice(
|
||||
do_not_save=1, cost_center="_Test Company - _TC", warehouse="Stores - _TC"
|
||||
)
|
||||
self.assertRaises(ClosedAccountingPeriod, doc.save)
|
||||
|
||||
def tearDown(self):
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2013-06-24 15:49:57",
|
||||
"description": "Settings for Accounts",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Other",
|
||||
"editable_grid": 1,
|
||||
@@ -31,7 +32,6 @@
|
||||
"column_break_19",
|
||||
"add_taxes_from_item_tax_template",
|
||||
"book_tax_discount_loss",
|
||||
"round_row_wise_tax",
|
||||
"print_settings",
|
||||
"show_inclusive_tax_in_print",
|
||||
"show_taxes_as_table_in_print",
|
||||
@@ -65,12 +65,7 @@
|
||||
"show_balance_in_coa",
|
||||
"banking_tab",
|
||||
"enable_party_matching",
|
||||
"enable_fuzzy_matching",
|
||||
"reports_tab",
|
||||
"remarks_section",
|
||||
"general_ledger_remarks_length",
|
||||
"column_break_lvjk",
|
||||
"receivable_payable_remarks_length"
|
||||
"enable_fuzzy_matching"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -419,41 +414,6 @@
|
||||
"fieldname": "ignore_account_closing_balance",
|
||||
"fieldtype": "Check",
|
||||
"label": "Ignore Account Closing Balance"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Tax Amount will be rounded on a row(items) level",
|
||||
"fieldname": "round_row_wise_tax",
|
||||
"fieldtype": "Check",
|
||||
"label": "Round Tax Amount Row-wise"
|
||||
},
|
||||
{
|
||||
"fieldname": "reports_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"label": "Reports"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Truncates 'Remarks' column to set character length",
|
||||
"fieldname": "general_ledger_remarks_length",
|
||||
"fieldtype": "Int",
|
||||
"label": "General Ledger"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Truncates 'Remarks' column to set character length",
|
||||
"fieldname": "receivable_payable_remarks_length",
|
||||
"fieldtype": "Int",
|
||||
"label": "Accounts Receivable/Payable"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_lvjk",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "remarks_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Remarks Column Length"
|
||||
}
|
||||
],
|
||||
"icon": "icon-cog",
|
||||
@@ -461,7 +421,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:05:57.568638",
|
||||
"modified": "2023-07-27 15:05:34.000264",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
@@ -486,7 +446,7 @@
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "creation",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
|
||||
@@ -14,52 +14,6 @@ from erpnext.stock.utils import check_pending_reposting
|
||||
|
||||
|
||||
class AccountsSettings(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
acc_frozen_upto: DF.Date | None
|
||||
add_taxes_from_item_tax_template: DF.Check
|
||||
allow_multi_currency_invoices_against_single_party_account: DF.Check
|
||||
allow_stale: DF.Check
|
||||
auto_reconcile_payments: DF.Check
|
||||
automatically_fetch_payment_terms: DF.Check
|
||||
automatically_process_deferred_accounting_entry: DF.Check
|
||||
book_asset_depreciation_entry_automatically: DF.Check
|
||||
book_deferred_entries_based_on: DF.Literal["Days", "Months"]
|
||||
book_deferred_entries_via_journal_entry: DF.Check
|
||||
book_tax_discount_loss: DF.Check
|
||||
check_supplier_invoice_uniqueness: DF.Check
|
||||
credit_controller: DF.Link | None
|
||||
delete_linked_ledger_entries: DF.Check
|
||||
determine_address_tax_category_from: DF.Literal["Billing Address", "Shipping Address"]
|
||||
enable_common_party_accounting: DF.Check
|
||||
enable_fuzzy_matching: DF.Check
|
||||
enable_party_matching: DF.Check
|
||||
frozen_accounts_modifier: DF.Link | None
|
||||
general_ledger_remarks_length: DF.Int
|
||||
ignore_account_closing_balance: DF.Check
|
||||
make_payment_via_journal_entry: DF.Check
|
||||
merge_similar_account_heads: DF.Check
|
||||
over_billing_allowance: DF.Currency
|
||||
post_change_gl_entries: DF.Check
|
||||
receivable_payable_remarks_length: DF.Int
|
||||
role_allowed_to_over_bill: DF.Link | None
|
||||
round_row_wise_tax: DF.Check
|
||||
show_balance_in_coa: DF.Check
|
||||
show_inclusive_tax_in_print: DF.Check
|
||||
show_payment_schedule_in_print: DF.Check
|
||||
show_taxes_as_table_in_print: DF.Check
|
||||
stale_days: DF.Int
|
||||
submit_journal_entries: DF.Check
|
||||
unlink_advance_payment_on_cancelation_of_order: DF.Check
|
||||
unlink_payment_on_cancellation_of_invoice: DF.Check
|
||||
# end: auto-generated types
|
||||
|
||||
def validate(self):
|
||||
old_doc = self.get_doc_before_save()
|
||||
clear_cache = False
|
||||
|
||||
@@ -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");
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
@@ -45,13 +45,12 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:05:58.308002",
|
||||
"modified": "2021-11-25 10:27:51.712286",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Advance Tax",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
@@ -6,22 +6,4 @@ from frappe.model.document import Document
|
||||
|
||||
|
||||
class AdvanceTax(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
account_head: DF.Link | None
|
||||
allocated_amount: DF.Currency
|
||||
parent: DF.Data
|
||||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
reference_detail: DF.Data | None
|
||||
reference_name: DF.DynamicLink | None
|
||||
reference_type: DF.Link | None
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
@@ -179,13 +179,12 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:05:58.437605",
|
||||
"modified": "2021-11-25 11:10:10.945027",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Advance Taxes and Charges",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "creation",
|
||||
"sort_order": "ASC",
|
||||
"states": []
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC"
|
||||
}
|
||||
@@ -7,33 +7,4 @@ from frappe.model.document import Document
|
||||
|
||||
|
||||
class AdvanceTaxesandCharges(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
account_head: DF.Link
|
||||
add_deduct_tax: DF.Literal["Add", "Deduct"]
|
||||
allocated_amount: DF.Currency
|
||||
base_tax_amount: DF.Currency
|
||||
base_total: DF.Currency
|
||||
charge_type: DF.Literal[
|
||||
"", "Actual", "On Paid Amount", "On Previous Row Amount", "On Previous Row Total"
|
||||
]
|
||||
cost_center: DF.Link | None
|
||||
currency: DF.Link | None
|
||||
description: DF.SmallText
|
||||
included_in_paid_amount: DF.Check
|
||||
parent: DF.Data
|
||||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
rate: DF.Float
|
||||
row_id: DF.Data | None
|
||||
tax_amount: DF.Currency
|
||||
total: DF.Currency
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
@@ -14,27 +14,30 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Accounting Dimension",
|
||||
"options": "DocType",
|
||||
"read_only": 1
|
||||
"read_only": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "dimension_value",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"in_list_view": 1,
|
||||
"options": "accounting_dimension"
|
||||
"options": "accounting_dimension",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:05:58.587487",
|
||||
"modified": "2020-11-23 09:56:19.744200",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Allowed Dimension",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "creation",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -7,19 +7,4 @@ from frappe.model.document import Document
|
||||
|
||||
|
||||
class AllowedDimension(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
accounting_dimension: DF.Link | None
|
||||
dimension_value: DF.DynamicLink | None
|
||||
parent: DF.Data
|
||||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
@@ -20,15 +19,14 @@
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:05:58.698893",
|
||||
"modified": "2020-05-01 12:32:34.044911",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Allowed To Transact With",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "creation",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -6,18 +6,4 @@ from frappe.model.document import Document
|
||||
|
||||
|
||||
class AllowedToTransactWith(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
company: DF.Link
|
||||
parent: DF.Data
|
||||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
"in_list_view": 1,
|
||||
"label": "Accounts",
|
||||
"options": "Account",
|
||||
"reqd": 1
|
||||
"reqd": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
@@ -23,21 +25,22 @@
|
||||
"fieldname": "is_mandatory",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Is Mandatory"
|
||||
"label": "Is Mandatory",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:05:59.168897",
|
||||
"modified": "2020-11-22 19:55:13.324136",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Applicable On Account",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "creation",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -7,19 +7,4 @@ from frappe.model.document import Document
|
||||
|
||||
|
||||
class ApplicableOnAccount(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
applicable_on_account: DF.Link
|
||||
is_mandatory: DF.Check
|
||||
parent: DF.Data
|
||||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
@@ -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' });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:06:36.896195",
|
||||
"modified": "2020-07-17 14:00:13.105433",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank",
|
||||
@@ -121,8 +121,7 @@
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "creation",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -10,25 +10,6 @@ from frappe.model.document import Document
|
||||
|
||||
|
||||
class Bank(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
from erpnext.accounts.doctype.bank_transaction_mapping.bank_transaction_mapping import (
|
||||
BankTransactionMapping,
|
||||
)
|
||||
|
||||
bank_name: DF.Data
|
||||
bank_transaction_mapping: DF.Table[BankTransactionMapping]
|
||||
plaid_access_token: DF.Data | None
|
||||
swift_number: DF.Data | None
|
||||
website: DF.Data | None
|
||||
# end: auto-generated types
|
||||
|
||||
def onload(self):
|
||||
"""Load address and contacts in `__onload`"""
|
||||
load_address_and_contact(self)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
"account_type",
|
||||
"account_subtype",
|
||||
"column_break_7",
|
||||
"disabled",
|
||||
"is_default",
|
||||
"is_company_account",
|
||||
"company",
|
||||
@@ -200,16 +199,10 @@
|
||||
"fieldtype": "Data",
|
||||
"in_global_search": 1,
|
||||
"label": "Branch Code"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Disabled"
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:06:37.049542",
|
||||
"modified": "2022-05-04 15:49:42.620630",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Account",
|
||||
@@ -242,7 +235,7 @@
|
||||
}
|
||||
],
|
||||
"search_fields": "bank,account",
|
||||
"sort_field": "creation",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
|
||||
@@ -9,37 +9,9 @@ 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):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
account: DF.Link | None
|
||||
account_name: DF.Data
|
||||
account_subtype: DF.Link | None
|
||||
account_type: DF.Link | None
|
||||
bank: DF.Link
|
||||
bank_account_no: DF.Data | None
|
||||
branch_code: DF.Data | None
|
||||
company: DF.Link | None
|
||||
disabled: DF.Check
|
||||
iban: DF.Data | None
|
||||
integration_id: DF.Data | None
|
||||
is_company_account: DF.Check
|
||||
is_default: DF.Check
|
||||
last_integration_date: DF.Date | None
|
||||
mask: DF.Data | None
|
||||
party: DF.DynamicLink | None
|
||||
party_type: DF.Link | None
|
||||
# end: auto-generated types
|
||||
|
||||
def onload(self):
|
||||
"""Load address and contacts in `__onload`"""
|
||||
load_address_and_contact(self)
|
||||
@@ -53,24 +25,10 @@ class BankAccount(Document):
|
||||
def validate(self):
|
||||
self.validate_company()
|
||||
self.validate_iban()
|
||||
self.validate_account()
|
||||
self.update_default_bank_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):
|
||||
"""
|
||||
@@ -101,51 +59,19 @@ class BankAccount(Document):
|
||||
if to_check % 97 != 1:
|
||||
frappe.throw(_("IBAN is not valid"))
|
||||
|
||||
def update_default_bank_account(self):
|
||||
if self.is_default and not self.disabled:
|
||||
frappe.db.set_value(
|
||||
"Bank Account",
|
||||
{
|
||||
"party_type": self.party_type,
|
||||
"party": self.party,
|
||||
"is_company_account": self.is_company_account,
|
||||
"is_default": 1,
|
||||
"disabled": 0,
|
||||
},
|
||||
"is_default",
|
||||
0,
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_bank_account(doctype, docname):
|
||||
doc = frappe.new_doc("Bank Account")
|
||||
doc.party_type = doctype
|
||||
doc.party = docname
|
||||
doc.is_default = 1
|
||||
|
||||
return doc
|
||||
|
||||
|
||||
def get_party_bank_account(party_type, party):
|
||||
return frappe.db.get_value(
|
||||
"Bank Account",
|
||||
{"party_type": party_type, "party": party, "is_default": 1, "disabled": 0},
|
||||
"name",
|
||||
)
|
||||
|
||||
|
||||
def get_default_company_bank_account(company, party_type, party):
|
||||
default_company_bank_account = frappe.db.get_value(party_type, party, "default_bank_account")
|
||||
if default_company_bank_account:
|
||||
if company != frappe.get_cached_value("Bank Account", default_company_bank_account, "company"):
|
||||
default_company_bank_account = None
|
||||
|
||||
if not default_company_bank_account:
|
||||
default_company_bank_account = frappe.db.get_value(
|
||||
"Bank Account", {"company": company, "is_company_account": 1, "is_default": 1}
|
||||
)
|
||||
|
||||
return default_company_bank_account
|
||||
return frappe.db.get_value(party_type, party, "default_bank_account")
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
||||
@@ -37,11 +37,11 @@ class TestBankAccount(unittest.TestCase):
|
||||
try:
|
||||
bank_account.validate_iban()
|
||||
except ValidationError:
|
||||
msg = f"BankAccount.validate_iban() failed for valid IBAN {iban}"
|
||||
msg = "BankAccount.validate_iban() failed for valid IBAN {}".format(iban)
|
||||
self.fail(msg=msg)
|
||||
|
||||
for not_iban in invalid_ibans:
|
||||
bank_account.iban = not_iban
|
||||
msg = f"BankAccount.validate_iban() accepted invalid IBAN {not_iban}"
|
||||
msg = "BankAccount.validate_iban() accepted invalid IBAN {}".format(not_iban)
|
||||
with self.assertRaises(ValidationError, msg=msg):
|
||||
bank_account.validate_iban()
|
||||
|
||||
@@ -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() {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,69 +1,134 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:account_subtype",
|
||||
"beta": 0,
|
||||
"creation": "2018-10-25 15:46:08.054586",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"account_subtype"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "account_subtype",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Account Subtype",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 1
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:06:37.221876",
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-10-25 15:47:03.841390",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Account Subtype",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "creation",
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
@@ -6,15 +6,4 @@ from frappe.model.document import Document
|
||||
|
||||
|
||||
class BankAccountSubtype(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
account_subtype: DF.Data | None
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
@@ -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) {
|
||||
|
||||
// }
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:06:37.347035",
|
||||
"modified": "2020-04-10 21:13:09.137898",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Account Type",
|
||||
@@ -63,7 +63,6 @@
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
@@ -7,15 +7,4 @@ from frappe.model.document import Document
|
||||
|
||||
|
||||
class BankAccountType(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
account_type: DF.Data | None
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
"idx": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:06:37.477927",
|
||||
"modified": "2022-11-28 17:24:13.008692",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Clearance",
|
||||
@@ -107,7 +107,7 @@
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 1,
|
||||
"sort_field": "creation",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC",
|
||||
"states": []
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -15,28 +13,6 @@ form_grid_templates = {"journal_entries": "templates/form_grid/bank_reconciliati
|
||||
|
||||
|
||||
class BankClearance(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
from erpnext.accounts.doctype.bank_clearance_detail.bank_clearance_detail import (
|
||||
BankClearanceDetail,
|
||||
)
|
||||
|
||||
account: DF.Link
|
||||
account_currency: DF.Link | None
|
||||
bank_account: DF.Link | None
|
||||
from_date: DF.Date
|
||||
include_pos_transactions: DF.Check
|
||||
include_reconciled_entries: DF.Check
|
||||
payment_entries: DF.Table[BankClearanceDetail]
|
||||
to_date: DF.Date
|
||||
# end: auto-generated types
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_payment_entries(self):
|
||||
if not (self.from_date and self.to_date):
|
||||
@@ -127,7 +103,7 @@ def get_payment_entries_for_bank_clearance(
|
||||
condition = "and (clearance_date IS NULL or clearance_date='0000-00-00')"
|
||||
|
||||
journal_entries = frappe.db.sql(
|
||||
f"""
|
||||
"""
|
||||
select
|
||||
"Journal Entry" as payment_document, t1.name as payment_entry,
|
||||
t1.cheque_no as cheque_number, t1.cheque_date,
|
||||
@@ -141,7 +117,9 @@ def get_payment_entries_for_bank_clearance(
|
||||
and ifnull(t1.is_opening, 'No') = 'No' {condition}
|
||||
group by t2.account, t1.name
|
||||
order by t1.posting_date ASC, t1.name DESC
|
||||
""",
|
||||
""".format(
|
||||
condition=condition
|
||||
),
|
||||
{"account": account, "from": from_date, "to": to_date},
|
||||
as_dict=1,
|
||||
)
|
||||
@@ -150,7 +128,7 @@ def get_payment_entries_for_bank_clearance(
|
||||
condition += "and bank_account = %(bank_account)s"
|
||||
|
||||
payment_entries = frappe.db.sql(
|
||||
f"""
|
||||
"""
|
||||
select
|
||||
"Payment Entry" as payment_document, name as payment_entry,
|
||||
reference_no as cheque_number, reference_date as cheque_date,
|
||||
@@ -165,7 +143,9 @@ def get_payment_entries_for_bank_clearance(
|
||||
{condition}
|
||||
order by
|
||||
posting_date ASC, name DESC
|
||||
""",
|
||||
""".format(
|
||||
condition=condition
|
||||
),
|
||||
{
|
||||
"account": account,
|
||||
"from": from_date,
|
||||
@@ -177,65 +157,45 @@ 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) + list(journal_entries) + list(pos_sales_invoices) + list(pos_purchase_invoices)
|
||||
list(payment_entries)
|
||||
+ list(journal_entries)
|
||||
+ list(pos_sales_invoices)
|
||||
+ list(pos_purchase_invoices)
|
||||
)
|
||||
|
||||
return entries
|
||||
|
||||
@@ -35,14 +35,13 @@ class TestBankClearance(unittest.TestCase):
|
||||
from lending.loan_management.doctype.loan.test_loan import (
|
||||
create_loan,
|
||||
create_loan_accounts,
|
||||
create_loan_product,
|
||||
create_loan_type,
|
||||
create_repayment_entry,
|
||||
make_loan_disbursement_entry,
|
||||
)
|
||||
|
||||
def create_loan_masters():
|
||||
create_loan_product(
|
||||
"Clearance Loan",
|
||||
create_loan_type(
|
||||
"Clearance Loan",
|
||||
2000000,
|
||||
13.5,
|
||||
@@ -68,7 +67,9 @@ class TestBankClearance(unittest.TestCase):
|
||||
)
|
||||
loan.submit()
|
||||
make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=getdate())
|
||||
repayment_entry = create_repayment_entry(loan.name, "_Test Customer", getdate(), loan.loan_amount)
|
||||
repayment_entry = create_repayment_entry(
|
||||
loan.name, "_Test Customer", getdate(), loan.loan_amount
|
||||
)
|
||||
repayment_entry.save()
|
||||
repayment_entry.submit()
|
||||
|
||||
|
||||
@@ -1,112 +1,340 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2013-02-22 01:27:37",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"payment_document",
|
||||
"payment_entry",
|
||||
"against_account",
|
||||
"amount",
|
||||
"column_break_5",
|
||||
"posting_date",
|
||||
"cheque_number",
|
||||
"cheque_date",
|
||||
"clearance_date"
|
||||
],
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:27:37",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "payment_document",
|
||||
"fieldtype": "Link",
|
||||
"label": "Payment Document",
|
||||
"options": "DocType"
|
||||
},
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "payment_document",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Payment Document",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "DocType",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "payment_entry",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Payment Entry",
|
||||
"oldfieldname": "voucher_id",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "payment_document",
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "payment_entry",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Payment Entry",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "voucher_id",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "payment_document",
|
||||
"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,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"width": "50"
|
||||
},
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "against_account",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Against Account",
|
||||
"oldfieldname": "against_account",
|
||||
"oldfieldtype": "Data",
|
||||
"read_only": 1,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "against_account",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Against Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "against_account",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"width": "15"
|
||||
},
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
"oldfieldname": "debit",
|
||||
"oldfieldtype": "Currency",
|
||||
"read_only": 1
|
||||
},
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "debit",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_5",
|
||||
"fieldtype": "Column Break",
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_5",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "posting_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Posting Date",
|
||||
"oldfieldname": "posting_date",
|
||||
"oldfieldtype": "Date",
|
||||
"read_only": 1
|
||||
},
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "posting_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Posting Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "posting_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "cheque_number",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Cheque Number",
|
||||
"oldfieldname": "cheque_number",
|
||||
"oldfieldtype": "Data",
|
||||
"read_only": 1
|
||||
},
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "cheque_number",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Cheque Number",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "cheque_number",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "cheque_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Cheque Date",
|
||||
"oldfieldname": "cheque_date",
|
||||
"oldfieldtype": "Date",
|
||||
"read_only": 1
|
||||
},
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "cheque_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Cheque Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "cheque_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "clearance_date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Clearance Date",
|
||||
"oldfieldname": "clearance_date",
|
||||
"oldfieldtype": "Date"
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "clearance_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Clearance Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "clearance_date",
|
||||
"oldfieldtype": "Date",
|
||||
"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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:06:37.609319",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Clearance Detail",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "creation",
|
||||
"sort_order": "ASC",
|
||||
"states": []
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2019-01-07 16:52:07.174687",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Clearance Detail",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_order": "ASC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
@@ -6,25 +6,4 @@ from frappe.model.document import Document
|
||||
|
||||
|
||||
class BankClearanceDetail(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
against_account: DF.Data | None
|
||||
amount: DF.Data | None
|
||||
cheque_date: DF.Date | None
|
||||
cheque_number: DF.Data | None
|
||||
clearance_date: DF.Date | None
|
||||
parent: DF.Data
|
||||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
payment_document: DF.Link | None
|
||||
payment_entry: DF.DynamicLink | None
|
||||
posting_date: DF.Date | None
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user