Compare commits
3 Commits
pe_referen
...
v14.0.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c6d8435a1 | ||
|
|
c3c59f1274 | ||
|
|
fc75cfdeb6 |
@@ -5,7 +5,7 @@
|
||||
"es6": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 11,
|
||||
"ecmaVersion": 9,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
|
||||
10
.github/ISSUE_TEMPLATE/feature_request.md
vendored
10
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -12,18 +12,10 @@ Welcome to ERPNext issue tracker! Before creating an issue, please heed the foll
|
||||
|
||||
1. This tracker should only be used to report bugs and request features / enhancements to ERPNext
|
||||
- For questions and general support, checkout the manual https://erpnext.com/docs/user/manual/en or use https://discuss.erpnext.com
|
||||
- For documentation issues, refer to https://github.com/frappe/erpnext_com
|
||||
2. Use the search function before creating a new issue. Duplicates will be closed and directed to
|
||||
the original discussion.
|
||||
3. When making a feature request, make sure to be as verbose as possible. The better you convey your message, the greater the drive to make it happen.
|
||||
|
||||
|
||||
Please keep in mind that we get many many requests and we can't possibly work on all of them, we prioritize development based on the goals of the product and organization. Feature requests are still welcome as it helps us in research when we do decide to work on the requested feature.
|
||||
|
||||
If you're in urgent need to a feature, please try the following channels to get paid developments done quickly:
|
||||
1. Certified ERPNext partners: https://erpnext.com/partners
|
||||
2. Developer community on ERPNext forums: https://discuss.erpnext.com/c/developers/5
|
||||
3. Telegram group for ERPNext/Frappe development work: https://t.me/erpnext_opps
|
||||
|
||||
-->
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
|
||||
1
.github/helper/.flake8_strict
vendored
1
.github/helper/.flake8_strict
vendored
@@ -66,7 +66,6 @@ ignore =
|
||||
F841,
|
||||
E713,
|
||||
E712,
|
||||
B023
|
||||
|
||||
|
||||
max-line-length = 200
|
||||
|
||||
16
.github/helper/install.sh
vendored
16
.github/helper/install.sh
vendored
@@ -4,7 +4,7 @@ set -e
|
||||
|
||||
cd ~ || exit
|
||||
|
||||
sudo apt update && sudo apt install redis-server libcups2-dev
|
||||
sudo apt-get install redis-server libcups2-dev
|
||||
|
||||
pip install frappe-bench
|
||||
|
||||
@@ -24,14 +24,15 @@ fi
|
||||
|
||||
|
||||
if [ "$DB" == "mariadb" ];then
|
||||
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'"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL character_set_server = 'utf8mb4'"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
|
||||
|
||||
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'"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE DATABASE test_frappe"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
|
||||
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -proot -e "FLUSH PRIVILEGES"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -e "FLUSH PRIVILEGES"
|
||||
fi
|
||||
|
||||
if [ "$DB" == "postgres" ];then
|
||||
@@ -55,7 +56,6 @@ sed -i 's/schedule:/# schedule:/g' Procfile
|
||||
sed -i 's/socketio:/# socketio:/g' Procfile
|
||||
sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile
|
||||
|
||||
bench get-app payments
|
||||
bench get-app erpnext "${GITHUB_WORKSPACE}"
|
||||
|
||||
if [ "$TYPE" == "server" ]; then bench setup requirements --dev; fi
|
||||
|
||||
2
.github/helper/site_config_mariadb.json
vendored
2
.github/helper/site_config_mariadb.json
vendored
@@ -9,7 +9,7 @@
|
||||
"mail_password": "test",
|
||||
"admin_password": "admin",
|
||||
"root_login": "root",
|
||||
"root_password": "root",
|
||||
"root_password": "travis",
|
||||
"host_name": "http://test_site:8000",
|
||||
"install_apps": ["erpnext"],
|
||||
"throttle_user_limit": 100
|
||||
|
||||
12
.github/stale.yml
vendored
12
.github/stale.yml
vendored
@@ -24,4 +24,14 @@ pulls:
|
||||
:) Also, even if it is closed, you can always reopen the PR when you're
|
||||
ready. Thank you for contributing.
|
||||
|
||||
only: pulls
|
||||
issues:
|
||||
daysUntilStale: 60
|
||||
daysUntilClose: 7
|
||||
exemptLabels:
|
||||
- valid
|
||||
- to-validate
|
||||
- QA
|
||||
markComment: >
|
||||
This issue has been automatically marked as inactive because it has not had
|
||||
recent activity and it wasn't validated by maintainer team. It will be
|
||||
closed within a week if no further activity occurs.
|
||||
|
||||
2
.github/try-on-f-cloud-button.svg
vendored
2
.github/try-on-f-cloud-button.svg
vendored
@@ -1,4 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="4 2 193 52">
|
||||
<svg width="201" height="60" viewBox="0 0 201 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_dd)">
|
||||
<rect x="4" y="2" width="193" height="52" rx="6" fill="#2490EF"/>
|
||||
<path d="M28 22.2891H32.8786V35.5H36.2088V22.2891H41.0874V19.5H28V22.2891Z" fill="white"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.4 KiB |
2
.github/workflows/docs-checker.yml
vendored
2
.github/workflows/docs-checker.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
- name: 'Setup Environment'
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.10'
|
||||
python-version: 3.8
|
||||
|
||||
- name: 'Clone repo'
|
||||
uses: actions/checkout@v2
|
||||
|
||||
32
.github/workflows/initiate_release.yml
vendored
32
.github/workflows/initiate_release.yml
vendored
@@ -1,32 +0,0 @@
|
||||
# This workflow is agnostic to branches. Only maintain on develop branch.
|
||||
# To add/remove versions just modify the matrix.
|
||||
|
||||
name: Create weekly release pull requests
|
||||
on:
|
||||
schedule:
|
||||
# 9:30 UTC => 3 PM IST Tuesday
|
||||
- cron: "30 9 * * 2"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: ["13", "14"]
|
||||
|
||||
steps:
|
||||
- uses: octokit/request-action@v2.x
|
||||
with:
|
||||
route: POST /repos/{owner}/{repo}/pulls
|
||||
owner: frappe
|
||||
repo: erpnext
|
||||
title: |-
|
||||
"chore: release v${{ matrix.version }}"
|
||||
body: "Automated weekly release."
|
||||
base: version-${{ matrix.version }}
|
||||
head: version-${{ matrix.version }}-hotfix
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
16
.github/workflows/linters.yml
vendored
16
.github/workflows/linters.yml
vendored
@@ -11,10 +11,10 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Python 3.10
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.10'
|
||||
python-version: 3.8
|
||||
|
||||
- name: Install and Run Pre-commit
|
||||
uses: pre-commit/action@v2.0.3
|
||||
@@ -22,8 +22,10 @@ jobs:
|
||||
- name: Download Semgrep rules
|
||||
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
|
||||
|
||||
- name: Download semgrep
|
||||
run: pip install semgrep==0.97.0
|
||||
|
||||
- name: Run Semgrep rules
|
||||
run: semgrep ci --config ./frappe-semgrep-rules/rules --config r/python.lang.correctness
|
||||
- uses: returntocorp/semgrep-action@v1
|
||||
env:
|
||||
SEMGREP_TIMEOUT: 120
|
||||
with:
|
||||
config: >-
|
||||
r/python.lang.correctness
|
||||
./frappe-semgrep-rules/rules
|
||||
|
||||
38
.github/workflows/patch.yml
vendored
38
.github/workflows/patch.yml
vendored
@@ -11,7 +11,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: patch-develop-${{ github.event_name }}-${{ github.event.number || github.event_name == 'workflow_dispatch' && github.run_id || '' }}
|
||||
group: patch-develop-${{ github.event.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
mysql:
|
||||
image: mariadb:10.3
|
||||
env:
|
||||
MARIADB_ROOT_PASSWORD: 'root'
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: YES
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
@@ -34,18 +34,10 @@ jobs:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Check for valid Python & Merge Conflicts
|
||||
run: |
|
||||
python -m compileall -f "${GITHUB_WORKSPACE}"
|
||||
if grep -lr --exclude-dir=node_modules "^<<<<<<< " "${GITHUB_WORKSPACE}"
|
||||
then echo "Found merge conflicts"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Setup Python
|
||||
uses: "gabrielfalcao/pyenv-action@v9"
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
versions: 3.10:latest, 3.7:latest
|
||||
python-version: 3.8
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
@@ -60,7 +52,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
${{ runner.os }}-
|
||||
@@ -90,10 +82,7 @@ jobs:
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
pip install frappe-bench
|
||||
pyenv global $(pyenv versions | grep '3.10')
|
||||
bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
|
||||
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
|
||||
env:
|
||||
DB: mariadb
|
||||
TYPE: server
|
||||
@@ -107,7 +96,6 @@ jobs:
|
||||
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
|
||||
|
||||
pyenv global $(pyenv versions | grep '3.7')
|
||||
for version in $(seq 12 13)
|
||||
do
|
||||
echo "Updating to v$version"
|
||||
@@ -119,11 +107,7 @@ jobs:
|
||||
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
|
||||
bench pip install -e ./apps/payments
|
||||
bench pip install -e ./apps/erpnext
|
||||
|
||||
bench setup requirements --python
|
||||
bench --site test_site migrate
|
||||
done
|
||||
|
||||
@@ -131,12 +115,4 @@ jobs:
|
||||
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"
|
||||
|
||||
pyenv global $(pyenv versions | grep '3.10')
|
||||
rm -rf ~/frappe-bench/env
|
||||
bench -v setup env
|
||||
bench pip install -e ./apps/payments
|
||||
bench pip install -e ./apps/erpnext
|
||||
|
||||
bench --site test_site migrate
|
||||
bench --site test_site install-app payments
|
||||
|
||||
31
.github/workflows/release.yml
vendored
31
.github/workflows/release.yml
vendored
@@ -1,31 +0,0 @@
|
||||
name: Generate Semantic Release
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- version-13
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Entire Repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- name: Setup Node.js v14
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
- name: Setup dependencies
|
||||
run: |
|
||||
npm install @semantic-release/git @semantic-release/exec --no-save
|
||||
- name: Create Release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
GIT_AUTHOR_NAME: "Frappe PR Bot"
|
||||
GIT_AUTHOR_EMAIL: "developers@frappe.io"
|
||||
GIT_COMMITTER_NAME: "Frappe PR Bot"
|
||||
GIT_COMMITTER_EMAIL: "developers@frappe.io"
|
||||
run: npx semantic-release
|
||||
30
.github/workflows/semantic-commits.yml
vendored
30
.github/workflows/semantic-commits.yml
vendored
@@ -1,30 +0,0 @@
|
||||
name: Semantic Commits
|
||||
|
||||
on:
|
||||
pull_request: {}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: commitcheck-erpnext-${{ github.event.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
commitlint:
|
||||
name: Check Commit Titles
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 200
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14
|
||||
check-latest: true
|
||||
|
||||
- name: Check commit titles
|
||||
run: |
|
||||
npm install @commitlint/cli @commitlint/config-conventional
|
||||
npx commitlint --verbose --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }}
|
||||
40
.github/workflows/server-tests-mariadb.yml
vendored
40
.github/workflows/server-tests-mariadb.yml
vendored
@@ -27,7 +27,7 @@ on:
|
||||
type: string
|
||||
|
||||
concurrency:
|
||||
group: server-mariadb-develop-${{ github.event_name }}-${{ github.event.number || github.event_name == 'workflow_dispatch' && github.run_id || '' }}
|
||||
group: server-mariadb-develop-${{ github.event.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
@@ -39,15 +39,15 @@ jobs:
|
||||
fail-fast: false
|
||||
|
||||
matrix:
|
||||
container: [1, 2, 3, 4]
|
||||
container: [1, 2, 3]
|
||||
|
||||
name: Python Unit Tests
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mariadb:10.6
|
||||
image: mariadb:10.3
|
||||
env:
|
||||
MARIADB_ROOT_PASSWORD: 'root'
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: YES
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
@@ -59,15 +59,7 @@ jobs:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Check for valid Python & Merge Conflicts
|
||||
run: |
|
||||
python -m compileall -f "${GITHUB_WORKSPACE}"
|
||||
if grep -lr --exclude-dir=node_modules "^<<<<<<< " "${GITHUB_WORKSPACE}"
|
||||
then echo "Found merge conflicts"
|
||||
exit 1
|
||||
fi
|
||||
python-version: 3.8
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
@@ -82,7 +74,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
${{ runner.os }}-
|
||||
@@ -120,32 +112,16 @@ jobs:
|
||||
FRAPPE_BRANCH: ${{ github.event.inputs.branch }}
|
||||
|
||||
- name: Run Tests
|
||||
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --with-coverage --total-builds 4 --build-number ${{ matrix.container }}'
|
||||
run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --use-orchestrator --with-coverage
|
||||
env:
|
||||
TYPE: server
|
||||
CI_BUILD_ID: ${{ github.run_id }}
|
||||
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
|
||||
|
||||
- name: Upload coverage data
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage-${{ matrix.container }}
|
||||
path: /home/runner/frappe-bench/sites/coverage.xml
|
||||
|
||||
coverage:
|
||||
name: Coverage Wrap Up
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
|
||||
- name: Upload coverage data
|
||||
uses: codecov/codecov-action@v2
|
||||
with:
|
||||
name: MariaDB
|
||||
fail_ci_if_error: true
|
||||
files: /home/runner/frappe-bench/sites/coverage.xml
|
||||
verbose: true
|
||||
|
||||
17
.github/workflows/server-tests-postgres.yml
vendored
17
.github/workflows/server-tests-postgres.yml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
types: [opened, labelled, synchronize, reopened]
|
||||
|
||||
concurrency:
|
||||
group: server-postgres-develop-${{ github.event_name }}-${{ github.event.number || github.event_name == 'workflow_dispatch' && github.run_id || '' }}
|
||||
group: server-postgres-develop-${{ github.event.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
container: [1]
|
||||
container: [1, 2, 3]
|
||||
|
||||
name: Python Unit Tests
|
||||
|
||||
@@ -46,15 +46,7 @@ jobs:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.10'
|
||||
|
||||
- name: Check for valid Python & Merge Conflicts
|
||||
run: |
|
||||
python -m compileall -f "${GITHUB_WORKSPACE}"
|
||||
if grep -lr --exclude-dir=node_modules "^<<<<<<< " "${GITHUB_WORKSPACE}"
|
||||
then echo "Found merge conflicts"
|
||||
exit 1
|
||||
fi
|
||||
python-version: 3.8
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
@@ -69,7 +61,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
${{ runner.os }}-
|
||||
@@ -98,6 +90,7 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
|
||||
- name: Install
|
||||
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
|
||||
env:
|
||||
|
||||
13
.mergify.yml
13
.mergify.yml
@@ -9,9 +9,6 @@ pull_request_rules:
|
||||
- author!=nabinhait
|
||||
- author!=ankush
|
||||
- author!=deepeshgarg007
|
||||
- author!=frappe-pr-bot
|
||||
- author!=mergify[bot]
|
||||
|
||||
- or:
|
||||
- base=version-13
|
||||
- base=version-12
|
||||
@@ -22,16 +19,6 @@ 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"
|
||||
|
||||
@@ -16,8 +16,8 @@ repos:
|
||||
- id: check-merge-conflict
|
||||
- id: check-ast
|
||||
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 5.0.4
|
||||
- repo: https://gitlab.com/pycqa/flake8
|
||||
rev: 3.9.2
|
||||
hooks:
|
||||
- id: flake8
|
||||
additional_dependencies: [
|
||||
|
||||
24
.releaserc
24
.releaserc
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"branches": ["version-13"],
|
||||
"plugins": [
|
||||
"@semantic-release/commit-analyzer", {
|
||||
"preset": "angular",
|
||||
"releaseRules": [
|
||||
{"breaking": true, "release": false}
|
||||
]
|
||||
},
|
||||
"@semantic-release/release-notes-generator",
|
||||
[
|
||||
"@semantic-release/exec", {
|
||||
"prepareCmd": 'sed -ir "s/[0-9]*\.[0-9]*\.[0-9]*/${nextRelease.version}/" erpnext/__init__.py'
|
||||
}
|
||||
],
|
||||
[
|
||||
"@semantic-release/git", {
|
||||
"assets": ["erpnext/__init__.py"],
|
||||
"message": "chore(release): Bumped to Version ${nextRelease.version}\n\n${nextRelease.notes}"
|
||||
}
|
||||
],
|
||||
"@semantic-release/github"
|
||||
]
|
||||
}
|
||||
37
CODEOWNERS
37
CODEOWNERS
@@ -3,26 +3,33 @@
|
||||
# These owners will be the default owners for everything in
|
||||
# the repo. Unless a later match takes precedence,
|
||||
|
||||
erpnext/accounts/ @nextchamp-saqib @deepeshgarg007 @ruthra-kumar
|
||||
erpnext/assets/ @nextchamp-saqib @deepeshgarg007 @ruthra-kumar
|
||||
erpnext/accounts/ @nextchamp-saqib @deepeshgarg007
|
||||
erpnext/assets/ @nextchamp-saqib @deepeshgarg007
|
||||
erpnext/erpnext_integrations/ @nextchamp-saqib
|
||||
erpnext/loan_management/ @nextchamp-saqib @deepeshgarg007
|
||||
erpnext/regional @nextchamp-saqib @deepeshgarg007 @ruthra-kumar
|
||||
erpnext/selling @nextchamp-saqib @deepeshgarg007 @ruthra-kumar
|
||||
erpnext/regional @nextchamp-saqib @deepeshgarg007
|
||||
erpnext/selling @nextchamp-saqib @deepeshgarg007
|
||||
erpnext/support/ @nextchamp-saqib @deepeshgarg007
|
||||
pos* @nextchamp-saqib
|
||||
|
||||
erpnext/buying/ @rohitwaghchaure @s-aga-r
|
||||
erpnext/maintenance/ @rohitwaghchaure @s-aga-r
|
||||
erpnext/manufacturing/ @rohitwaghchaure @s-aga-r
|
||||
erpnext/quality_management/ @rohitwaghchaure @s-aga-r
|
||||
erpnext/stock/ @rohitwaghchaure @s-aga-r
|
||||
erpnext/buying/ @marination @rohitwaghchaure @ankush
|
||||
erpnext/e_commerce/ @marination
|
||||
erpnext/maintenance/ @marination @rohitwaghchaure
|
||||
erpnext/manufacturing/ @marination @rohitwaghchaure @ankush
|
||||
erpnext/portal/ @marination
|
||||
erpnext/quality_management/ @marination @rohitwaghchaure
|
||||
erpnext/shopping_cart/ @marination
|
||||
erpnext/stock/ @marination @rohitwaghchaure @ankush
|
||||
|
||||
erpnext/crm/ @NagariaHussain
|
||||
erpnext/education/ @rutwikhdev
|
||||
erpnext/projects/ @ruchamahabal
|
||||
erpnext/crm/ @ruchamahabal @pateljannat
|
||||
erpnext/education/ @ruchamahabal @pateljannat
|
||||
erpnext/hr/ @ruchamahabal @pateljannat
|
||||
erpnext/payroll @ruchamahabal @pateljannat
|
||||
erpnext/projects/ @ruchamahabal @pateljannat
|
||||
|
||||
erpnext/controllers/ @deepeshgarg007 @nextchamp-saqib @rohitwaghchaure
|
||||
erpnext/patches/ @deepeshgarg007 @nextchamp-saqib
|
||||
erpnext/controllers/ @deepeshgarg007 @nextchamp-saqib @rohitwaghchaure @marination @ankush
|
||||
erpnext/patches/ @deepeshgarg007 @nextchamp-saqib @marination @ankush
|
||||
erpnext/public/ @nextchamp-saqib @marination
|
||||
|
||||
.github/ @ankush
|
||||
pyproject.toml @ankush
|
||||
requirements.txt @gavindsouza
|
||||
|
||||
92
README.md
92
README.md
@@ -1,7 +1,5 @@
|
||||
<div align="center">
|
||||
<a href="https://erpnext.com">
|
||||
<img src="https://raw.githubusercontent.com/frappe/erpnext/develop/erpnext/public/images/erpnext-logo.png" height="128">
|
||||
</a>
|
||||
<h2>ERPNext</h2>
|
||||
<p align="center">
|
||||
<p>ERP made simple</p>
|
||||
@@ -34,47 +32,32 @@ ERPNext as a monolith includes the following areas for managing businesses:
|
||||
1. [Customize ERPNext](https://erpnext.com/docs/user/manual/en/customize-erpnext)
|
||||
1. [And More](https://erpnext.com/docs/user/manual/en/)
|
||||
|
||||
ERPNext requires MariaDB.
|
||||
|
||||
ERPNext is built on the [Frappe Framework](https://github.com/frappe/frappe), a full-stack web app framework built with Python & JavaScript.
|
||||
|
||||
## Installation
|
||||
- [User Guide](https://erpnext.com/docs/user)
|
||||
- [Discussion Forum](https://discuss.erpnext.com/)
|
||||
|
||||
<div align="center" style="max-height: 40px;">
|
||||
<a href="https://frappecloud.com/erpnext/signup">
|
||||
---
|
||||
|
||||
<div align="center">
|
||||
<a href="https://frappecloud.com/deploy?apps=frappe,erpnext&source=erpnext_readme">
|
||||
<img src=".github/try-on-f-cloud-button.svg" height="40">
|
||||
</a>
|
||||
<a href="https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/frappe/frappe_docker/main/pwd.yml">
|
||||
<img src="https://raw.githubusercontent.com/play-with-docker/stacks/master/assets/images/button.png" alt="Try in PWD" height="37"/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
> Login for the PWD site: (username: Administrator, password: admin)
|
||||
|
||||
### Containerized Installation
|
||||
|
||||
Use docker to deploy ERPNext in production or for development of [Frappe](https://github.com/frappe/frappe) apps. See https://github.com/frappe/frappe_docker for more details.
|
||||
|
||||
### Manual Install
|
||||
### Full Install
|
||||
|
||||
The Easy Way: our install script for bench will install all dependencies (e.g. MariaDB). See https://github.com/frappe/bench for more details.
|
||||
|
||||
New passwords will be created for the ERPNext "Administrator" user, the MariaDB root user, and the frappe user (the script displays the passwords and saves them to ~/frappe_passwords.txt).
|
||||
|
||||
|
||||
## Learning and community
|
||||
|
||||
1. [Frappe School](https://frappe.school) - Learn Frappe Framework and ERPNext from the various courses by the maintainers or from the community.
|
||||
2. [Official documentation](https://docs.erpnext.com/) - Extensive documentation for ERPNext.
|
||||
3. [Discussion Forum](https://discuss.erpnext.com/) - Engage with community of ERPNext users and service providers.
|
||||
4. [Telegram Group](https://t.me/erpnexthelp) - Get instant help from huge community of users.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
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
|
||||
|
||||
@@ -82,8 +65,57 @@ GNU/General Public License (see [license.txt](license.txt))
|
||||
|
||||
The ERPNext code is licensed as GNU General Public License (v3) and the Documentation is licensed as Creative Commons (CC-BY-SA-3.0) and the copyright is owned by Frappe Technologies Pvt Ltd (Frappe) and Contributors.
|
||||
|
||||
By contributing to ERPNext, you agree that your contributions will be licensed under its GNU General Public License (v3).
|
||||
---
|
||||
|
||||
## Logo and Trademark Policy
|
||||
## Contributing
|
||||
|
||||
Please read our [Logo and Trademark Policy](TRADEMARK_POLICY.md).
|
||||
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)
|
||||
1. [Chart of Accounts](https://charts.erpnext.com)
|
||||
|
||||
---
|
||||
|
||||
## Learning
|
||||
|
||||
1. [Frappe School](https://frappe.school) - Learn Frappe Framework and ERPNext from the various courses by the maintainers or from the community.
|
||||
|
||||
---
|
||||
|
||||
## Logo and Trademark
|
||||
|
||||
The brand name ERPNext and the logo are trademarks of Frappe Technologies Pvt. Ltd.
|
||||
|
||||
### Introduction
|
||||
|
||||
Frappe Technologies Pvt. Ltd. (Frappe) owns and oversees the trademarks for the ERPNext name and logos. We have developed this trademark usage policy with the following goals in mind:
|
||||
|
||||
- We’d like to make it easy for anyone to use the ERPNext name or logo for community-oriented efforts that help spread and improve ERPNext.
|
||||
- We’d like to make it clear how ERPNext-related businesses and projects can (and cannot) use the ERPNext name and logo.
|
||||
- We’d like to make it hard for anyone to use the ERPNext name and logo to unfairly profit from, trick or confuse people who are looking for official ERPNext resources.
|
||||
|
||||
### Frappe Trademark Usage Policy
|
||||
|
||||
Permission from Frappe is required to use the ERPNext name or logo as part of any project, product, service, domain or company name.
|
||||
|
||||
We will grant permission to use the ERPNext name and logo for projects that meet the following criteria:
|
||||
|
||||
- The primary purpose of your project is to promote the spread and improvement of the ERPNext software.
|
||||
- Your project is non-commercial in nature (it can make money to cover its costs or contribute to non-profit entities, but it cannot be run as a for-profit project or business).
|
||||
Your project neither promotes nor is associated with entities that currently fail to comply with the GPL license under which ERPNext is distributed.
|
||||
- If your project meets these criteria, you will be permitted to use the ERPNext name and logo to promote your project in any way you see fit with one exception: Please do not use ERPNext as part of a domain name.
|
||||
|
||||
Use of the ERPNext name and logo is additionally allowed in the following situations:
|
||||
|
||||
All other ERPNext-related businesses or projects can use the ERPNext name and logo to refer to and explain their services, but they cannot use them as part of a product, project, service, domain, or company name and they cannot use them in any way that suggests an affiliation with or endorsement by ERPNext or Frappe Technologies or the ERPNext open source project. For example, a consulting company can describe its business as “123 Web Services, offering ERPNext consulting for small businesses,” but cannot call its business “The ERPNext Consulting Company.”
|
||||
|
||||
Similarly, it’s OK to use the ERPNext logo as part of a page that describes your products or services, but it is not OK to use it as part of your company or product logo or branding itself. Under no circumstances is it permitted to use ERPNext as part of a top-level domain name.
|
||||
|
||||
We do not allow the use of the trademark in advertising, including AdSense/AdWords.
|
||||
|
||||
Please note that it is not the goal of this policy to limit commercial activity around ERPNext. We encourage ERPNext-based businesses, and we would love to see hundreds of them.
|
||||
|
||||
When in doubt about your use of the ERPNext name or logo, please contact Frappe Technologies for clarification.
|
||||
|
||||
(inspired by WordPress)
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
## Logo and Trademark Policy
|
||||
|
||||
The brand name ERPNext and the logo are trademarks of Frappe Technologies Pvt. Ltd.
|
||||
|
||||
### Introduction
|
||||
|
||||
Frappe Technologies Pvt. Ltd. (Frappe) owns and oversees the trademarks for the ERPNext name and logos. We have developed this trademark usage policy with the following goals in mind:
|
||||
|
||||
- We’d like to make it easy for anyone to use the ERPNext name or logo for community-oriented efforts that help spread and improve ERPNext.
|
||||
- We’d like to make it clear how ERPNext-related businesses and projects can (and cannot) use the ERPNext name and logo.
|
||||
- We’d like to make it hard for anyone to use the ERPNext name and logo to unfairly profit from, trick or confuse people who are looking for official ERPNext resources.
|
||||
|
||||
### Frappe Trademark Usage Policy
|
||||
|
||||
Permission from Frappe is required to use the ERPNext name or logo as part of any project, product, service, domain or company name.
|
||||
|
||||
We will grant permission to use the ERPNext name and logo for projects that meet the following criteria:
|
||||
|
||||
- The primary purpose of your project is to promote the spread and improvement of the ERPNext software.
|
||||
- Your project is non-commercial in nature (it can make money to cover its costs or contribute to non-profit entities, but it cannot be run as a for-profit project or business).
|
||||
Your project neither promotes nor is associated with entities that currently fail to comply with the GPL license under which ERPNext is distributed.
|
||||
- If your project meets these criteria, you will be permitted to use the ERPNext name and logo to promote your project in any way you see fit with one exception: Please do not use ERPNext as part of a domain name.
|
||||
|
||||
Use of the ERPNext name and logo is additionally allowed in the following situations:
|
||||
|
||||
All other ERPNext-related businesses or projects can use the ERPNext name and logo to refer to and explain their services, but they cannot use them as part of a product, project, service, domain, or company name and they cannot use them in any way that suggests an affiliation with or endorsement by ERPNext or Frappe Technologies or the ERPNext open source project. For example, a consulting company can describe its business as “123 Web Services, offering ERPNext consulting for small businesses,” but cannot call its business “The ERPNext Consulting Company.”
|
||||
|
||||
Similarly, it’s OK to use the ERPNext logo as part of a page that describes your products or services, but it is not OK to use it as part of your company or product logo or branding itself. Under no circumstances is it permitted to use ERPNext as part of a top-level domain name.
|
||||
|
||||
We do not allow the use of the trademark in advertising, including AdSense/AdWords.
|
||||
|
||||
Please note that it is not the goal of this policy to limit commercial activity around ERPNext. We encourage ERPNext-based businesses, and we would love to see hundreds of them.
|
||||
|
||||
When in doubt about your use of the ERPNext name or logo, please contact Frappe Technologies for clarification.
|
||||
|
||||
(inspired by WordPress)
|
||||
@@ -21,6 +21,7 @@ coverage:
|
||||
comment:
|
||||
layout: "diff, files"
|
||||
require_changes: true
|
||||
after_n_builds: 3
|
||||
|
||||
ignore:
|
||||
- "erpnext/demo"
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
module.exports = {
|
||||
parserPreset: 'conventional-changelog-conventionalcommits',
|
||||
rules: {
|
||||
'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',
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
11
cypress.json
Normal file
11
cypress.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"baseUrl": "http://test_site:8000/",
|
||||
"projectId": "da59y9",
|
||||
"adminPassword": "admin",
|
||||
"defaultCommandTimeout": 20000,
|
||||
"pageLoadTimeout": 15000,
|
||||
"retries": {
|
||||
"runMode": 2,
|
||||
"openMode": 2
|
||||
}
|
||||
}
|
||||
5
cypress/fixtures/example.json
Normal file
5
cypress/fixtures/example.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
44
cypress/integration/test_bulk_transaction_processing.js
Normal file
44
cypress/integration/test_bulk_transaction_processing.js
Normal file
@@ -0,0 +1,44 @@
|
||||
describe("Bulk Transaction Processing", () => {
|
||||
before(() => {
|
||||
cy.login();
|
||||
cy.visit("/app/website");
|
||||
});
|
||||
|
||||
it("Creates To Sales Order", () => {
|
||||
cy.visit("/app/sales-order");
|
||||
cy.url().should("include", "/sales-order");
|
||||
cy.window()
|
||||
.its("frappe.csrf_token")
|
||||
.then((csrf_token) => {
|
||||
return cy
|
||||
.request({
|
||||
url: "/api/method/erpnext.tests.ui_test_bulk_transaction_processing.create_records",
|
||||
method: "POST",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"X-Frappe-CSRF-Token": csrf_token,
|
||||
},
|
||||
timeout: 60000,
|
||||
})
|
||||
.then((res) => {
|
||||
expect(res.status).eq(200);
|
||||
});
|
||||
});
|
||||
cy.wait(5000);
|
||||
cy.get(
|
||||
".list-row-head > .list-header-subject > .list-row-col > .list-check-all"
|
||||
).check({ force: true });
|
||||
cy.wait(3000);
|
||||
cy.get(".actions-btn-group > .btn-primary").click({ force: true });
|
||||
cy.wait(3000);
|
||||
cy.get(".dropdown-menu-right > .user-action > .dropdown-item")
|
||||
.contains("Sales Invoice")
|
||||
.click({ force: true });
|
||||
cy.wait(3000);
|
||||
cy.get(".modal-content > .modal-footer > .standard-actions")
|
||||
.contains("Yes")
|
||||
.click({ force: true });
|
||||
cy.contains("Creation of Sales Invoice successful");
|
||||
});
|
||||
});
|
||||
13
cypress/integration/test_customer.js
Normal file
13
cypress/integration/test_customer.js
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
context('Customer', () => {
|
||||
before(() => {
|
||||
cy.login();
|
||||
});
|
||||
it('Check Customer Group', () => {
|
||||
cy.visit(`app/customer/`);
|
||||
cy.get('.primary-action').click();
|
||||
cy.wait(500);
|
||||
cy.get('.custom-actions > .btn').click();
|
||||
cy.get_field('customer_group', 'Link').should('have.value', 'All Customer Groups');
|
||||
});
|
||||
});
|
||||
44
cypress/integration/test_item.js
Normal file
44
cypress/integration/test_item.js
Normal file
@@ -0,0 +1,44 @@
|
||||
describe("Test Item Dashboard", () => {
|
||||
before(() => {
|
||||
cy.login();
|
||||
cy.visit("/app/item");
|
||||
cy.insert_doc(
|
||||
"Item",
|
||||
{
|
||||
item_code: "e2e_test_item",
|
||||
item_group: "All Item Groups",
|
||||
opening_stock: 42,
|
||||
valuation_rate: 100,
|
||||
},
|
||||
true
|
||||
);
|
||||
cy.go_to_doc("item", "e2e_test_item");
|
||||
});
|
||||
|
||||
it("should show dashboard with correct data on first load", () => {
|
||||
cy.get(".stock-levels").contains("Stock Levels").should("be.visible");
|
||||
cy.get(".stock-levels").contains("e2e_test_item").should("exist");
|
||||
|
||||
// reserved and available qty
|
||||
cy.get(".stock-levels .inline-graph-count")
|
||||
.eq(0)
|
||||
.contains("0")
|
||||
.should("exist");
|
||||
cy.get(".stock-levels .inline-graph-count")
|
||||
.eq(1)
|
||||
.contains("42")
|
||||
.should("exist");
|
||||
});
|
||||
|
||||
it("should persist on field change", () => {
|
||||
cy.get('input[data-fieldname="disabled"]').check();
|
||||
cy.wait(500);
|
||||
cy.get(".stock-levels").contains("Stock Levels").should("be.visible");
|
||||
cy.get(".stock-levels").should("have.length", 1);
|
||||
});
|
||||
|
||||
it("should persist on reload", () => {
|
||||
cy.reload();
|
||||
cy.get(".stock-levels").contains("Stock Levels").should("be.visible");
|
||||
});
|
||||
});
|
||||
116
cypress/integration/test_organizational_chart_desktop.js
Normal file
116
cypress/integration/test_organizational_chart_desktop.js
Normal file
@@ -0,0 +1,116 @@
|
||||
context('Organizational Chart', () => {
|
||||
before(() => {
|
||||
cy.login();
|
||||
cy.visit('/app/website');
|
||||
});
|
||||
|
||||
it('navigates to org chart', () => {
|
||||
cy.visit('/app');
|
||||
cy.visit('/app/organizational-chart');
|
||||
cy.url().should('include', '/organizational-chart');
|
||||
|
||||
cy.window().its('frappe.csrf_token').then(csrf_token => {
|
||||
return cy.request({
|
||||
url: `/api/method/erpnext.tests.ui_test_helpers.create_employee_records`,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'X-Frappe-CSRF-Token': csrf_token
|
||||
},
|
||||
timeout: 60000
|
||||
}).then(res => {
|
||||
expect(res.status).eq(200);
|
||||
cy.get('.frappe-control[data-fieldname=company] input').focus().as('input');
|
||||
cy.get('@input')
|
||||
.clear({ force: true })
|
||||
.type('Test Org Chart{downarrow}{enter}', { force: true })
|
||||
.blur({ force: true });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('renders root nodes and loads children for the first expandable node', () => {
|
||||
// check rendered root nodes and the node name, title, connections
|
||||
cy.get('.hierarchy').find('.root-level ul.node-children').children()
|
||||
.should('have.length', 2)
|
||||
.first()
|
||||
.as('first-child');
|
||||
|
||||
cy.get('@first-child').get('.node-name').contains('Test Employee 1');
|
||||
cy.get('@first-child').get('.node-info').find('.node-title').contains('CEO');
|
||||
cy.get('@first-child').get('.node-info').find('.node-connections').contains('· 2 Connections');
|
||||
|
||||
cy.call('erpnext.tests.ui_test_helpers.get_employee_records').then(employee_records => {
|
||||
// children of 1st root visible
|
||||
cy.get(`div[data-parent="${employee_records.message[0]}"]`).as('child-node');
|
||||
cy.get('@child-node')
|
||||
.should('have.length', 1)
|
||||
.should('be.visible');
|
||||
cy.get('@child-node').get('.node-name').contains('Test Employee 3');
|
||||
|
||||
// connectors between first root node and immediate child
|
||||
cy.get(`path[data-parent="${employee_records.message[0]}"]`)
|
||||
.should('be.visible')
|
||||
.invoke('attr', 'data-child')
|
||||
.should('equal', employee_records.message[2]);
|
||||
});
|
||||
});
|
||||
|
||||
it('hides active nodes children and connectors on expanding sibling node', () => {
|
||||
cy.call('erpnext.tests.ui_test_helpers.get_employee_records').then(employee_records => {
|
||||
// click sibling
|
||||
cy.get(`#${employee_records.message[1]}`)
|
||||
.click()
|
||||
.should('have.class', 'active');
|
||||
|
||||
// child nodes and connectors hidden
|
||||
cy.get(`[data-parent="${employee_records.message[0]}"]`).should('not.be.visible');
|
||||
cy.get(`path[data-parent="${employee_records.message[0]}"]`).should('not.be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
it('collapses previous level nodes and refreshes connectors on expanding child node', () => {
|
||||
cy.call('erpnext.tests.ui_test_helpers.get_employee_records').then(employee_records => {
|
||||
// click child node
|
||||
cy.get(`#${employee_records.message[3]}`)
|
||||
.click()
|
||||
.should('have.class', 'active');
|
||||
|
||||
// previous level nodes: parent should be on active-path; other nodes should be collapsed
|
||||
cy.get(`#${employee_records.message[0]}`).should('have.class', 'collapsed');
|
||||
cy.get(`#${employee_records.message[1]}`).should('have.class', 'active-path');
|
||||
|
||||
// previous level connectors refreshed
|
||||
cy.get(`path[data-parent="${employee_records.message[1]}"]`)
|
||||
.should('have.class', 'collapsed-connector');
|
||||
|
||||
// child node's children and connectors rendered
|
||||
cy.get(`[data-parent="${employee_records.message[3]}"]`).should('be.visible');
|
||||
cy.get(`path[data-parent="${employee_records.message[3]}"]`).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
it('expands previous level nodes', () => {
|
||||
cy.call('erpnext.tests.ui_test_helpers.get_employee_records').then(employee_records => {
|
||||
cy.get(`#${employee_records.message[0]}`)
|
||||
.click()
|
||||
.should('have.class', 'active');
|
||||
|
||||
cy.get(`[data-parent="${employee_records.message[0]}"]`)
|
||||
.should('be.visible');
|
||||
|
||||
cy.get('ul.hierarchy').children().should('have.length', 2);
|
||||
cy.get(`#connectors`).children().should('have.length', 1);
|
||||
});
|
||||
});
|
||||
|
||||
it('edit node navigates to employee master', () => {
|
||||
cy.call('erpnext.tests.ui_test_helpers.get_employee_records').then(employee_records => {
|
||||
cy.get(`#${employee_records.message[0]}`).find('.btn-edit-node')
|
||||
.click();
|
||||
|
||||
cy.url().should('include', `/employee/${employee_records.message[0]}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
195
cypress/integration/test_organizational_chart_mobile.js
Normal file
195
cypress/integration/test_organizational_chart_mobile.js
Normal file
@@ -0,0 +1,195 @@
|
||||
context('Organizational Chart Mobile', () => {
|
||||
before(() => {
|
||||
cy.login();
|
||||
cy.visit('/app/website');
|
||||
});
|
||||
|
||||
it('navigates to org chart', () => {
|
||||
cy.viewport(375, 667);
|
||||
cy.visit('/app');
|
||||
cy.visit('/app/organizational-chart');
|
||||
cy.url().should('include', '/organizational-chart');
|
||||
|
||||
cy.window().its('frappe.csrf_token').then(csrf_token => {
|
||||
return cy.request({
|
||||
url: `/api/method/erpnext.tests.ui_test_helpers.create_employee_records`,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'X-Frappe-CSRF-Token': csrf_token
|
||||
},
|
||||
timeout: 60000
|
||||
}).then(res => {
|
||||
expect(res.status).eq(200);
|
||||
cy.get('.frappe-control[data-fieldname=company] input').focus().as('input');
|
||||
cy.get('@input')
|
||||
.clear({ force: true })
|
||||
.type('Test Org Chart{downarrow}{enter}', { force: true })
|
||||
.blur({ force: true });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('renders root nodes', () => {
|
||||
// check rendered root nodes and the node name, title, connections
|
||||
cy.get('.hierarchy-mobile').find('.root-level').children()
|
||||
.should('have.length', 2)
|
||||
.first()
|
||||
.as('first-child');
|
||||
|
||||
cy.get('@first-child').get('.node-name').contains('Test Employee 1');
|
||||
cy.get('@first-child').get('.node-info').find('.node-title').contains('CEO');
|
||||
cy.get('@first-child').get('.node-info').find('.node-connections').contains('· 2');
|
||||
});
|
||||
|
||||
it('expands root node', () => {
|
||||
cy.call('erpnext.tests.ui_test_helpers.get_employee_records').then(employee_records => {
|
||||
cy.get(`#${employee_records.message[1]}`)
|
||||
.click()
|
||||
.should('have.class', 'active');
|
||||
|
||||
// other root node removed
|
||||
cy.get(`#${employee_records.message[0]}`).should('not.exist');
|
||||
|
||||
// children of active root node
|
||||
cy.get('.hierarchy-mobile').find('.level').first().find('ul.node-children').children()
|
||||
.should('have.length', 2);
|
||||
|
||||
cy.get(`div[data-parent="${employee_records.message[1]}"]`).first().as('child-node');
|
||||
cy.get('@child-node').should('be.visible');
|
||||
|
||||
cy.get('@child-node')
|
||||
.get('.node-name')
|
||||
.contains('Test Employee 4');
|
||||
|
||||
// connectors between root node and immediate children
|
||||
cy.get(`path[data-parent="${employee_records.message[1]}"]`).as('connectors');
|
||||
cy.get('@connectors')
|
||||
.should('have.length', 2)
|
||||
.should('be.visible');
|
||||
|
||||
cy.get('@connectors')
|
||||
.first()
|
||||
.invoke('attr', 'data-child')
|
||||
.should('eq', employee_records.message[3]);
|
||||
});
|
||||
});
|
||||
|
||||
it('expands child node', () => {
|
||||
cy.call('erpnext.tests.ui_test_helpers.get_employee_records').then(employee_records => {
|
||||
cy.get(`#${employee_records.message[3]}`)
|
||||
.click()
|
||||
.should('have.class', 'active')
|
||||
.as('expanded_node');
|
||||
|
||||
// 2 levels on screen; 1 on active path; 1 collapsed
|
||||
cy.get('.hierarchy-mobile').children().should('have.length', 2);
|
||||
cy.get(`#${employee_records.message[1]}`).should('have.class', 'active-path');
|
||||
|
||||
// children of expanded node visible
|
||||
cy.get('@expanded_node')
|
||||
.next()
|
||||
.should('have.class', 'node-children')
|
||||
.as('node-children');
|
||||
|
||||
cy.get('@node-children').children().should('have.length', 1);
|
||||
cy.get('@node-children')
|
||||
.first()
|
||||
.get('.node-card')
|
||||
.should('have.class', 'active-child')
|
||||
.contains('Test Employee 7');
|
||||
|
||||
// orphan connectors removed
|
||||
cy.get(`#connectors`).children().should('have.length', 2);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders sibling group', () => {
|
||||
cy.call('erpnext.tests.ui_test_helpers.get_employee_records').then(employee_records => {
|
||||
// sibling group visible for parent
|
||||
cy.get(`#${employee_records.message[1]}`)
|
||||
.next()
|
||||
.as('sibling_group');
|
||||
|
||||
cy.get('@sibling_group')
|
||||
.should('have.attr', 'data-parent', 'undefined')
|
||||
.should('have.class', 'node-group')
|
||||
.and('have.class', 'collapsed');
|
||||
|
||||
cy.get('@sibling_group').get('.avatar-group').children().as('siblings');
|
||||
cy.get('@siblings').should('have.length', 1);
|
||||
cy.get('@siblings')
|
||||
.first()
|
||||
.should('have.attr', 'title', 'Test Employee 1');
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
it('expands previous level nodes', () => {
|
||||
cy.call('erpnext.tests.ui_test_helpers.get_employee_records').then(employee_records => {
|
||||
cy.get(`#${employee_records.message[6]}`)
|
||||
.click()
|
||||
.should('have.class', 'active');
|
||||
|
||||
// clicking on previous level node should remove all the nodes ahead
|
||||
// and expand that node
|
||||
cy.get(`#${employee_records.message[3]}`).click();
|
||||
cy.get(`#${employee_records.message[3]}`)
|
||||
.should('have.class', 'active')
|
||||
.should('not.have.class', 'active-path');
|
||||
|
||||
cy.get(`#${employee_records.message[6]}`).should('have.class', 'active-child');
|
||||
cy.get('.hierarchy-mobile').children().should('have.length', 2);
|
||||
cy.get(`#connectors`).children().should('have.length', 2);
|
||||
});
|
||||
});
|
||||
|
||||
it('expands sibling group', () => {
|
||||
cy.call('erpnext.tests.ui_test_helpers.get_employee_records').then(employee_records => {
|
||||
// sibling group visible for parent
|
||||
cy.get(`#${employee_records.message[6]}`).click();
|
||||
|
||||
cy.get(`#${employee_records.message[3]}`)
|
||||
.next()
|
||||
.click();
|
||||
|
||||
// siblings of parent should be visible
|
||||
cy.get('.hierarchy-mobile').prev().as('sibling_group');
|
||||
cy.get('@sibling_group')
|
||||
.should('exist')
|
||||
.should('have.class', 'sibling-group')
|
||||
.should('not.have.class', 'collapsed');
|
||||
|
||||
cy.get(`#${employee_records.message[1]}`)
|
||||
.should('be.visible')
|
||||
.should('have.class', 'active');
|
||||
|
||||
cy.get(`[data-parent="${employee_records.message[1]}"]`)
|
||||
.should('be.visible')
|
||||
.should('have.length', 2)
|
||||
.should('have.class', 'active-child');
|
||||
});
|
||||
});
|
||||
|
||||
it('goes to the respective level after clicking on non-collapsed sibling group', () => {
|
||||
cy.call('erpnext.tests.ui_test_helpers.get_employee_records').then(() => {
|
||||
// click on non-collapsed sibling group
|
||||
cy.get('.hierarchy-mobile')
|
||||
.prev()
|
||||
.click();
|
||||
|
||||
// should take you to that level
|
||||
cy.get('.hierarchy-mobile').find('li.level .node-card').should('have.length', 2);
|
||||
});
|
||||
});
|
||||
|
||||
it('edit node navigates to employee master', () => {
|
||||
cy.call('erpnext.tests.ui_test_helpers.get_employee_records').then(employee_records => {
|
||||
cy.get(`#${employee_records.message[0]}`).find('.btn-edit-node')
|
||||
.click();
|
||||
|
||||
cy.url().should('include', `/employee/${employee_records.message[0]}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
17
cypress/plugins/index.js
Normal file
17
cypress/plugins/index.js
Normal file
@@ -0,0 +1,17 @@
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
module.exports = () => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
};
|
||||
31
cypress/support/commands.js
Normal file
31
cypress/support/commands.js
Normal file
@@ -0,0 +1,31 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add("login", (email, password) => { ... });
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... });
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... });
|
||||
//
|
||||
//
|
||||
// -- This is will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... });
|
||||
|
||||
const slug = (name) => name.toLowerCase().replace(" ", "-");
|
||||
|
||||
Cypress.Commands.add("go_to_doc", (doctype, name) => {
|
||||
cy.visit(`/app/${slug(doctype)}/${encodeURIComponent(name)}`);
|
||||
});
|
||||
26
cypress/support/index.js
Normal file
26
cypress/support/index.js
Normal file
@@ -0,0 +1,26 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands';
|
||||
import '../../../frappe/cypress/support/commands' // eslint-disable-line
|
||||
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
||||
Cypress.Cookies.defaults({
|
||||
preserve: 'sid'
|
||||
});
|
||||
12
cypress/tsconfig.json
Normal file
12
cypress/tsconfig.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": "../node_modules",
|
||||
"types": [
|
||||
"cypress"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.*"
|
||||
]
|
||||
}
|
||||
1
dev-requirements.txt
Normal file
1
dev-requirements.txt
Normal file
@@ -0,0 +1 @@
|
||||
hypothesis~=6.31.0
|
||||
@@ -2,7 +2,7 @@ import inspect
|
||||
|
||||
import frappe
|
||||
|
||||
__version__ = "14.0.0-dev"
|
||||
__version__ = "14.0.0-beta.4"
|
||||
|
||||
|
||||
def get_default_company(user=None):
|
||||
|
||||
@@ -11,41 +11,3 @@ Entries are:
|
||||
- Purchase Invoice (Itemised)
|
||||
|
||||
All accounting entries are stored in the `General Ledger`
|
||||
|
||||
## Payment Ledger
|
||||
Transactions on Receivable and Payable Account types will also be stored in `Payment Ledger`. This is so that payment reconciliation process only requires update on this ledger.
|
||||
|
||||
### Key Fields
|
||||
| Field | Description |
|
||||
|----------------------|----------------------------------|
|
||||
| `account_type` | Receivable/Payable |
|
||||
| `account` | Accounting head |
|
||||
| `party` | Party Name |
|
||||
| `voucher_no` | Voucher No |
|
||||
| `against_voucher_no` | Linked voucher(secondary effect) |
|
||||
| `amount` | can be +ve/-ve |
|
||||
|
||||
### Design
|
||||
`debit` and `credit` have been replaced with `account_type` and `amount`. `against_voucher_no` is populated for all entries. So, outstanding amount can be calculated by summing up amount only using `against_voucher_no`.
|
||||
|
||||
Ex:
|
||||
1. Consider an invoice for ₹100 and a partial payment of ₹80 against that invoice. Payment Ledger will have following entries.
|
||||
|
||||
| voucher_no | against_voucher_no | amount |
|
||||
|------------|--------------------|--------|
|
||||
| SINV-01 | SINV-01 | 100 |
|
||||
| PAY-01 | SINV-01 | -80 |
|
||||
|
||||
|
||||
2. Reconcile a Credit Note against an invoice using a Journal Entry
|
||||
|
||||
An invoice for ₹100 partially reconciled against a credit of ₹70 using a Journal Entry. Payment Ledger will have the following entries.
|
||||
|
||||
| voucher_no | against_voucher_no | amount |
|
||||
|------------|--------------------|--------|
|
||||
| SINV-01 | SINV-01 | 100 |
|
||||
| | | |
|
||||
| CR-NOTE-01 | CR-NOTE-01 | -70 |
|
||||
| | | |
|
||||
| JE-01 | CR-NOTE-01 | +70 |
|
||||
| JE-01 | SINV-01 | -70 |
|
||||
|
||||
@@ -76,7 +76,7 @@ def get(
|
||||
|
||||
def build_result(account, dates, gl_entries):
|
||||
result = [[getdate(date), 0.0] for date in dates]
|
||||
root_type = frappe.get_cached_value("Account", account, "root_type")
|
||||
root_type = frappe.db.get_value("Account", account, "root_type")
|
||||
|
||||
# start with the first date
|
||||
date_index = 0
|
||||
|
||||
@@ -386,6 +386,7 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
||||
doc,
|
||||
credit_account,
|
||||
debit_account,
|
||||
against,
|
||||
amount,
|
||||
base_amount,
|
||||
end_date,
|
||||
@@ -539,11 +540,19 @@ def make_gl_entries(
|
||||
frappe.db.commit()
|
||||
except Exception as e:
|
||||
if frappe.flags.in_test:
|
||||
doc.log_error(f"Error while processing deferred accounting for Invoice {doc.name}")
|
||||
traceback = frappe.get_traceback()
|
||||
frappe.log_error(
|
||||
title=_("Error while processing deferred accounting for Invoice {0}").format(doc.name),
|
||||
message=traceback,
|
||||
)
|
||||
raise e
|
||||
else:
|
||||
frappe.db.rollback()
|
||||
doc.log_error(f"Error while processing deferred accounting for Invoice {doc.name}")
|
||||
traceback = frappe.get_traceback()
|
||||
frappe.log_error(
|
||||
title=_("Error while processing deferred accounting for Invoice {0}").format(doc.name),
|
||||
message=traceback,
|
||||
)
|
||||
frappe.flags.deferred_accounting_error = True
|
||||
|
||||
|
||||
@@ -561,6 +570,7 @@ def book_revenue_via_journal_entry(
|
||||
doc,
|
||||
credit_account,
|
||||
debit_account,
|
||||
against,
|
||||
amount,
|
||||
base_amount,
|
||||
posting_date,
|
||||
@@ -581,7 +591,6 @@ def book_revenue_via_journal_entry(
|
||||
journal_entry.voucher_type = (
|
||||
"Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense"
|
||||
)
|
||||
journal_entry.process_deferred_accounting = deferred_process
|
||||
|
||||
debit_entry = {
|
||||
"account": credit_account,
|
||||
@@ -624,7 +633,12 @@ def book_revenue_via_journal_entry(
|
||||
frappe.db.commit()
|
||||
except Exception:
|
||||
frappe.db.rollback()
|
||||
doc.log_error(f"Error while processing deferred accounting for Invoice {doc.name}")
|
||||
traceback = frappe.get_traceback()
|
||||
frappe.log_error(
|
||||
title=_("Error while processing deferred accounting for Invoice {0}").format(doc.name),
|
||||
message=traceback,
|
||||
)
|
||||
|
||||
frappe.flags.deferred_accounting_error = True
|
||||
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class Account(NestedSet):
|
||||
def autoname(self):
|
||||
from erpnext.accounts.utils import get_autoname_with_number
|
||||
|
||||
self.name = get_autoname_with_number(self.account_number, self.account_name, self.company)
|
||||
self.name = get_autoname_with_number(self.account_number, self.account_name, None, self.company)
|
||||
|
||||
def validate(self):
|
||||
from erpnext.accounts.utils import validate_field_number
|
||||
@@ -58,7 +58,7 @@ class Account(NestedSet):
|
||||
def validate_parent(self):
|
||||
"""Fetch Parent Details and validate parent account"""
|
||||
if self.parent_account:
|
||||
par = frappe.get_cached_value(
|
||||
par = frappe.db.get_value(
|
||||
"Account", self.parent_account, ["name", "is_group", "company"], as_dict=1
|
||||
)
|
||||
if not par:
|
||||
@@ -82,7 +82,7 @@ class Account(NestedSet):
|
||||
|
||||
def set_root_and_report_type(self):
|
||||
if self.parent_account:
|
||||
par = frappe.get_cached_value(
|
||||
par = frappe.db.get_value(
|
||||
"Account", self.parent_account, ["report_type", "root_type"], as_dict=1
|
||||
)
|
||||
|
||||
@@ -92,7 +92,7 @@ class Account(NestedSet):
|
||||
self.root_type = par.root_type
|
||||
|
||||
if self.is_group:
|
||||
db_value = self.get_doc_before_save()
|
||||
db_value = frappe.db.get_value("Account", self.name, ["report_type", "root_type"], as_dict=1)
|
||||
if db_value:
|
||||
if self.report_type != db_value.report_type:
|
||||
frappe.db.sql(
|
||||
@@ -111,13 +111,13 @@ class Account(NestedSet):
|
||||
)
|
||||
|
||||
def validate_root_details(self):
|
||||
doc_before_save = self.get_doc_before_save()
|
||||
|
||||
if doc_before_save and not doc_before_save.parent_account:
|
||||
# does not exists parent
|
||||
if frappe.db.exists("Account", self.name):
|
||||
if not frappe.db.get_value("Account", self.name, "parent_account"):
|
||||
throw(_("Root cannot be edited."), RootNotEditable)
|
||||
|
||||
if not self.parent_account and not self.is_group:
|
||||
throw(_("The root account {0} must be a group").format(frappe.bold(self.name)))
|
||||
frappe.throw(_("The root account {0} must be a group").format(frappe.bold(self.name)))
|
||||
|
||||
def validate_root_company_and_sync_account_to_children(self):
|
||||
# ignore validation while creating new compnay or while syncing to child companies
|
||||
@@ -127,9 +127,7 @@ class Account(NestedSet):
|
||||
return
|
||||
ancestors = get_root_company(self.company)
|
||||
if ancestors:
|
||||
if frappe.get_cached_value(
|
||||
"Company", self.company, "allow_account_creation_against_child_company"
|
||||
):
|
||||
if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"):
|
||||
return
|
||||
if not frappe.db.get_value(
|
||||
"Account", {"account_name": self.account_name, "company": ancestors[0]}, "name"
|
||||
@@ -140,7 +138,7 @@ class Account(NestedSet):
|
||||
if not descendants:
|
||||
return
|
||||
parent_acc_name_map = {}
|
||||
parent_acc_name, parent_acc_number = frappe.get_cached_value(
|
||||
parent_acc_name, parent_acc_number = frappe.db.get_value(
|
||||
"Account", self.parent_account, ["account_name", "account_number"]
|
||||
)
|
||||
filters = {
|
||||
@@ -161,10 +159,11 @@ class Account(NestedSet):
|
||||
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
|
||||
|
||||
def validate_group_or_ledger(self):
|
||||
doc_before_save = self.get_doc_before_save()
|
||||
if not doc_before_save or cint(doc_before_save.is_group) == cint(self.is_group):
|
||||
if self.get("__islocal"):
|
||||
return
|
||||
|
||||
existing_is_group = frappe.db.get_value("Account", self.name, "is_group")
|
||||
if cint(self.is_group) != cint(existing_is_group):
|
||||
if self.check_gle_exists():
|
||||
throw(_("Account with existing transaction cannot be converted to ledger"))
|
||||
elif self.is_group:
|
||||
@@ -174,12 +173,10 @@ class Account(NestedSet):
|
||||
throw(_("Account with child nodes cannot be set as ledger"))
|
||||
|
||||
def validate_frozen_accounts_modifier(self):
|
||||
doc_before_save = self.get_doc_before_save()
|
||||
if not doc_before_save or doc_before_save.freeze_account == self.freeze_account:
|
||||
return
|
||||
|
||||
frozen_accounts_modifier = frappe.get_cached_value(
|
||||
"Accounts Settings", "Accounts Settings", "frozen_accounts_modifier"
|
||||
old_value = frappe.db.get_value("Account", self.name, "freeze_account")
|
||||
if old_value and old_value != self.freeze_account:
|
||||
frozen_accounts_modifier = frappe.db.get_value(
|
||||
"Accounts Settings", None, "frozen_accounts_modifier"
|
||||
)
|
||||
if not frozen_accounts_modifier or frozen_accounts_modifier not in frappe.get_roles():
|
||||
throw(_("You are not authorized to set Frozen value"))
|
||||
@@ -226,9 +223,9 @@ class Account(NestedSet):
|
||||
)
|
||||
|
||||
# validate if parent of child company account to be added is a group
|
||||
if frappe.get_cached_value(
|
||||
"Account", self.parent_account, "is_group"
|
||||
) and not frappe.get_cached_value("Account", parent_acc_name_map[company], "is_group"):
|
||||
if frappe.db.get_value("Account", self.parent_account, "is_group") and not frappe.db.get_value(
|
||||
"Account", parent_acc_name_map[company], "is_group"
|
||||
):
|
||||
msg = _(
|
||||
"While creating account for Child Company {0}, parent account {1} found as a ledger account."
|
||||
).format(company_bold, parent_acc_name_bold)
|
||||
@@ -325,9 +322,9 @@ 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 = %s
|
||||
and %s like %s order by name limit %s offset %s"""
|
||||
and %s like %s order by name limit %s, %s"""
|
||||
% ("%s", searchfield, "%s", "%s", "%s"),
|
||||
(filters["company"], "%%%s%%" % txt, page_len, start),
|
||||
(filters["company"], "%%%s%%" % txt, start, page_len),
|
||||
as_list=1,
|
||||
)
|
||||
|
||||
@@ -380,15 +377,17 @@ def validate_account_number(name, account_number, company):
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_account_number(name, account_name, account_number=None, from_descendant=False):
|
||||
account = frappe.get_cached_doc("Account", name)
|
||||
account = frappe.db.get_value("Account", name, "company", as_dict=True)
|
||||
if not account:
|
||||
return
|
||||
|
||||
old_acc_name, old_acc_number = account.account_name, account.account_number
|
||||
old_acc_name, old_acc_number = frappe.db.get_value(
|
||||
"Account", name, ["account_name", "account_number"]
|
||||
)
|
||||
|
||||
# check if account exists in parent company
|
||||
ancestors = get_ancestors_of("Company", account.company)
|
||||
allow_independent_account_creation = frappe.get_cached_value(
|
||||
allow_independent_account_creation = frappe.get_value(
|
||||
"Company", account.company, "allow_account_creation_against_child_company"
|
||||
)
|
||||
|
||||
@@ -436,24 +435,22 @@ def update_account_number(name, account_name, account_number=None, from_descenda
|
||||
@frappe.whitelist()
|
||||
def merge_account(old, new, is_group, root_type, company):
|
||||
# Validate properties before merging
|
||||
new_account = frappe.get_cached_doc("Account", new)
|
||||
|
||||
if not new_account:
|
||||
if not frappe.db.exists("Account", new):
|
||||
throw(_("Account {0} does not exist").format(new))
|
||||
|
||||
if (new_account.is_group, new_account.root_type, new_account.company) != (
|
||||
cint(is_group),
|
||||
root_type,
|
||||
company,
|
||||
):
|
||||
val = list(frappe.db.get_value("Account", new, ["is_group", "root_type", "company"]))
|
||||
|
||||
if val != [cint(is_group), root_type, company]:
|
||||
throw(
|
||||
_(
|
||||
"""Merging is only possible if following properties are same in both records. Is Group, Root Type, Company"""
|
||||
)
|
||||
)
|
||||
|
||||
if is_group and new_account.parent_account == old:
|
||||
new_account.db_set("parent_account", frappe.get_cached_value("Account", old, "parent_account"))
|
||||
if is_group and frappe.db.get_value("Account", new, "parent_account") == old:
|
||||
frappe.db.set_value(
|
||||
"Account", new, "parent_account", frappe.db.get_value("Account", old, "parent_account")
|
||||
)
|
||||
|
||||
frappe.rename_doc("Account", old, new, merge=1, force=1)
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ def create_charts(
|
||||
"account_number": account_number,
|
||||
"account_type": child.get("account_type"),
|
||||
"account_currency": child.get("account_currency")
|
||||
or frappe.get_cached_value("Company", company, "default_currency"),
|
||||
or frappe.db.get_value("Company", company, "default_currency"),
|
||||
"tax_rate": child.get("tax_rate"),
|
||||
}
|
||||
)
|
||||
@@ -148,7 +148,7 @@ def get_charts_for_country(country, with_standard=False):
|
||||
) or frappe.local.flags.allow_unverified_charts:
|
||||
charts.append(content["name"])
|
||||
|
||||
country_code = frappe.get_cached_value("Country", country, "code")
|
||||
country_code = frappe.db.get_value("Country", country, "code")
|
||||
if country_code:
|
||||
folders = ("verified",)
|
||||
if frappe.local.flags.allow_unverified_charts:
|
||||
|
||||
@@ -2,438 +2,397 @@
|
||||
"country_code": "at",
|
||||
"name": "Austria - Chart of Accounts",
|
||||
"tree": {
|
||||
"Klasse 0 Aktiva: Anlageverm\u00f6gen": {
|
||||
"0100 Konzessionen ": {"account_type": "Fixed Asset"},
|
||||
"0110 Patentrechte und Lizenzen ": {"account_type": "Fixed Asset"},
|
||||
"0120 Datenverarbeitungsprogramme ": {"account_type": "Fixed Asset"},
|
||||
"0130 Marken, Warenzeichen und Musterschutzrechte, sonstige Urheberrechte ": {"account_type": "Fixed Asset"},
|
||||
"0140 Pacht- und Mietrechte ": {"account_type": "Fixed Asset"},
|
||||
"0150 Bezugs- und ähnliche Rechte ": {"account_type": "Fixed Asset"},
|
||||
"0160 Geschäfts-/Firmenwert ": {"account_type": "Fixed Asset"},
|
||||
"0170 Umgründungsmehrwert ": {"account_type": "Fixed Asset"},
|
||||
"0180 Geleistete Anzahlungen auf immaterielle Vermögensgegenstände": {"account_type": "Fixed Asset"},
|
||||
"0190 Kumulierte Abschreibungen zu immateriellen Vermögensgegenständen ": {"account_type": "Fixed Asset"},
|
||||
"0200 Unbebaute Grundstücke, soweit nicht landwirtschaftlich genutzt ": {"account_type": "Fixed Asset"},
|
||||
"0210 Bebaute Grundstücke (Grundwert) ": {"account_type": "Fixed Asset"},
|
||||
"0220 Landwirtschaftlich genutzte Grundstücke ": {"account_type": "Fixed Asset"},
|
||||
"0230 Grundstücksgleiche Rechte ": {"account_type": "Fixed Asset"},
|
||||
"0300 Betriebs- und Geschäftsgebäude auf eigenem Grund ": {"account_type": "Fixed Asset"},
|
||||
"0310 Wohn- und Sozialgebäude auf eigenem Grund ": {"account_type": "Fixed Asset"},
|
||||
"0320 Betriebs- und Geschäftsgebäude auf fremdem Grund ": {"account_type": "Fixed Asset"},
|
||||
"0330 Wohn- und Sozialgebäude auf fremdem Grund ": {"account_type": "Fixed Asset"},
|
||||
"0340 Grundstückseinrichtungen auf eigenem Grund ": {"account_type": "Fixed Asset"},
|
||||
"0350 Grundstückseinrichtungen auf fremdem Grund ": {"account_type": "Fixed Asset"},
|
||||
"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"},
|
||||
"0500 Maschinenwerkzeuge ": {"account_type": "Fixed Asset"},
|
||||
"0510 Allgemeine Werkzeuge und Handwerkzeuge ": {"account_type": "Fixed Asset"},
|
||||
"0520 Prototypen, Formen, Modelle ": {"account_type": "Fixed Asset"},
|
||||
"0530 Andere Erzeugungshilfsmittel (auch Softwarewerkzeuge)": {"account_type": "Fixed Asset"},
|
||||
"0540 Hebezeuge und Montageanlagen ": {"account_type": "Fixed Asset"},
|
||||
"0550 Geringwertige Vermögensgegenstände, soweit im Erzeugungsprozess ": {"account_type": "Fixed Asset"},
|
||||
"0560 Festwerte technische Anlagen und Maschinen ": {"account_type": "Fixed Asset"},
|
||||
"0590 Kumulierte Abschreibungen zu technischen Anlagen und Maschinen ": {"account_type": "Fixed Asset"},
|
||||
"0600 Betriebs- und Geschäftsausstattung, soweit nicht gesondert angeführt ": {"account_type": "Fixed Asset"},
|
||||
"0610 Andere Anlagen, soweit nicht gesondert angeführt ": {"account_type": "Fixed Asset"},
|
||||
"0620 Büromaschinen, EDV-Anlagen ": {"account_type": "Fixed Asset"},
|
||||
"0630 PKW und Kombis ": {"account_type": "Fixed Asset"},
|
||||
"0640 LKW ": {"account_type": "Fixed Asset"},
|
||||
"0650 Andere Beförderungsmittel ": {"account_type": "Fixed Asset"},
|
||||
"0660 Gebinde ": {"account_type": "Fixed Asset"},
|
||||
"0670 Geringwertige Vermögensgegenstände, soweit nicht im Erzeugungssprozess verwendet": {"account_type": "Fixed Asset"},
|
||||
"0680 Festwerte außer technische Anlagen und Maschinen ": {"account_type": "Fixed Asset"},
|
||||
"0690 Kumulierte Abschreibungen zu anderen Anlagen, Betriebs- und Geschäftsausstattung": {"account_type": "Fixed Asset"},
|
||||
"0700 Geleistete Anzahlungen auf Sachanlagen ": {"account_type": "Fixed Asset"},
|
||||
"0710 Anlagen in Bau ": {"account_type": "Fixed Asset"},
|
||||
"0790 Kumulierte Abschreibungen zu geleisteten Anzahlungen auf Sachanlagen ": {"account_type": "Fixed Asset"},
|
||||
"0800 Anteile an verbundenen Unternehmen ": {"account_type": "Fixed Asset"},
|
||||
"0810 Beteiligungen an Gemeinschaftsunternehmen ": {"account_type": "Fixed Asset"},
|
||||
"0820 Beteiligungen an angeschlossenen (assoziierten) Unternehmen ": {"account_type": "Fixed Asset"},
|
||||
"0830 Eigene Anteile, Anteile an herrschenden oder mit Mehrheit beteiligten ": {"account_type": "Fixed Asset"},
|
||||
"0840 Sonstige Beteiligungen ": {"account_type": "Fixed Asset"},
|
||||
"0850 Ausleihungen an verbundene Unternehmen ": {"account_type": "Fixed Asset"},
|
||||
"0860 Ausleihungen an Unternehmen mit Beteiligungsverhältnis": {"account_type": "Fixed Asset"},
|
||||
"0870 Ausleihungen an Gesellschafter ": {"account_type": "Fixed Asset"},
|
||||
"0880 Sonstige Ausleihungen ": {"account_type": "Fixed Asset"},
|
||||
"0890 Anteile an Kapitalgesellschaften ohne Beteiligungscharakter ": {"account_type": "Fixed Asset"},
|
||||
"0900 Anteile an Personengesellschaften ohne Beteiligungscharakter ": {"account_type": "Fixed Asset"},
|
||||
"0910 Genossenschaftsanteile ohne Beteiligungscharakter ": {"account_type": "Fixed Asset"},
|
||||
"0920 Anteile an Investmentfonds ": {"account_type": "Fixed Asset"},
|
||||
"0930 Festverzinsliche Wertpapiere des Anlagevermögens ": {"account_type": "Fixed Asset"},
|
||||
"0980 Geleistete Anzahlungen auf Finanzanlagen ": {"account_type": "Fixed Asset"},
|
||||
"0990 Kumulierte Abschreibungen zu Finanzanlagen ": {"account_type": "Fixed Asset"},
|
||||
"root_type": "Asset"
|
||||
"Summe Abschreibungen und Aufwendungen": {
|
||||
"7010 bis 7080 Abschreibungen auf das Anlageverm\u00f6gen (ausgenommen Finanzanlagen)": {},
|
||||
"7100 bis 7190 Sonstige Steuern": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"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"},
|
||||
"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"
|
||||
"7200 bis 7290 Instandhaltung u. Reinigung durh Dritte, Entsorgung, Beleuchtung": {},
|
||||
"7300 bis 7310 Transporte durch Dritte": {},
|
||||
"7320 bis 7330 Kfz - Aufwand": {},
|
||||
"7340 bis 7350 Reise- und Fahraufwand": {},
|
||||
"7360 bis 7370 Tag- und N\u00e4chtigungsgelder": {},
|
||||
"7380 bis 7390 Nachrichtenaufwand": {},
|
||||
"7400 bis 7430 Miet- und Pachtaufwand": {},
|
||||
"7440 bis 7470 Leasingaufwand": {},
|
||||
"7480 bis 7490 Lizenzaufwand": {},
|
||||
"7500 bis 7530 Aufwand f\u00fcr beigestelltes Personal": {},
|
||||
"7540 bis 7570 Provisionen an Dritte": {},
|
||||
"7580 bis 7590 Aufsichtsratsverg\u00fctungen": {},
|
||||
"7610 bis 7620 Druckerzeugnisse und Vervielf\u00e4ltigungen": {},
|
||||
"7650 bis 7680 Werbung und Repr\u00e4sentationen": {},
|
||||
"7700 bis 7740 Versicherungen": {},
|
||||
"7750 bis 7760 Beratungs- und Pr\u00fcfungsaufwand": {},
|
||||
"7800 bis 7810 Schadensf\u00e4lle": {},
|
||||
"7840 bis 7880 Verschiedene betriebliche Aufwendungen": {},
|
||||
"7910 bis 7950 Aufwandsstellenrechung der Hersteller": {},
|
||||
"Abschreibungen auf aktivierte Aufwendungen f\u00fcr das Ingangs. u. Erweitern des Betriebes": {},
|
||||
"Abschreibungen vom Umlaufverm\u00f6gen, soweit diese die im Unternehmen \u00fcblichen Abschreibungen \u00fcbersteigen": {},
|
||||
"Aufwandsstellenrechnung": {},
|
||||
"Aus- und Fortbildung": {},
|
||||
"Buchwert abgegangener Anlagen, ausgenommen Finanzanlagen": {},
|
||||
"B\u00fcromaterial und Drucksorten": {},
|
||||
"Fachliteratur und Zeitungen ": {},
|
||||
"Herstellungskosten der zur Erzielung der Umsatzerl\u00f6se erbrachten Leistungen": {},
|
||||
"Mitgliedsbeitr\u00e4ge": {},
|
||||
"Skontoertr\u00e4ge auf sonstige betriebliche Aufwendungen": {},
|
||||
"Sonstige betrieblichen Aufwendungen": {},
|
||||
"Spenden und Trinkgelder": {},
|
||||
"Spesen des Geldverkehrs": {},
|
||||
"Verluste aus dem Abgang vom Anlageverm\u00f6gen, ausgenommen Finanzanlagen": {},
|
||||
"Vertriebskosten": {},
|
||||
"Verwaltungskosten": {},
|
||||
"root_type": "Expense"
|
||||
},
|
||||
"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"},
|
||||
"3110 Verbindlichkeiten gegen\u00fcber Bank": {"account_type": "Payable"},
|
||||
"3150 Verbindlichkeiten Darlehen": {"account_type": "Payable"},
|
||||
"3185 Verbindlichkeiten Kreditkarte": {"account_type": "Payable"},
|
||||
"3380 Verbindlichkeiten aus der Annahme gezogener Wechsel u. d. Ausstellungen eigener Wechsel": {
|
||||
"Summe Betriebliche Ertr\u00e4ge": {
|
||||
"4400 bis 4490 Erl\u00f6sschm\u00e4lerungen": {},
|
||||
"4500 bis 4570 Ver\u00e4nderungen des Bestandes an fertigen und unfertigen Erzeugn. sowie an noch nicht abrechenbaren Leistungen": {},
|
||||
"4580 bis 4590 andere aktivierte Eigenleistungen": {},
|
||||
"4600 bis 4620 Erl\u00f6se aus dem Abgang vom Anlageverm\u00f6gen, ausgen. Finanzanlagen": {},
|
||||
"4630 bis 4650 Ertr\u00e4ge aus dem Abgang vom Anlageverm\u00f6gen, ausgen. Finanzanlagen": {},
|
||||
"4660 bis 4670 Ertr\u00e4ge aus der Zuschreibung zum Anlageverm\u00f6gen, ausgen. Finanzanlagen": {},
|
||||
"4700 bis 4790 Ertr\u00e4ge aus der Aufl\u00f6sung von R\u00fcckstellungen": {},
|
||||
"4800 bis 4990 \u00dcbrige betriebliche Ertr\u00e4ge": {},
|
||||
"Erl\u00f6se 0 % Ausfuhrlieferungen/Drittl\u00e4nder": {},
|
||||
"Erl\u00f6se 10 %": {},
|
||||
"Erl\u00f6se 20 %": {},
|
||||
"Erl\u00f6se aus im Inland stpfl. EG Lieferungen 10 % USt": {},
|
||||
"Erl\u00f6se aus im Inland stpfl. EG Lieferungen 20 % USt": {},
|
||||
"Erl\u00f6se i.g. Lieferungen (stfr)": {},
|
||||
"root_type": "Income"
|
||||
},
|
||||
"Summe Eigenkapital R\u00fccklagen Abschlusskonten": {
|
||||
"9000 bis 9180 Gezeichnetes bzw. gewidmetes Kapital": {
|
||||
"account_type": "Equity"
|
||||
},
|
||||
"9200 bis 9290 Kapitalr\u00fccklagen": {
|
||||
"account_type": "Equity"
|
||||
},
|
||||
"9300 bis 9380 Gewinnr\u00fccklagen": {
|
||||
"account_type": "Equity"
|
||||
},
|
||||
"9400 bis 9590 Bewertungsreserven uns sonst. unversteuerte R\u00fccklagen": {
|
||||
"account_type": "Equity"
|
||||
},
|
||||
"9600 bis 9690 Privat und Verrechnungskonten bei Einzelunternehmen und Personengesellschaften": {},
|
||||
"9700 bis 9790 Einlagen stiller Gesellschafter ": {},
|
||||
"9900 bis 9999 Evidenzkonten": {},
|
||||
"Bilanzgewinn (-verlust )": {
|
||||
"account_type": "Equity"
|
||||
},
|
||||
"Er\u00f6ffnungsbilanz": {},
|
||||
"Gewinn- und Verlustrechnung": {},
|
||||
"Schlussbilanz": {},
|
||||
"nicht eingeforderte ausstehende Einlagen": {
|
||||
"account_type": "Equity"
|
||||
},
|
||||
"root_type": "Equity"
|
||||
},
|
||||
"Summe Finanzertr\u00e4ge und Aufwendungen": {
|
||||
"8000 bis 8040 Ertr\u00e4ge aus Beteiligungen": {},
|
||||
"8050 bis 8090 Ertr\u00e4ge aus anderen Wertpapieren und Ausleihungen des Finanzanlageverm\u00f6gens": {},
|
||||
"8100 bis 8130 Sonstige Zinsen und \u00e4hnliche Ertr\u00e4ge": {},
|
||||
"8220 bis 8250 Aufwendungen aus Beteiligungen": {},
|
||||
"8260 bis 8270 Aufwendungen aus sonst. Fiananzanlagen und aus Wertpapieren des Umlaufverm\u00f6gens": {},
|
||||
"8280 bis 8340 Zinsen und \u00e4hnliche Aufwendungem": {},
|
||||
"8400 bis 8440 Au\u00dferordentliche Ertr\u00e4ge": {},
|
||||
"8450 bis 8490 Au\u00dferordentliche Aufwendungen": {},
|
||||
"8500 bis 8590 Steuern vom Einkommen und vom Ertrag": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"8600 bis 8690 Aufl\u00f6sung unversteuerten R\u00fccklagen": {},
|
||||
"8700 bis 8740 Aufl\u00f6sung von Kapitalr\u00fccklagen": {},
|
||||
"8750 bis 8790 Aufl\u00f6sung von Gewinnr\u00fccklagen": {},
|
||||
"8800 bis 8890 Zuweisung von unversteuerten R\u00fccklagen": {},
|
||||
"Buchwert abgegangener Beteiligungen": {},
|
||||
"Buchwert abgegangener Wertpapiere des Umlaufverm\u00f6gens": {},
|
||||
"Buchwert abgegangener sonstiger Finanzanlagen": {},
|
||||
"Erl\u00f6se aus dem Abgang von Beteiligungen": {},
|
||||
"Erl\u00f6se aus dem Abgang von Wertpapieren des Umlaufverm\u00f6gens": {},
|
||||
"Erl\u00f6se aus dem Abgang von sonstigen Finanzanlagen": {},
|
||||
"Ertr\u00e4ge aus dem Abgang von und der Zuschreibung zu Finanzanlagen": {},
|
||||
"Ertr\u00e4ge aus dem Abgang von und der Zuschreibung zu Wertpapieren des Umlaufverm\u00f6gens": {},
|
||||
"Gewinabfuhr bzw. Verlust\u00fcberrechnung aus Ergebnisabf\u00fchrungsvertr\u00e4gen": {},
|
||||
"nicht ausgenutzte Lieferantenskonti": {},
|
||||
"root_type": "Income"
|
||||
},
|
||||
"Summe Fremdkapital": {
|
||||
"3020 bis 3030 Steuerr\u00fcckstellungen": {},
|
||||
"3040 bis 3090 Sonstige R\u00fcckstellungen": {},
|
||||
"3110 bis 3170 Verbindlichkeiten gegen\u00fcber Kredidinstituten": {},
|
||||
"3180 bis 3190 Verbindlichkeiten gegen\u00fcber Finanzinstituten": {},
|
||||
"3380 bis 3390 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"},
|
||||
"3600 Verbindlichkeiten Sozialversicherung": {"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"},
|
||||
"3200 Erhaltene Anzahlungen auf Bestellungen": {"account_type": "Payable"},
|
||||
"3040 R\u00fcckstellungen f\u00fcr Abfertigung": {"account_type": "Payable"},
|
||||
|
||||
"3530 USt. \u00a719 (reverse charge)": {
|
||||
"3400 bis 3470 Verbindlichkeiten gegen\u00fc. verb. Untern., Verbindl. gegen\u00fc. Untern., mit denen eine Beteiligungsverh\u00e4lnis besteht": {},
|
||||
"3600 bis 3690 Verbindlichkeiten im Rahmen der sozialen Sicherheit": {},
|
||||
"3700 bis 3890 \u00dcbrige sonstige Verbindlichkeiten": {},
|
||||
"3900 bis 3990 Passive Rechnungsabgrenzungsposten": {},
|
||||
"Anleihen (einschlie\u00dflich konvertibler)": {},
|
||||
"Erhaltene Anzahlungenauf Bestellungen": {},
|
||||
"R\u00fcckstellungen f\u00fcr Abfertigung": {},
|
||||
"R\u00fcckstellungen f\u00fcr Pensionen": {},
|
||||
"USt. \u00a719 /art (reverse charge)": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"3500 Verbindlichkeiten aus Umsatzsteuer": {"account_type": "Tax"},
|
||||
"3580 Umsatzsteuer Zahllast": {
|
||||
"Umsatzsteuer": {},
|
||||
"Umsatzsteuer Zahllast": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"3510 Umsatzsteuer Inland 20%": {
|
||||
"Umsatzsteuer aus i.g. Erwerb 10%": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"3515 Umsatzsteuer Inland 10%": {
|
||||
"Umsatzsteuer aus i.g. Erwerb 20%": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"3520 Umsatzsteuer aus i.g. Erwerb 20%": {
|
||||
"Umsatzsteuer aus i.g. Lieferungen 10%": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"3525 Umsatzsteuer aus i.g. Erwerb 10%": {
|
||||
"Umsatzsteuer aus i.g. Lieferungen 20%": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"3560 Umsatzsteuer-Evidenzkonto f\u00fcr erhaltene Anzahlungen auf Bestellungen": {},
|
||||
"3360 Verbindlichkeiten aus Lieferungen u. Leistungen EU": {
|
||||
"Umsatzsteuer-Evidenzkonto f\u00fcr erhaltene Anzahlungen auf Bestellungen": {},
|
||||
"Verbindlichkeiten aus Lieferungen u. Leistungen EU": {
|
||||
"account_type": "Payable"
|
||||
},
|
||||
"3000 Verbindlichkeiten aus Lieferungen u. Leistungen Inland": {
|
||||
"Verbindlichkeiten aus Lieferungen u. Leistungen Inland": {
|
||||
"account_type": "Payable"
|
||||
},
|
||||
"3370 Verbindlichkeiten aus Lieferungen u. Leistungen sonst. Ausland": {
|
||||
"Verbindlichkeiten aus Lieferungen u. Leistungen sonst. Ausland": {
|
||||
"account_type": "Payable"
|
||||
},
|
||||
"3400 Verbindlichkeiten gegen\u00fcber verbundenen Unternehmen": {},
|
||||
"3570 Verrechnung Finanzamt": {
|
||||
"Verbindlichkeiten gegen\u00fcber Gesellschaften": {},
|
||||
"Verrechnung Finanzamt": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"root_type": "Liability"
|
||||
},
|
||||
"Klasse 2 Aktiva: Umlaufverm\u00f6gen, Rechnungsabgrenzungen": {
|
||||
"2030 Forderungen aus Lieferungen und Leistungen Inland (0% USt, umsatzsteuerfrei)": {
|
||||
"Summe Kontoklasse 0 Anlageverm\u00f6gen": {
|
||||
"44 bis 49 Sonstige Maschinen und maschinelle Anlagen": {},
|
||||
"920 bis 930 Festverzinsliche Wertpapiere des Anlageverm\u00f6gens": {},
|
||||
"940 bis 970 Sonstige Finanzanlagen, Wertrechte": {},
|
||||
"Allgemeine Werkzeuge und Handwerkzeuge": {},
|
||||
"Andere Bef\u00f6rderungsmittel": {},
|
||||
"Andere Betriebs- und Gesch\u00e4ftsausstattung": {},
|
||||
"Andere Erzeugungshilfsmittel": {},
|
||||
"Anlagen im Bau": {},
|
||||
"Anteile an Investmentfonds": {},
|
||||
"Anteile an Kapitalgesellschaften ohne Beteiligungscharakter": {},
|
||||
"Anteile an Personengesellschaften ohne Beteiligungscharakter": {},
|
||||
"Anteile an verbundenen Unternehmen": {},
|
||||
"Antriebsmaschinen": {},
|
||||
"Aufwendungen f\u00fcs das Ingangssetzen u. Erweitern eines Betriebes": {},
|
||||
"Ausleihungen an verbundene Unternehmen": {},
|
||||
"Ausleihungen an verbundene Unternehmen, mit denen ein Beteiligungsverh\u00e4lnis besteht": {},
|
||||
"Bauliche Investitionen in fremden (gepachteten) Betriebs- und Gesch\u00e4ftsgeb\u00e4uden": {},
|
||||
"Bauliche Investitionen in fremden (gepachteten) Wohn- und Sozialgeb\u00e4uden": {},
|
||||
"Bebaute Grundst\u00fccke (Grundwert)": {},
|
||||
"Beheizungs- und Beleuchtungsanlagen": {},
|
||||
"Beteiligungen an Gemeinschaftunternehmen": {},
|
||||
"Beteiligungen an angeschlossenen (assoziierten) Unternehmen": {},
|
||||
"Betriebs- und Gesch\u00e4ftsgeb\u00e4ude auf eigenem Grund": {},
|
||||
"Betriebs- und Gesch\u00e4ftsgeb\u00e4ude auf fremdem Grund": {},
|
||||
"B\u00fcromaschinen, EDV - Anlagen": {},
|
||||
"Datenverarbeitungsprogramme": {},
|
||||
"Energieversorgungsanlagen": {},
|
||||
"Fertigungsmaschinen": {},
|
||||
"Gebinde": {},
|
||||
"Geleistete Anzahlungen": {},
|
||||
"Genossenschaften ohne Beteiligungscharakter": {},
|
||||
"Geringwertige Verm\u00f6gensgegenst\u00e4nde, soweit im Erzeugerprozess verwendet": {},
|
||||
"Geringwertige Verm\u00f6gensgegenst\u00e4nde, soweit nicht im Erzeugungsprozess verwendet": {},
|
||||
"Gesch\u00e4fts(Firmen)wert": {},
|
||||
"Grundst\u00fcckseinrichtunten auf eigenem Grund": {},
|
||||
"Grundst\u00fcckseinrichtunten auf fremdem Grund": {},
|
||||
"Grundst\u00fccksgleiche Rechte": {},
|
||||
"Hebezeuge und Montageanlagen": {},
|
||||
"Konzessionen": {},
|
||||
"Kumulierte Abschreibungen": {},
|
||||
"LKW": {},
|
||||
"Marken, Warenzeichen und Musterschutzrechte": {},
|
||||
"Maschinenwerkzeuge": {},
|
||||
"Nachrichten- und Kontrollanlagen": {},
|
||||
"PKW": {},
|
||||
"Pacht- und Mietrechte": {},
|
||||
"Patentrechte und Lizenzen": {},
|
||||
"Sonstige Ausleihungen": {},
|
||||
"Sonstige Beteiligungen": {},
|
||||
"Transportanlagen": {},
|
||||
"Unbebaute Grundst\u00fccke": {},
|
||||
"Vorrichtungen, Formen und Modelle": {},
|
||||
"Wohn- und Sozialgeb\u00e4ude auf eigenem Grund": {},
|
||||
"Wohn- und Sozialgeb\u00e4ude auf fremdem Grund": {},
|
||||
"root_type": "Asset"
|
||||
},
|
||||
"Summe Personalaufwand": {
|
||||
"6000 bis 6190 L\u00f6hne": {},
|
||||
"6200 bis 6390 Geh\u00e4lter": {},
|
||||
"6400 bis 6440 Aufwendungen f\u00fcr Abfertigungen": {},
|
||||
"6450 bis 6490 Aufwendungen f\u00fcr Altersversorgung": {},
|
||||
"6500 bis 6550 Gesetzlicher Sozialaufwand Arbeiter": {},
|
||||
"6560 bis 6590 Gesetzlicher Sozialaufwand Angestellte": {},
|
||||
"6600 bis 6650 Lohnabh\u00e4ngige Abgaben und Pflichtbeitr\u00e4gte": {},
|
||||
"6660 bis 6690 Gehaltsabh\u00e4ngige Abgaben und Pflichtbeitr\u00e4gte": {},
|
||||
"6700 bis 6890 Sonstige Sozialaufwendungen": {},
|
||||
"Aufwandsstellenrechnung": {},
|
||||
"root_type": "Expense"
|
||||
},
|
||||
"Summe Umlaufverm\u00f6gen": {
|
||||
"2000 bis 2007 Forderungen aus Lief. und Leist. Inland": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2010 Forderungen aus Lieferungen und Leistungen Inland (10% USt, umsatzsteuerfrei)": {
|
||||
"2100 bis 2120 Forderungen aus Lief. und Leist. EU": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2000 Forderungen aus Lieferungen und Leistungen Inland (20% USt, umsatzsteuerfrei)": {
|
||||
"2150 bis 2170 Forderungen aus Lief. und Leist. Ausland": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2040 Forderungen aus Lieferungen und Leistungen Inland (sonstiger USt-Satz)": {
|
||||
"2200 bis 2220 Forderungen gegen\u00fcber verbundenen Unternehmen": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2100 Forderungen aus Lieferungen und Leistungen EU": {
|
||||
"2250 bis 2270 Forderungen gegen\u00fcber Unternehmen, mit denen ein Beteiligungsverh\u00e4ltnis besteht": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2150 Forderungen aus Lieferungen und Leistungen Ausland (Nicht-EU)": {
|
||||
"2300 bis 2460 Sonstige Forderungen und Verm\u00f6gensgegenst\u00e4nde": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2200 Forderungen gegen\u00fcber verbundenen Unternehmen": {
|
||||
"2630 bis 2670 Sonstige Wertpapiere": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2250 Forderungen gegen\u00fcber Unternehmen, mit denen ein Beteiligungsverh\u00e4ltnis besteht": {
|
||||
"2750 bis 2770 Kassenbest\u00e4nde in Fremdw\u00e4hrung": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2300 Sonstige Forderungen und Verm\u00f6gensgegenst\u00e4nde": {
|
||||
"Aktive Rechnungsabrenzungsposten": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2630 Sonstige Wertpapiere": {
|
||||
"account_type": "Stock"
|
||||
},
|
||||
"2750 Kassenbest\u00e4nde in Fremdw\u00e4hrung": {
|
||||
"account_type": "Cash"
|
||||
},
|
||||
"2900 Aktive Rechnungsabrenzungsposten": {
|
||||
"Anteile an verbundenen Unternehmen": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2600 Anteile an verbundenen Unternehmen": {
|
||||
"account_type": "Equity"
|
||||
},
|
||||
"2680 Besitzwechsel ohne Forderungen": {
|
||||
"Bank / Guthaben bei Kreditinstituten": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2950 Aktiviertes Disagio": {
|
||||
"Besitzwechsel ...": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2610 Eigene Anteile und Wertpapiere an mit Mehrheit beteiligten Unternehmen": {
|
||||
"Disagio": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2570 Einfuhrumsatzsteuer (bezahlt)": {"account_type": "Tax"},
|
||||
|
||||
"2460 Eingeforderte aber noch nicht eingezahlte Einlagen": {
|
||||
"Eigene Anteile (Wertpapiere)": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2180 Einzelwertberichtigungen zu Forderungen aus Lief. und Leist. Ausland": {
|
||||
"Einfuhrumsatzsteuer (bezahlt)": {},
|
||||
"Eingeforderte aber noch nicht eingezahlte Einlagen": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2130 Einzelwertberichtigungen zu Forderungen aus Lief. und Leist. EU": {
|
||||
"Einzelwertberichtigungen zu Forderungen aus Lief. und Leist. Ausland": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2080 Einzelwertberichtigungen zu Forderungen aus Lief. und Leist. Inland ": {
|
||||
"Einzelwertberichtigungen zu Forderungen aus Lief. und Leist. EU": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2270 Einzelwertberichtigungen zu Forderungen gegen\u00fcber Unternehmen mit denen ein Beteiligungsverh\u00e4ltnis besteht": {
|
||||
"Einzelwertberichtigungen zu Forderungen aus Lief. und Leist. Inland ": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2230 Einzelwertberichtigungen zu Forderungen gegen\u00fcber verbundenen Unternehmen": {
|
||||
"Einzelwertberichtigungen zu Forderungen gegen\u00fcber Unternehmen mit denen ein Beteiligungsverh\u00e4ltnis besteht": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2470 Einzelwertberichtigungen zu sonstigen Forderungen und Verm\u00f6gensgegenst\u00e4nden": {
|
||||
"Einzelwertberichtigungen zu Forderungen gegen\u00fcber verbundenen Unternehmen": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2700 Kassenbestand": {
|
||||
"account_type": "Cash"
|
||||
},
|
||||
"2190 Pauschalwertberichtigungen zu Forderungen aus Lief. und Leist. sonstiges Ausland": {
|
||||
"Einzelwertberichtigungen zu sonstigen Forderungen und Verm\u00f6gensgegenst\u00e4nden": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2130 Pauschalwertberichtigungen zu Forderungen aus Lief. und Leist. EU": {
|
||||
"Kassenbestand": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2100 Pauschalwertberichtigungen zu Forderungen aus Lief. und Leist. Inland ": {
|
||||
"Pauschalwertberichtigungen zu Forderungen aus Lief. und Leist. Ausland": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2280 Pauschalwertberichtigungen zu Forderungen gegen\u00fcber Unternehmen mit denen ein Beteiligungsverh\u00e4ltnis besteht": {
|
||||
"Pauschalwertberichtigungen zu Forderungen aus Lief. und Leist. EU": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2240 Pauschalwertberichtigungen zu Forderungen gegen\u00fcber verbundenen Unternehmen": {
|
||||
"Pauschalwertberichtigungen zu Forderungen aus Lief. und Leist. Inland ": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2480 Pauschalwertberichtigungen zu sonstigen Forderungen und Verm\u00f6gensgegenst\u00e4nden": {
|
||||
"Pauschalwertberichtigungen zu Forderungen gegen\u00fcber Unternehmen mit denen ein Beteiligungsverh\u00e4ltnis besteht": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2740 Postwertzeichen": {
|
||||
"account_type": "Cash"
|
||||
},
|
||||
"2780 Schecks in Euro": {
|
||||
"account_type": "Cash"
|
||||
},
|
||||
"2800 Guthaben bei Bank": {
|
||||
"account_type": "Bank"
|
||||
},
|
||||
"2801 Guthaben bei Bank - Sparkonto": {
|
||||
"account_type": "Bank"
|
||||
},
|
||||
"2810 Guthaben bei Paypal": {
|
||||
"account_type": "Bank"
|
||||
},
|
||||
"2930 Mietvorauszahlungen": {
|
||||
"Pauschalwertberichtigungen zu Forderungen gegen\u00fcber verbundenen Unternehmen": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2980 Abgrenzung latenter Steuern": {
|
||||
"Pauschalwertberichtigungen zu sonstigen Forderungen und Verm\u00f6gensgegenst\u00e4nden": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2500 Vorsteuer": {
|
||||
"Postwertzeichen": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"2510 Vorsteuer Inland 10%": {
|
||||
"Schecks in Inlandsw\u00e4hrung": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"Sonstige Anteile": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"Stempelmarken": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"Steuerabgrenzung": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"Unterschiedsbetrag gem. Abschnitt XII Pensionskassengesetz": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"Unterschiedsbetrag zur gebotenen Pensionsr\u00fcckstellung": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"Vorsteuer": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"Vorsteuer aus ig. Erwerb 10%": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"2895 Schwebende Geldbewegugen": {
|
||||
"account_type": "Bank"
|
||||
},
|
||||
"2513 Vorsteuer Inland 5%": {
|
||||
"Vorsteuer aus ig. Erwerb 20%": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"2515 Vorsteuer Inland 20%": {
|
||||
"Vorsteuer \u00a719/Art 19 ( reverse charge ) ": {
|
||||
"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"
|
||||
},
|
||||
"2690 Wertberichtigungen zu Wertpapieren und Anteilen": {
|
||||
"Wertberichtigungen": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"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"},
|
||||
"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"},
|
||||
"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"},
|
||||
"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"},
|
||||
"4630 Ertr\u00e4ge aus dem Abgang vom Anlageverm\u00f6gen, ausgen. Finanzanlagen": {"account_type": "Income Account"},
|
||||
"4660 Ertr\u00e4ge aus der Zuschreibung zum Anlageverm\u00f6gen, ausgen. Finanzanlagen": {"account_type": "Income Account"},
|
||||
"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"
|
||||
"Summe Vorr\u00e4te": {
|
||||
"1000 bis 1090 Bezugsverrechnung": {},
|
||||
"1100 bis 1190 Rohstoffe": {},
|
||||
"1200 bis 1290 Bezogene Teile": {},
|
||||
"1300 bis 1340 Hilfsstoffe": {},
|
||||
"1350 bis 1390 Betriebsstoffe": {},
|
||||
"1400 bis 1490 Unfertige Erzeugniss": {},
|
||||
"1500 bis 1590 Fertige Erzeugniss": {},
|
||||
"1600 bis 1690 Waren": {},
|
||||
"1700 bis 1790 Noch nicht abgerechenbare Leistungen": {},
|
||||
"1900 bis 1990 Wertberichtigungen": {},
|
||||
"geleistete Anzahlungen": {},
|
||||
"root_type": "Asset"
|
||||
},
|
||||
"Klasse 5: Aufwand f\u00fcr Material und Leistungen": {
|
||||
"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"},
|
||||
"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"},
|
||||
"5700 Bearbeitung durch Dritte": {"account_type": "Cost of Goods Sold"},
|
||||
"5900 Aufwandsstellenrechnung Material": {"account_type": "Cost of Goods Sold"},
|
||||
"5820 Skontoertr\u00e4ge (20% USt.)": {"account_type": "Income Account"},
|
||||
"5810 Skontoertr\u00e4ge (10% USt.)": {"account_type": "Income Account"},
|
||||
"5010 Handelswareneinkauf 10 %": {"account_type": "Cost of Goods Sold"},
|
||||
"5020 Handelswareneinkauf 20 %": {"account_type": "Cost of Goods Sold"},
|
||||
"5040 Handelswareneinkauf innergemeinschaftlicher Erwerb 10 % VSt/10 % USt": {"account_type": "Cost of Goods Sold"},
|
||||
"5050 Handelswareneinkauf innergemeinschaftlicher Erwerb 20 % VSt/20 % USt": {"account_type": "Cost of Goods Sold"},
|
||||
"5070 Handelswareneinkauf innergemeinschaftlicher Erwerb ohne Vorsteuerabzug und 10 % USt": {"account_type": "Cost of Goods Sold"},
|
||||
"5080 Handelswareneinkauf innergemeinschaftlicher Erwerb ohne Vorsteuerabzug und 20 % USt": {"account_type": "Cost of Goods Sold"},
|
||||
"Summe Wareneinsatz": {
|
||||
"5100 bis 5190 Verbrauch an Rohstoffen": {},
|
||||
"5200 bis 5290 Verbrauch von bezogenen Fertig- und Einzelteilen": {},
|
||||
"5300 bis 5390 Verbrauch von Hilfsstoffen": {},
|
||||
"5400 bis 5490 Verbrauch von Betriebsstoffen": {},
|
||||
"5500 bis 5590 Verbrauch von Werkzeugen und anderen Erzeugungshilfsmittel": {},
|
||||
"5600 bis 5690 Verbrauch von Brenn- und Treibstoffen, Energie und Wasser": {},
|
||||
"5700 bis 5790 Sonstige bezogene Herstellungsleistungen": {},
|
||||
"Aufwandsstellenrechnung": {},
|
||||
"Skontoertr\u00e4ge auf Materialaufwand": {},
|
||||
"Skontoertr\u00e4ge auf sonstige bezogene Herstellungsleistungen": {},
|
||||
"Wareneinkauf 10 %": {},
|
||||
"Wareneinkauf 20 %": {},
|
||||
"Wareneinkauf igErwerb 10 % VSt/10 % USt": {},
|
||||
"Wareneinkauf igErwerb 20 % VSt/20 % USt": {},
|
||||
"Wareneinkauf igErwerb ohne Vorsteuerabzug und 10 % USt": {},
|
||||
"Wareneinkauf igErwerb ohne Vorsteuerabzug und 20 % USt": {},
|
||||
"root_type": "Expense"
|
||||
},
|
||||
"Klasse 6: Personalaufwand": {
|
||||
"6000 L\u00f6hne": {"account_type": "Payable"},
|
||||
"6200 Geh\u00e4lter": {"account_type": "Payable"},
|
||||
"6400 Aufwendungen f\u00fcr Abfertigungen": {"account_type": "Payable"},
|
||||
"6450 Aufwendungen f\u00fcr Altersversorgung": {"account_type": "Payable"},
|
||||
"6500 Gesetzlicher Sozialaufwand Arbeiter": {"account_type": "Payable"},
|
||||
"6560 Gesetzlicher Sozialaufwand Angestellte": {"account_type": "Payable"},
|
||||
"6600 Lohnabh\u00e4ngige Abgaben und Pflichtbeitr\u00e4gte": {"account_type": "Payable"},
|
||||
"6660 Gehaltsabh\u00e4ngige Abgaben und Pflichtbeitr\u00e4gte": {"account_type": "Payable"},
|
||||
"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"},
|
||||
"7200 Instandhaltung u. Reinigung durch Dritte, Entsorgung, Energie": {"account_type": "Expense Account"},
|
||||
"7300 Transporte durch Dritte": {"account_type": "Expense Account"},
|
||||
"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"},
|
||||
"7350 Reise- und Fahraufwand": {"account_type": "Expense Account"},
|
||||
"7360 Tag- und N\u00e4chtigungsgelder": {"account_type": "Expense Account"},
|
||||
"7380 Nachrichtenaufwand": {"account_type": "Expense Account"},
|
||||
"7400 Miet- und Pachtaufwand": {"account_type": "Expense Account"},
|
||||
"7440 Leasingaufwand": {"account_type": "Expense Account"},
|
||||
"7480 Lizenzaufwand": {"account_type": "Expense Account"},
|
||||
"7500 Aufwand f\u00fcr beigestelltes Personal": {"account_type": "Expense Account"},
|
||||
"7540 Provisionen an Dritte": {"account_type": "Expense Account"},
|
||||
"7580 Aufsichtsratsverg\u00fctungen": {"account_type": "Expense Account"},
|
||||
"7610 Druckerzeugnisse und Vervielf\u00e4ltigungen": {"account_type": "Expense Account"},
|
||||
"7650 Werbung und Repr\u00e4sentationen": {"account_type": "Expense Account"},
|
||||
"7700 Versicherungen": {"account_type": "Expense Account"},
|
||||
"7750 Beratungs- und Pr\u00fcfungsaufwand": {"account_type": "Expense Account"},
|
||||
"7800 Forderungsverluste und Schadensf\u00e4lle": {"account_type": "Expense Account"},
|
||||
"7840 Verschiedene betriebliche Aufwendungen": {"account_type": "Expense Account"},
|
||||
"7910 Aufwandsstellenrechung der Hersteller": {"account_type": "Expense Account"},
|
||||
"7060 Sofortabschreibungen geringwertig": {"account_type": "Expense Account"},
|
||||
"7070 Abschreibungen vom Umlaufverm\u00f6gen, soweit diese die im Unternehmen \u00fcblichen Abschreibungen \u00fcbersteigen": {"account_type": "Depreciation"},
|
||||
"7900 Aufwandsstellenrechnung": {"account_type": "Expense Account"},
|
||||
"7770 Aus- und Fortbildung": {"account_type": "Expense Account"},
|
||||
"7820 Buchwert abgegangener Anlagen, ausgenommen Finanzanlagen": {"account_type": "Expense Account"},
|
||||
"7600 B\u00fcromaterial und Drucksorten": {"account_type": "Expense Account"},
|
||||
"7630 Fachliteratur und Zeitungen ": {"account_type": "Expense Account"},
|
||||
"7960 Herstellungskosten der zur Erzielung der Umsatzerl\u00f6se erbrachten Leistungen": {"account_type": "Expense Account"},
|
||||
"7780 Mitgliedsbeitr\u00e4ge": {"account_type": "Expense Account"},
|
||||
"7880 Skontoertr\u00e4ge auf sonstige betriebliche Aufwendungen": {"account_type": "Expense Account"},
|
||||
"7990 Sonstige betrieblichen Aufwendungen": {"account_type": "Expense Account"},
|
||||
"7680 Spenden und Trinkgelder": {"account_type": "Expense Account"},
|
||||
"7790 Spesen des Geldverkehrs": {"account_type": "Expense Account"},
|
||||
"7830 Verluste aus dem Abgang vom Anlageverm\u00f6gen, ausgenommen Finanzanlagen": {"account_type": "Expense Account"},
|
||||
"7970 Vertriebskosten": {"account_type": "Expense Account"},
|
||||
"7980 Verwaltungskosten": {"account_type": "Expense Account"},
|
||||
"root_type": "Expense"
|
||||
},
|
||||
"Klasse 8: Finanz- und ausserordentliche Ertr\u00e4ge und Aufwendungen": {
|
||||
"8000 Ertr\u00e4ge aus Beteiligungen": {"account_type": "Income Account"},
|
||||
"8050 Ertr\u00e4ge aus anderen Wertpapieren und Ausleihungen des Finanzanlageverm\u00f6gens": {"account_type": "Income Account"},
|
||||
"8100 Zinsen aus Bankguthaben": {"account_type": "Income Account"},
|
||||
"8110 Zinsen aus gewaehrten Darlehen": {"account_type": "Income Account"},
|
||||
"8130 Verzugszinsenertraege": {"account_type": "Income Account"},
|
||||
"8220 Aufwendungen aus Beteiligungen": {"account_type": "Expense Account"},
|
||||
"8260 Aufwendungen aus sonst. Fiananzanlagen und aus Wertpapieren des Umlaufverm\u00f6gens": {},
|
||||
"8280 Zinsen und \u00e4hnliche Aufwendungem": {"account_type": "Expense Account"},
|
||||
"8400 Au\u00dferordentliche Ertr\u00e4ge": {"account_type": "Income Account"},
|
||||
"8450 Au\u00dferordentliche Aufwendungen": {"account_type": "Expense Account"},
|
||||
"8500 Steuern vom Einkommen und vom Ertrag": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"8600 Aufl\u00f6sung unversteuerten R\u00fccklagen": {"account_type": "Income Account"},
|
||||
"8700 Aufl\u00f6sung von Kapitalr\u00fccklagen": {"account_type": "Income Account"},
|
||||
"8750 Aufl\u00f6sung von Gewinnr\u00fccklagen": {"account_type": "Income Account"},
|
||||
"8800 Zuweisung zu unversteuerten R\u00fccklagen": {"account_type": "Expense Account"},
|
||||
"8900 Zuweisung zu Gewinnr\u00fccklagen": {"account_type": "Expense Account"},
|
||||
"8100 Buchwert abgegangener Beteiligungen": {"account_type": "Expense Account"},
|
||||
"8130 Buchwert abgegangener Wertpapiere des Umlaufverm\u00f6gens": {"account_type": "Expense Account"},
|
||||
"8120 Buchwert abgegangener sonstiger Finanzanlagen": {"account_type": "Expense Account"},
|
||||
"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"
|
||||
},
|
||||
"9200 Kapitalr\u00fccklagen": {
|
||||
"account_type": "Equity"
|
||||
},
|
||||
"9300 Gewinnr\u00fccklagen": {
|
||||
"account_type": "Equity"
|
||||
},
|
||||
"9400 Bewertungsreserven uns sonst. unversteuerte R\u00fccklagen": {
|
||||
"account_type": "Equity"
|
||||
},
|
||||
"9600 Private Entnahmen": {"account_type": "Equity"},
|
||||
"9610 Privatsteuern": {"account_type": "Equity"},
|
||||
"9700 Einlagen stiller Gesellschafter ": {"account_type": "Equity"},
|
||||
"9900 Evidenzkonto": {"account_type": "Equity"},
|
||||
"9800 Er\u00f6ffnungsbilanzkonto (EBK)": {"account_type": "Equity"},
|
||||
"9880 Jahresergebnis laut Gewinn- und Verlustrechnung (G+V)": {"account_type": "Equity"},
|
||||
"9850 Schlussbilanzkonto (SBK)": {"account_type": "Round Off"},
|
||||
"9190 nicht eingeforderte ausstehende Einlagen und berechtigte Entnahmen von Gesellschaftern": {
|
||||
"account_type": "Equity"
|
||||
},
|
||||
"root_type": "Equity"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -99,7 +99,7 @@ def make_dimension_in_accounting_doctypes(doc, doclist=None):
|
||||
if doctype == "Budget":
|
||||
add_dimension_to_budget_doctype(df.copy(), doc)
|
||||
else:
|
||||
create_custom_field(doctype, df, ignore_validate=True)
|
||||
create_custom_field(doctype, df)
|
||||
|
||||
count += 1
|
||||
|
||||
@@ -115,7 +115,7 @@ def add_dimension_to_budget_doctype(df, doc):
|
||||
}
|
||||
)
|
||||
|
||||
create_custom_field("Budget", df, ignore_validate=True)
|
||||
create_custom_field("Budget", df)
|
||||
|
||||
property_setter = frappe.db.exists("Property Setter", "Budget-budget_against-options")
|
||||
|
||||
@@ -205,16 +205,10 @@ def get_doctypes_with_dimensions():
|
||||
return frappe.get_hooks("accounting_dimension_doctypes")
|
||||
|
||||
|
||||
def get_accounting_dimensions(as_list=True, filters=None):
|
||||
|
||||
if not filters:
|
||||
filters = {"disabled": 0}
|
||||
|
||||
def get_accounting_dimensions(as_list=True):
|
||||
if frappe.flags.accounting_dimensions is None:
|
||||
frappe.flags.accounting_dimensions = frappe.get_all(
|
||||
"Accounting Dimension",
|
||||
fields=["label", "fieldname", "disabled", "document_type"],
|
||||
filters=filters,
|
||||
"Accounting Dimension", fields=["label", "fieldname", "disabled", "document_type"]
|
||||
)
|
||||
|
||||
if as_list:
|
||||
@@ -234,14 +228,12 @@ def get_checks_for_pl_and_bs_accounts():
|
||||
return dimensions
|
||||
|
||||
|
||||
def get_dimension_with_children(doctype, dimensions):
|
||||
def get_dimension_with_children(doctype, dimension):
|
||||
|
||||
if isinstance(dimensions, str):
|
||||
dimensions = [dimensions]
|
||||
if isinstance(dimension, list):
|
||||
dimension = dimension[0]
|
||||
|
||||
all_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"
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
|
||||
frappe.ui.form.on('Accounting Dimension Filter', {
|
||||
refresh: function(frm, cdt, cdn) {
|
||||
if (frm.doc.accounting_dimension) {
|
||||
frm.set_df_property('dimensions', 'label', frm.doc.accounting_dimension, cdn, 'dimension_value');
|
||||
}
|
||||
|
||||
let help_content =
|
||||
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
|
||||
<tr><td>
|
||||
@@ -64,7 +68,6 @@ frappe.ui.form.on('Accounting Dimension Filter', {
|
||||
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.refresh_field("dimensions");
|
||||
frm.trigger('setup_filters');
|
||||
},
|
||||
|
||||
@@ -49,9 +49,15 @@ class AccountingPeriod(Document):
|
||||
@frappe.whitelist()
|
||||
def get_doctypes_for_closing(self):
|
||||
docs_for_closing = []
|
||||
# get period closing doctypes from all the apps
|
||||
doctypes = frappe.get_hooks("period_closing_doctypes")
|
||||
|
||||
doctypes = [
|
||||
"Sales Invoice",
|
||||
"Purchase Invoice",
|
||||
"Journal Entry",
|
||||
"Payroll Entry",
|
||||
"Bank Clearance",
|
||||
"Asset",
|
||||
"Stock Entry",
|
||||
]
|
||||
closed_doctypes = [{"document_type": doctype, "closed": 1} for doctype in doctypes]
|
||||
for closed_doctype in closed_doctypes:
|
||||
docs_for_closing.append(closed_doctype)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"automatically_fetch_payment_terms",
|
||||
"column_break_17",
|
||||
"enable_common_party_accounting",
|
||||
"allow_multi_currency_invoices_against_single_party_account",
|
||||
"enable_discount_accounting",
|
||||
"report_setting_section",
|
||||
"use_custom_cash_flow",
|
||||
"deferred_accounting_settings_section",
|
||||
@@ -91,7 +91,7 @@
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Enabling ensure each Purchase Invoice has a unique value in Supplier Invoice No. field",
|
||||
"description": "Enabling ensure each Sales Invoice has a unique value in Supplier Invoice No. field",
|
||||
"fieldname": "check_supplier_invoice_uniqueness",
|
||||
"fieldtype": "Check",
|
||||
"label": "Check Supplier Invoice Number Uniqueness"
|
||||
@@ -272,6 +272,13 @@
|
||||
"fieldtype": "Check",
|
||||
"label": "Create Ledger Entries for Change Amount"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "If enabled, additional ledger entries will be made for discounts in a separate Discount Account",
|
||||
"fieldname": "enable_discount_accounting",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enable Discount Accounting"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Learn about <a href=\"https://docs.erpnext.com/docs/v13/user/manual/en/accounts/articles/common_party_accounting#:~:text=Common%20Party%20Accounting%20in%20ERPNext,Invoice%20against%20a%20primary%20Supplier.\">Common Party</a>",
|
||||
@@ -340,13 +347,6 @@
|
||||
"fieldname": "report_setting_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Report Setting"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Enabling this will allow creation of multi-currency invoices against single party account in company currency",
|
||||
"fieldname": "allow_multi_currency_invoices_against_single_party_account",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow multi-currency invoices against single party account "
|
||||
}
|
||||
],
|
||||
"icon": "icon-cog",
|
||||
@@ -354,7 +354,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2022-11-27 21:49:52.538655",
|
||||
"modified": "2022-02-04 12:32:36.805652",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
|
||||
@@ -28,6 +28,7 @@ class AccountsSettings(Document):
|
||||
|
||||
self.validate_stale_days()
|
||||
self.enable_payment_schedule_in_print()
|
||||
self.toggle_discount_accounting_fields()
|
||||
self.validate_pending_reposts()
|
||||
|
||||
def validate_stale_days(self):
|
||||
@@ -51,6 +52,74 @@ class AccountsSettings(Document):
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
|
||||
def toggle_discount_accounting_fields(self):
|
||||
enable_discount_accounting = cint(self.enable_discount_accounting)
|
||||
|
||||
for doctype in ["Sales Invoice Item", "Purchase Invoice Item"]:
|
||||
make_property_setter(
|
||||
doctype,
|
||||
"discount_account",
|
||||
"hidden",
|
||||
not (enable_discount_accounting),
|
||||
"Check",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
if enable_discount_accounting:
|
||||
make_property_setter(
|
||||
doctype,
|
||||
"discount_account",
|
||||
"mandatory_depends_on",
|
||||
"eval: doc.discount_amount",
|
||||
"Code",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
else:
|
||||
make_property_setter(
|
||||
doctype,
|
||||
"discount_account",
|
||||
"mandatory_depends_on",
|
||||
"",
|
||||
"Code",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
|
||||
for doctype in ["Sales Invoice", "Purchase Invoice"]:
|
||||
make_property_setter(
|
||||
doctype,
|
||||
"additional_discount_account",
|
||||
"hidden",
|
||||
not (enable_discount_accounting),
|
||||
"Check",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
if enable_discount_accounting:
|
||||
make_property_setter(
|
||||
doctype,
|
||||
"additional_discount_account",
|
||||
"mandatory_depends_on",
|
||||
"eval: doc.discount_amount",
|
||||
"Code",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
else:
|
||||
make_property_setter(
|
||||
doctype,
|
||||
"additional_discount_account",
|
||||
"mandatory_depends_on",
|
||||
"",
|
||||
"Code",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
|
||||
make_property_setter(
|
||||
"Item",
|
||||
"default_discount_account",
|
||||
"hidden",
|
||||
not (enable_discount_accounting),
|
||||
"Check",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
|
||||
def validate_pending_reposts(self):
|
||||
if self.acc_frozen_upto:
|
||||
check_pending_reposting(self.acc_frozen_upto)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"bank_account_no",
|
||||
"address_and_contact",
|
||||
"address_html",
|
||||
"website",
|
||||
"column_break_13",
|
||||
"contact_html",
|
||||
"integration_details_section",
|
||||
@@ -155,6 +156,11 @@
|
||||
"fieldtype": "HTML",
|
||||
"label": "Address HTML"
|
||||
},
|
||||
{
|
||||
"fieldname": "website",
|
||||
"fieldtype": "Data",
|
||||
"label": "Website"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_13",
|
||||
"fieldtype": "Column Break"
|
||||
@@ -202,7 +208,7 @@
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2022-05-04 15:49:42.620630",
|
||||
"modified": "2020-10-23 16:48:06.303658",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Account",
|
||||
@@ -237,6 +243,5 @@
|
||||
"search_fields": "bank,account",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -77,6 +77,6 @@ def get_party_bank_account(party_type, party):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_bank_account_details(bank_account):
|
||||
return frappe.get_cached_value(
|
||||
return frappe.db.get_value(
|
||||
"Bank Account", bank_account, ["account", "bank", "bank_account_no"], as_dict=1
|
||||
)
|
||||
|
||||
@@ -4,23 +4,6 @@
|
||||
frappe.ui.form.on("Bank Clearance", {
|
||||
setup: function(frm) {
|
||||
frm.add_fetch("account", "account_currency", "account_currency");
|
||||
|
||||
frm.set_query("account", function() {
|
||||
return {
|
||||
"filters": {
|
||||
"account_type": ["in",["Bank","Cash"]],
|
||||
"is_group": 0,
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("bank_account", function () {
|
||||
return {
|
||||
filters: {
|
||||
'is_company_account': 1
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
onload: function(frm) {
|
||||
@@ -29,7 +12,14 @@ frappe.ui.form.on("Bank Clearance", {
|
||||
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "";
|
||||
frm.set_value("account", default_bank_account);
|
||||
|
||||
|
||||
frm.set_query("account", function() {
|
||||
return {
|
||||
"filters": {
|
||||
"account_type": ["in",["Bank","Cash"]],
|
||||
"is_group": 0
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_value("from_date", frappe.datetime.month_start());
|
||||
frm.set_value("to_date", frappe.datetime.month_end());
|
||||
@@ -37,14 +27,6 @@ frappe.ui.form.on("Bank Clearance", {
|
||||
|
||||
refresh: function(frm) {
|
||||
frm.disable_save();
|
||||
|
||||
if (frm.doc.account && frm.doc.from_date && frm.doc.to_date) {
|
||||
frm.add_custom_button(__('Get Payment Entries'), () =>
|
||||
frm.trigger("get_payment_entries")
|
||||
);
|
||||
|
||||
frm.change_custom_button_type('Get Payment Entries', null, 'primary');
|
||||
}
|
||||
},
|
||||
|
||||
update_clearance_date: function(frm) {
|
||||
@@ -54,30 +36,22 @@ frappe.ui.form.on("Bank Clearance", {
|
||||
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');
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
get_payment_entries: function(frm) {
|
||||
return frappe.call({
|
||||
method: "get_payment_entries",
|
||||
doc: frm.doc,
|
||||
callback: function(r, rt) {
|
||||
frm.refresh_field("payment_entries");
|
||||
frm.refresh_fields();
|
||||
|
||||
if (frm.doc.payment_entries.length) {
|
||||
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.fields_dict.payment_entries.wrapper).find("[data-fieldname=amount]").each(function(i,v){
|
||||
if (i !=0){
|
||||
$(v).addClass("text-right")
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_copy": 1,
|
||||
"creation": "2013-01-10 16:34:05",
|
||||
"doctype": "DocType",
|
||||
@@ -14,8 +13,11 @@
|
||||
"bank_account",
|
||||
"include_reconciled_entries",
|
||||
"include_pos_transactions",
|
||||
"get_payment_entries",
|
||||
"section_break_10",
|
||||
"payment_entries"
|
||||
"payment_entries",
|
||||
"update_clearance_date",
|
||||
"total_amount"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -74,6 +76,11 @@
|
||||
"fieldtype": "Check",
|
||||
"label": "Include POS Transactions"
|
||||
},
|
||||
{
|
||||
"fieldname": "get_payment_entries",
|
||||
"fieldtype": "Button",
|
||||
"label": "Get Payment Entries"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_10",
|
||||
"fieldtype": "Section Break"
|
||||
@@ -84,14 +91,25 @@
|
||||
"fieldtype": "Table",
|
||||
"label": "Payment Entries",
|
||||
"options": "Bank Clearance Detail"
|
||||
},
|
||||
{
|
||||
"fieldname": "update_clearance_date",
|
||||
"fieldtype": "Button",
|
||||
"label": "Update Clearance Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "total_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total Amount",
|
||||
"options": "account_currency",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"hide_toolbar": 1,
|
||||
"icon": "fa fa-check",
|
||||
"idx": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2022-11-28 17:24:13.008692",
|
||||
"modified": "2020-04-06 16:12:06.628008",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Clearance",
|
||||
@@ -108,6 +126,5 @@
|
||||
"quick_entry": 1,
|
||||
"read_only": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC",
|
||||
"states": []
|
||||
"sort_order": "ASC"
|
||||
}
|
||||
@@ -5,10 +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
|
||||
|
||||
import erpnext
|
||||
from frappe.utils import flt, fmt_money, getdate, nowdate
|
||||
|
||||
form_grid_templates = {"journal_entries": "templates/form_grid/bank_reconciliation_grid.html"}
|
||||
|
||||
@@ -79,59 +76,6 @@ class BankClearance(Document):
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
loan_disbursement = frappe.qb.DocType("Loan Disbursement")
|
||||
|
||||
loan_disbursements = (
|
||||
frappe.qb.from_(loan_disbursement)
|
||||
.select(
|
||||
ConstantColumn("Loan Disbursement").as_("payment_document"),
|
||||
loan_disbursement.name.as_("payment_entry"),
|
||||
loan_disbursement.disbursed_amount.as_("credit"),
|
||||
ConstantColumn(0).as_("debit"),
|
||||
loan_disbursement.reference_number.as_("cheque_number"),
|
||||
loan_disbursement.reference_date.as_("cheque_date"),
|
||||
loan_disbursement.disbursement_date.as_("posting_date"),
|
||||
loan_disbursement.applicant.as_("against_account"),
|
||||
)
|
||||
.where(loan_disbursement.docstatus == 1)
|
||||
.where(loan_disbursement.disbursement_date >= self.from_date)
|
||||
.where(loan_disbursement.disbursement_date <= self.to_date)
|
||||
.where(loan_disbursement.clearance_date.isnull())
|
||||
.where(loan_disbursement.disbursement_account.isin([self.bank_account, self.account]))
|
||||
.orderby(loan_disbursement.disbursement_date)
|
||||
.orderby(loan_disbursement.name, order=frappe.qb.desc)
|
||||
).run(as_dict=1)
|
||||
|
||||
loan_repayment = frappe.qb.DocType("Loan Repayment")
|
||||
|
||||
query = (
|
||||
frappe.qb.from_(loan_repayment)
|
||||
.select(
|
||||
ConstantColumn("Loan Repayment").as_("payment_document"),
|
||||
loan_repayment.name.as_("payment_entry"),
|
||||
loan_repayment.amount_paid.as_("debit"),
|
||||
ConstantColumn(0).as_("credit"),
|
||||
loan_repayment.reference_number.as_("cheque_number"),
|
||||
loan_repayment.reference_date.as_("cheque_date"),
|
||||
loan_repayment.applicant.as_("against_account"),
|
||||
loan_repayment.posting_date,
|
||||
)
|
||||
.where(loan_repayment.docstatus == 1)
|
||||
.where(loan_repayment.clearance_date.isnull())
|
||||
.where(loan_repayment.posting_date >= self.from_date)
|
||||
.where(loan_repayment.posting_date <= self.to_date)
|
||||
.where(loan_repayment.payment_account.isin([self.bank_account, self.account]))
|
||||
)
|
||||
|
||||
if frappe.db.has_column("Loan Repayment", "repay_from_salary"):
|
||||
query = query.where((loan_repayment.repay_from_salary == 0))
|
||||
|
||||
query = query.orderby(loan_repayment.posting_date).orderby(
|
||||
loan_repayment.name, order=frappe.qb.desc
|
||||
)
|
||||
|
||||
loan_repayments = query.run(as_dict=True)
|
||||
|
||||
pos_sales_invoices, pos_purchase_invoices = [], []
|
||||
if self.include_pos_transactions:
|
||||
pos_sales_invoices = frappe.db.sql(
|
||||
@@ -170,33 +114,26 @@ class BankClearance(Document):
|
||||
|
||||
entries = sorted(
|
||||
list(payment_entries)
|
||||
+ list(journal_entries)
|
||||
+ list(pos_sales_invoices)
|
||||
+ list(pos_purchase_invoices)
|
||||
+ list(loan_disbursements)
|
||||
+ list(loan_repayments),
|
||||
key=lambda k: getdate(k["posting_date"]),
|
||||
+ list(journal_entries + list(pos_sales_invoices) + list(pos_purchase_invoices)),
|
||||
key=lambda k: k["posting_date"] or getdate(nowdate()),
|
||||
)
|
||||
|
||||
self.set("payment_entries", [])
|
||||
default_currency = erpnext.get_default_currency()
|
||||
self.total_amount = 0.0
|
||||
|
||||
for d in entries:
|
||||
row = self.append("payment_entries", {})
|
||||
|
||||
amount = flt(d.get("debit", 0)) - flt(d.get("credit", 0))
|
||||
|
||||
if not d.get("account_currency"):
|
||||
d.account_currency = default_currency
|
||||
|
||||
formatted_amount = fmt_money(abs(amount), 2, d.account_currency)
|
||||
d.amount = formatted_amount + " " + (_("Dr") if amount > 0 else _("Cr"))
|
||||
d.posting_date = getdate(d.posting_date)
|
||||
|
||||
d.pop("credit")
|
||||
d.pop("debit")
|
||||
d.pop("account_currency")
|
||||
row.update(d)
|
||||
self.total_amount += flt(amount)
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_clearance_date(self):
|
||||
|
||||
@@ -1,96 +1,9 @@
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
from frappe.utils import add_months, getdate
|
||||
|
||||
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
|
||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||
from erpnext.loan_management.doctype.loan.test_loan import (
|
||||
create_loan,
|
||||
create_loan_accounts,
|
||||
create_loan_type,
|
||||
create_repayment_entry,
|
||||
make_loan_disbursement_entry,
|
||||
)
|
||||
|
||||
|
||||
class TestBankClearance(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
make_bank_account()
|
||||
create_loan_accounts()
|
||||
create_loan_masters()
|
||||
add_transactions()
|
||||
|
||||
# Basic test case to test if bank clearance tool doesn't break
|
||||
# Detailed test can be added later
|
||||
def test_bank_clearance(self):
|
||||
bank_clearance = frappe.get_doc("Bank Clearance")
|
||||
bank_clearance.account = "_Test Bank Clearance - _TC"
|
||||
bank_clearance.from_date = add_months(getdate(), -1)
|
||||
bank_clearance.to_date = getdate()
|
||||
bank_clearance.get_payment_entries()
|
||||
self.assertEqual(len(bank_clearance.payment_entries), 3)
|
||||
|
||||
|
||||
def make_bank_account():
|
||||
if not frappe.db.get_value("Account", "_Test Bank Clearance - _TC"):
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Account",
|
||||
"account_type": "Bank",
|
||||
"account_name": "_Test Bank Clearance",
|
||||
"company": "_Test Company",
|
||||
"parent_account": "Bank Accounts - _TC",
|
||||
}
|
||||
).insert()
|
||||
|
||||
|
||||
def create_loan_masters():
|
||||
create_loan_type(
|
||||
"Clearance Loan",
|
||||
2000000,
|
||||
13.5,
|
||||
25,
|
||||
0,
|
||||
5,
|
||||
"Cash",
|
||||
"_Test Bank Clearance - _TC",
|
||||
"_Test Bank Clearance - _TC",
|
||||
"Loan Account - _TC",
|
||||
"Interest Income Account - _TC",
|
||||
"Penalty Income Account - _TC",
|
||||
)
|
||||
|
||||
|
||||
def add_transactions():
|
||||
make_payment_entry()
|
||||
make_loan()
|
||||
|
||||
|
||||
def make_loan():
|
||||
loan = create_loan(
|
||||
"_Test Customer",
|
||||
"Clearance Loan",
|
||||
280000,
|
||||
"Repay Over Number of Periods",
|
||||
20,
|
||||
applicant_type="Customer",
|
||||
)
|
||||
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.save()
|
||||
repayment_entry.submit()
|
||||
|
||||
|
||||
def make_payment_entry():
|
||||
pi = make_purchase_invoice(supplier="_Test Supplier", qty=1, rate=690)
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank Clearance - _TC")
|
||||
pe.reference_no = "Conrad Oct 18"
|
||||
pe.reference_date = "2018-10-24"
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
pass
|
||||
|
||||
@@ -43,13 +43,20 @@ frappe.ui.form.on('Bank Guarantee', {
|
||||
|
||||
reference_docname: function(frm) {
|
||||
if (frm.doc.reference_docname && frm.doc.reference_doctype) {
|
||||
let fields_to_fetch = ["grand_total"];
|
||||
let party_field = frm.doc.reference_doctype == "Sales Order" ? "customer" : "supplier";
|
||||
|
||||
if (frm.doc.reference_doctype == "Sales Order") {
|
||||
fields_to_fetch.push("project");
|
||||
}
|
||||
|
||||
fields_to_fetch.push(party_field);
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.bank_guarantee.bank_guarantee.get_voucher_details",
|
||||
method: "erpnext.accounts.doctype.bank_guarantee.bank_guarantee.get_vouchar_detials",
|
||||
args: {
|
||||
"bank_guarantee_type": frm.doc.bg_type,
|
||||
"reference_name": frm.doc.reference_docname
|
||||
"column_list": fields_to_fetch,
|
||||
"doctype": frm.doc.reference_doctype,
|
||||
"docname": frm.doc.reference_docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
# For license information, please see license.txt
|
||||
|
||||
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.desk.search import sanitize_searchfield
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
@@ -22,18 +25,14 @@ class BankGuarantee(Document):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_voucher_details(bank_guarantee_type: str, reference_name: str):
|
||||
if not isinstance(reference_name, str):
|
||||
raise TypeError("reference_name must be a string")
|
||||
|
||||
fields_to_fetch = ["grand_total"]
|
||||
|
||||
if bank_guarantee_type == "Receiving":
|
||||
doctype = "Sales Order"
|
||||
fields_to_fetch.append("customer")
|
||||
fields_to_fetch.append("project")
|
||||
else:
|
||||
doctype = "Purchase Order"
|
||||
fields_to_fetch.append("supplier")
|
||||
|
||||
return frappe.db.get_value(doctype, reference_name, fields_to_fetch, as_dict=True)
|
||||
def get_vouchar_detials(column_list, doctype, docname):
|
||||
column_list = json.loads(column_list)
|
||||
for col in column_list:
|
||||
sanitize_searchfield(col)
|
||||
return frappe.db.sql(
|
||||
""" select {columns} from `tab{doctype}` where name=%s""".format(
|
||||
columns=", ".join(column_list), doctype=doctype
|
||||
),
|
||||
docname,
|
||||
as_dict=1,
|
||||
)[0]
|
||||
|
||||
@@ -12,9 +12,6 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
||||
},
|
||||
};
|
||||
});
|
||||
let no_bank_transactions_text =
|
||||
`<div class="text-muted text-center">${__("No Matching Bank Transactions Found")}</div>`
|
||||
set_field_options("no_bank_transactions", no_bank_transactions_text);
|
||||
},
|
||||
|
||||
onload: function (frm) {
|
||||
|
||||
@@ -81,7 +81,8 @@
|
||||
},
|
||||
{
|
||||
"fieldname": "no_bank_transactions",
|
||||
"fieldtype": "HTML"
|
||||
"fieldtype": "HTML",
|
||||
"options": "<div class=\"text-muted text-center\">No Matching Bank Transactions Found</div>"
|
||||
}
|
||||
],
|
||||
"hide_toolbar": 1,
|
||||
|
||||
@@ -10,6 +10,7 @@ from frappe.model.document import Document
|
||||
from frappe.query_builder.custom import ConstantColumn
|
||||
from frappe.utils import flt
|
||||
|
||||
from erpnext import get_company_currency
|
||||
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_paid_amount
|
||||
from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_statement import (
|
||||
get_amounts_not_reflected_in_system,
|
||||
@@ -57,7 +58,7 @@ def get_bank_transactions(bank_account, from_date=None, to_date=None):
|
||||
@frappe.whitelist()
|
||||
def get_account_balance(bank_account, till_date):
|
||||
# returns account balance till the specified date
|
||||
account = frappe.get_cached_value("Bank Account", bank_account, "account")
|
||||
account = frappe.db.get_value("Bank Account", bank_account, "account")
|
||||
filters = frappe._dict(
|
||||
{"account": account, "report_date": till_date, "include_pos_transactions": 1}
|
||||
)
|
||||
@@ -130,10 +131,8 @@ def create_journal_entry_bts(
|
||||
fieldname=["name", "deposit", "withdrawal", "bank_account"],
|
||||
as_dict=True,
|
||||
)[0]
|
||||
company_account = frappe.get_cached_value(
|
||||
"Bank Account", bank_transaction.bank_account, "account"
|
||||
)
|
||||
account_type = frappe.get_cached_value("Account", second_account, "account_type")
|
||||
company_account = frappe.get_value("Bank Account", bank_transaction.bank_account, "account")
|
||||
account_type = frappe.db.get_value("Account", second_account, "account_type")
|
||||
if account_type in ["Receivable", "Payable"]:
|
||||
if not (party_type and party):
|
||||
frappe.throw(
|
||||
@@ -166,7 +165,7 @@ def create_journal_entry_bts(
|
||||
}
|
||||
)
|
||||
|
||||
company = frappe.get_cached_value("Account", company_account, "company")
|
||||
company = frappe.get_value("Account", company_account, "company")
|
||||
|
||||
journal_entry_dict = {
|
||||
"voucher_type": entry_type,
|
||||
@@ -221,10 +220,8 @@ def create_payment_entry_bts(
|
||||
paid_amount = bank_transaction.unallocated_amount
|
||||
payment_type = "Receive" if bank_transaction.deposit > 0 else "Pay"
|
||||
|
||||
company_account = frappe.get_cached_value(
|
||||
"Bank Account", bank_transaction.bank_account, "account"
|
||||
)
|
||||
company = frappe.get_cached_value("Account", company_account, "company")
|
||||
company_account = frappe.get_value("Bank Account", bank_transaction.bank_account, "account")
|
||||
company = frappe.get_value("Account", company_account, "company")
|
||||
payment_entry_dict = {
|
||||
"company": company,
|
||||
"payment_type": payment_type,
|
||||
@@ -270,7 +267,7 @@ def reconcile_vouchers(bank_transaction_name, vouchers):
|
||||
# updated clear date of all the vouchers based on the bank transaction
|
||||
vouchers = json.loads(vouchers)
|
||||
transaction = frappe.get_doc("Bank Transaction", bank_transaction_name)
|
||||
company_account = frappe.get_cached_value("Bank Account", transaction.bank_account, "account")
|
||||
company_account = frappe.db.get_value("Bank Account", transaction.bank_account, "account")
|
||||
|
||||
if transaction.unallocated_amount == 0:
|
||||
frappe.throw(_("This bank transaction is already fully reconciled"))
|
||||
@@ -294,7 +291,7 @@ def reconcile_vouchers(bank_transaction_name, vouchers):
|
||||
"The sum total of amounts of all selected vouchers should be less than the unallocated amount of the bank transaction"
|
||||
)
|
||||
)
|
||||
account = frappe.get_cached_value("Bank Account", transaction.bank_account, "account")
|
||||
account = frappe.db.get_value("Bank Account", transaction.bank_account, "account")
|
||||
|
||||
for voucher in vouchers:
|
||||
gl_entry = frappe.db.get_value(
|
||||
@@ -371,27 +368,6 @@ def get_queries(bank_account, company, transaction, document_types):
|
||||
account_from_to = "paid_to" if transaction.deposit > 0 else "paid_from"
|
||||
queries = []
|
||||
|
||||
# get matching queries from all the apps
|
||||
for method_name in frappe.get_hooks("get_matching_queries"):
|
||||
queries.extend(
|
||||
frappe.get_attr(method_name)(
|
||||
bank_account,
|
||||
company,
|
||||
transaction,
|
||||
document_types,
|
||||
amount_condition,
|
||||
account_from_to,
|
||||
)
|
||||
or []
|
||||
)
|
||||
|
||||
return queries
|
||||
|
||||
|
||||
def get_matching_queries(
|
||||
bank_account, company, transaction, document_types, amount_condition, account_from_to
|
||||
):
|
||||
queries = []
|
||||
if "payment_entry" in document_types:
|
||||
pe_amount_matching = get_pe_matching_query(amount_condition, account_from_to, transaction)
|
||||
queries.extend([pe_amount_matching])
|
||||
@@ -409,6 +385,10 @@ def get_matching_queries(
|
||||
pi_amount_matching = get_pi_matching_query(amount_condition)
|
||||
queries.extend([pi_amount_matching])
|
||||
|
||||
if "expense_claim" in document_types:
|
||||
ec_amount_matching = get_ec_matching_query(bank_account, company, amount_condition)
|
||||
queries.extend([ec_amount_matching])
|
||||
|
||||
return queries
|
||||
|
||||
|
||||
@@ -491,9 +471,6 @@ def get_lr_matching_query(bank_account, amount_condition, filters):
|
||||
.where(loan_repayment.payment_account == bank_account)
|
||||
)
|
||||
|
||||
if frappe.db.has_column("Loan Repayment", "repay_from_salary"):
|
||||
query = query.where((loan_repayment.repay_from_salary == 0))
|
||||
|
||||
if amount_condition:
|
||||
query.where(loan_repayment.amount_paid == filters.get("amount"))
|
||||
else:
|
||||
@@ -624,3 +601,37 @@ def get_pi_matching_query(amount_condition):
|
||||
AND ifnull(clearance_date, '') = ""
|
||||
AND cash_bank_account = %(bank_account)s
|
||||
"""
|
||||
|
||||
|
||||
def get_ec_matching_query(bank_account, company, amount_condition):
|
||||
# get matching Expense Claim query
|
||||
mode_of_payments = [
|
||||
x["parent"]
|
||||
for x in frappe.db.get_all(
|
||||
"Mode of Payment Account", filters={"default_account": bank_account}, fields=["parent"]
|
||||
)
|
||||
]
|
||||
mode_of_payments = "('" + "', '".join(mode_of_payments) + "' )"
|
||||
company_currency = get_company_currency(company)
|
||||
return f"""
|
||||
SELECT
|
||||
( CASE WHEN employee = %(party)s THEN 1 ELSE 0 END
|
||||
+ 1 ) AS rank,
|
||||
'Expense Claim' as doctype,
|
||||
name,
|
||||
total_sanctioned_amount as paid_amount,
|
||||
'' as reference_no,
|
||||
'' as reference_date,
|
||||
employee as party,
|
||||
'Employee' as party_type,
|
||||
posting_date,
|
||||
'{company_currency}' as currency
|
||||
FROM
|
||||
`tabExpense Claim`
|
||||
WHERE
|
||||
total_sanctioned_amount {amount_condition} %(amount)s
|
||||
AND docstatus = 1
|
||||
AND is_paid = 1
|
||||
AND ifnull(clearance_date, '') = ""
|
||||
AND mode_of_payment in {mode_of_payments}
|
||||
"""
|
||||
|
||||
@@ -100,7 +100,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
|
||||
if (frm.doc.status.includes("Success")) {
|
||||
frm.add_custom_button(
|
||||
__("Go to {0} List", [__(frm.doc.reference_doctype)]),
|
||||
__("Go to {0} List", [frm.doc.reference_doctype]),
|
||||
() => frappe.set_route("List", frm.doc.reference_doctype)
|
||||
);
|
||||
}
|
||||
@@ -141,7 +141,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
},
|
||||
|
||||
show_import_status(frm) {
|
||||
let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
|
||||
let import_log = JSON.parse(frm.doc.import_log || "[]");
|
||||
let successful_records = import_log.filter((log) => log.success);
|
||||
let failed_records = import_log.filter((log) => !log.success);
|
||||
if (successful_records.length === 0) return;
|
||||
@@ -309,7 +309,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
// method: 'frappe.core.doctype.data_import.data_import.get_preview_from_template',
|
||||
|
||||
show_import_preview(frm, preview_data) {
|
||||
let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
|
||||
let import_log = JSON.parse(frm.doc.import_log || "[]");
|
||||
|
||||
if (
|
||||
frm.import_preview &&
|
||||
@@ -439,7 +439,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
},
|
||||
|
||||
show_import_log(frm) {
|
||||
let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
|
||||
let import_log = JSON.parse(frm.doc.import_log || "[]");
|
||||
let logs = import_log;
|
||||
frm.toggle_display("import_log", false);
|
||||
frm.toggle_display("import_log_section", logs.length > 0);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"section_import_preview",
|
||||
"import_preview",
|
||||
"import_log_section",
|
||||
"statement_import_log",
|
||||
"import_log",
|
||||
"show_failed_logs",
|
||||
"import_log_preview",
|
||||
"reference_doctype",
|
||||
@@ -90,6 +90,12 @@
|
||||
"options": "JSON",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "import_log",
|
||||
"fieldtype": "Code",
|
||||
"label": "Import Log",
|
||||
"options": "JSON"
|
||||
},
|
||||
{
|
||||
"fieldname": "import_log_section",
|
||||
"fieldtype": "Section Break",
|
||||
@@ -192,17 +198,11 @@
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "statement_import_log",
|
||||
"fieldtype": "Code",
|
||||
"label": "Statement Import Log",
|
||||
"options": "JSON"
|
||||
}
|
||||
],
|
||||
"hide_toolbar": 1,
|
||||
"links": [],
|
||||
"modified": "2022-09-07 11:11:40.293317",
|
||||
"modified": "2021-05-12 14:17:37.777246",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Statement Import",
|
||||
|
||||
@@ -53,13 +53,15 @@ class BankStatementImport(DataImport):
|
||||
if "Bank Account" not in json.dumps(preview["columns"]):
|
||||
frappe.throw(_("Please add the Bank Account column"))
|
||||
|
||||
from frappe.utils.background_jobs import is_job_queued
|
||||
from frappe.core.page.background_jobs.background_jobs import get_info
|
||||
from frappe.utils.scheduler import is_scheduler_inactive
|
||||
|
||||
if is_scheduler_inactive() and not frappe.flags.in_test:
|
||||
frappe.throw(_("Scheduler is inactive. Cannot import data."), title=_("Scheduler Inactive"))
|
||||
|
||||
if not is_job_queued(self.name):
|
||||
enqueued_jobs = [d.get("job_name") for d in get_info()]
|
||||
|
||||
if self.name not in enqueued_jobs:
|
||||
enqueue(
|
||||
start_import,
|
||||
queue="default",
|
||||
@@ -134,7 +136,7 @@ def start_import(
|
||||
except Exception:
|
||||
frappe.db.rollback()
|
||||
data_import.db_set("status", "Error")
|
||||
data_import.log_error("Bank Statement Import failed")
|
||||
frappe.log_error(title=data_import.name)
|
||||
finally:
|
||||
frappe.flags.in_import = False
|
||||
|
||||
|
||||
@@ -4,15 +4,22 @@
|
||||
frappe.ui.form.on("Bank Transaction", {
|
||||
onload(frm) {
|
||||
frm.set_query("payment_document", "payment_entries", function () {
|
||||
const payment_doctypes = frm.events.get_payment_doctypes(frm);
|
||||
return {
|
||||
filters: {
|
||||
name: ["in", payment_doctypes],
|
||||
name: [
|
||||
"in",
|
||||
[
|
||||
"Payment Entry",
|
||||
"Journal Entry",
|
||||
"Sales Invoice",
|
||||
"Purchase Invoice",
|
||||
"Expense Claim",
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
bank_account: function (frm) {
|
||||
set_bank_statement_filter(frm);
|
||||
},
|
||||
@@ -26,16 +33,6 @@ frappe.ui.form.on("Bank Transaction", {
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
get_payment_doctypes: function() {
|
||||
// get payment doctypes from all the apps
|
||||
return [
|
||||
"Payment Entry",
|
||||
"Journal Entry",
|
||||
"Sales Invoice",
|
||||
"Purchase Invoice",
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Bank Transaction Payments", {
|
||||
|
||||
@@ -58,11 +58,19 @@ class BankTransaction(StatusUpdater):
|
||||
|
||||
def clear_linked_payment_entries(self, for_cancel=False):
|
||||
for payment_entry in self.payment_entries:
|
||||
if payment_entry.payment_document == "Sales Invoice":
|
||||
self.clear_sales_invoice(payment_entry, for_cancel=for_cancel)
|
||||
elif payment_entry.payment_document in get_doctypes_for_bank_reconciliation():
|
||||
if payment_entry.payment_document in [
|
||||
"Payment Entry",
|
||||
"Journal Entry",
|
||||
"Purchase Invoice",
|
||||
"Expense Claim",
|
||||
"Loan Repayment",
|
||||
"Loan Disbursement",
|
||||
]:
|
||||
self.clear_simple_entry(payment_entry, for_cancel=for_cancel)
|
||||
|
||||
elif payment_entry.payment_document == "Sales Invoice":
|
||||
self.clear_sales_invoice(payment_entry, for_cancel=for_cancel)
|
||||
|
||||
def clear_simple_entry(self, payment_entry, for_cancel=False):
|
||||
if payment_entry.payment_document == "Payment Entry":
|
||||
if (
|
||||
@@ -87,12 +95,6 @@ class BankTransaction(StatusUpdater):
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_doctypes_for_bank_reconciliation():
|
||||
"""Get Bank Reconciliation doctypes from all the apps"""
|
||||
return frappe.get_hooks("bank_reconciliation_doctypes")
|
||||
|
||||
|
||||
def get_reconciled_bank_transactions(payment_entry):
|
||||
reconciled_bank_transactions = frappe.get_all(
|
||||
"Bank Transaction Payments",
|
||||
|
||||
@@ -56,7 +56,7 @@ def create_bank_entries(columns, data, bank_account):
|
||||
bank_transaction.submit()
|
||||
success += 1
|
||||
except Exception:
|
||||
bank_transaction.log_error("Bank entry creation failed")
|
||||
frappe.log_error(frappe.get_traceback())
|
||||
errors += 1
|
||||
|
||||
return {"success": success, "errors": errors}
|
||||
@@ -74,7 +74,7 @@ def get_header_mapping(columns, bank_account):
|
||||
|
||||
|
||||
def get_bank_mapping(bank_account):
|
||||
bank_name = frappe.get_cached_value("Bank Account", bank_account, "bank")
|
||||
bank_name = frappe.db.get_value("Bank Account", bank_account, "bank")
|
||||
bank = frappe.get_doc("Bank", bank_name)
|
||||
|
||||
mapping = {row.file_field: row.bank_transaction_field for row in bank.bank_transaction_mapping}
|
||||
|
||||
@@ -5,7 +5,6 @@ import json
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
from frappe.tests.utils import FrappeTestCase
|
||||
|
||||
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
|
||||
get_linked_payments,
|
||||
@@ -19,21 +18,28 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal
|
||||
test_dependencies = ["Item", "Cost Center"]
|
||||
|
||||
|
||||
class TestBankTransaction(FrappeTestCase):
|
||||
def setUp(self):
|
||||
for dt in [
|
||||
"Loan Repayment",
|
||||
"Bank Transaction",
|
||||
"Payment Entry",
|
||||
"Payment Entry Reference",
|
||||
"POS Profile",
|
||||
]:
|
||||
frappe.db.delete(dt)
|
||||
|
||||
class TestBankTransaction(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
make_pos_profile()
|
||||
add_transactions()
|
||||
add_vouchers()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
for bt in frappe.get_all("Bank Transaction"):
|
||||
doc = frappe.get_doc("Bank Transaction", bt.name)
|
||||
if doc.docstatus == 1:
|
||||
doc.cancel()
|
||||
doc.delete()
|
||||
|
||||
# Delete directly in DB to avoid validation errors for countries not allowing deletion
|
||||
frappe.db.sql("""delete from `tabPayment Entry Reference`""")
|
||||
frappe.db.sql("""delete from `tabPayment Entry`""")
|
||||
|
||||
# Delete POS Profile
|
||||
frappe.db.sql("delete from `tabPOS Profile`")
|
||||
|
||||
# This test checks if ERPNext is able to provide a linked payment for a bank transaction based on the amount of the bank transaction.
|
||||
def test_linked_payments(self):
|
||||
bank_transaction = frappe.get_doc(
|
||||
@@ -149,35 +155,6 @@ class TestBankTransaction(FrappeTestCase):
|
||||
is not None
|
||||
)
|
||||
|
||||
def test_matching_loan_repayment(self):
|
||||
from erpnext.loan_management.doctype.loan.test_loan import create_loan_accounts
|
||||
|
||||
create_loan_accounts()
|
||||
bank_account = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Bank Account",
|
||||
"account_name": "Payment Account",
|
||||
"bank": "Citi Bank",
|
||||
"account": "Payment Account - _TC",
|
||||
}
|
||||
).insert(ignore_if_duplicate=True)
|
||||
|
||||
bank_transaction = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Bank Transaction",
|
||||
"description": "Loan Repayment - OPSKATTUZWXXX AT776000000098709837 Herr G",
|
||||
"date": "2018-10-27",
|
||||
"deposit": 500,
|
||||
"currency": "INR",
|
||||
"bank_account": bank_account.name,
|
||||
}
|
||||
).submit()
|
||||
|
||||
repayment_entry = create_loan_and_repayment()
|
||||
|
||||
linked_payments = get_linked_payments(bank_transaction.name, ["loan_repayment", "exact_match"])
|
||||
self.assertEqual(linked_payments[0][2], repayment_entry.name)
|
||||
|
||||
|
||||
def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
|
||||
try:
|
||||
@@ -387,59 +364,3 @@ def add_vouchers():
|
||||
)
|
||||
si.insert()
|
||||
si.submit()
|
||||
|
||||
|
||||
def create_loan_and_repayment():
|
||||
from erpnext.loan_management.doctype.loan.test_loan import (
|
||||
create_loan,
|
||||
create_loan_type,
|
||||
create_repayment_entry,
|
||||
make_loan_disbursement_entry,
|
||||
)
|
||||
from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import (
|
||||
process_loan_interest_accrual_for_term_loans,
|
||||
)
|
||||
from erpnext.setup.doctype.employee.test_employee import make_employee
|
||||
|
||||
create_loan_type(
|
||||
"Personal Loan",
|
||||
500000,
|
||||
8.4,
|
||||
is_term_loan=1,
|
||||
mode_of_payment="Cash",
|
||||
disbursement_account="Disbursement Account - _TC",
|
||||
payment_account="Payment Account - _TC",
|
||||
loan_account="Loan Account - _TC",
|
||||
interest_income_account="Interest Income Account - _TC",
|
||||
penalty_income_account="Penalty Income Account - _TC",
|
||||
)
|
||||
|
||||
applicant = make_employee("test_bank_reco@loan.com", company="_Test Company")
|
||||
loan = create_loan(applicant, "Personal Loan", 5000, "Repay Over Number of Periods", 20)
|
||||
loan = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Loan",
|
||||
"applicant_type": "Employee",
|
||||
"company": "_Test Company",
|
||||
"applicant": applicant,
|
||||
"loan_type": "Personal Loan",
|
||||
"loan_amount": 5000,
|
||||
"repayment_method": "Repay Fixed Amount per Period",
|
||||
"monthly_repayment_amount": 500,
|
||||
"repayment_start_date": "2018-09-27",
|
||||
"is_term_loan": 1,
|
||||
"posting_date": "2018-09-27",
|
||||
}
|
||||
).insert()
|
||||
|
||||
make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date="2018-09-27")
|
||||
process_loan_interest_accrual_for_term_loans(posting_date="2018-10-27")
|
||||
|
||||
repayment_entry = create_repayment_entry(
|
||||
loan.name,
|
||||
applicant,
|
||||
"2018-10-27",
|
||||
500,
|
||||
)
|
||||
repayment_entry.submit()
|
||||
return repayment_entry
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2016-05-16 11:42:29.632528",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
@@ -10,7 +9,6 @@
|
||||
"budget_against",
|
||||
"company",
|
||||
"cost_center",
|
||||
"naming_series",
|
||||
"project",
|
||||
"fiscal_year",
|
||||
"column_break_3",
|
||||
@@ -192,26 +190,15 @@
|
||||
"label": "Budget Accounts",
|
||||
"options": "Budget Account",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Series",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"set_only_once": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2022-10-10 22:14:36.361509",
|
||||
"modified": "2020-10-06 15:13:54.055854",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Budget",
|
||||
"naming_rule": "By \"Naming Series\" field",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
@@ -233,6 +220,5 @@
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.naming import make_autoname
|
||||
from frappe.utils import add_months, flt, fmt_money, get_last_day, getdate
|
||||
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||
@@ -22,6 +23,11 @@ class DuplicateBudgetError(frappe.ValidationError):
|
||||
|
||||
|
||||
class Budget(Document):
|
||||
def autoname(self):
|
||||
self.name = make_autoname(
|
||||
self.get(frappe.scrub(self.budget_against)) + "/" + self.fiscal_year + "/.###"
|
||||
)
|
||||
|
||||
def validate(self):
|
||||
if not self.get(frappe.scrub(self.budget_against)):
|
||||
frappe.throw(_("{0} is mandatory").format(self.budget_against))
|
||||
@@ -59,7 +65,7 @@ class Budget(Document):
|
||||
account_list = []
|
||||
for d in self.get("accounts"):
|
||||
if d.account:
|
||||
account_details = frappe.get_cached_value(
|
||||
account_details = frappe.db.get_value(
|
||||
"Account", d.account, ["is_group", "company", "report_type"], as_dict=1
|
||||
)
|
||||
|
||||
@@ -103,11 +109,8 @@ class Budget(Document):
|
||||
):
|
||||
self.applicable_on_booking_actual_expenses = 1
|
||||
|
||||
def before_naming(self):
|
||||
self.naming_series = f"{{{frappe.scrub(self.budget_against)}}}./.{self.fiscal_year}/.###"
|
||||
|
||||
|
||||
def validate_expense_against_budget(args, expense_amount=0):
|
||||
def validate_expense_against_budget(args):
|
||||
args = frappe._dict(args)
|
||||
|
||||
if args.get("company") and not args.fiscal_year:
|
||||
@@ -175,13 +178,13 @@ def validate_expense_against_budget(args, expense_amount=0):
|
||||
) # nosec
|
||||
|
||||
if budget_records:
|
||||
validate_budget_records(args, budget_records, expense_amount)
|
||||
validate_budget_records(args, budget_records)
|
||||
|
||||
|
||||
def validate_budget_records(args, budget_records, expense_amount):
|
||||
def validate_budget_records(args, budget_records):
|
||||
for budget in budget_records:
|
||||
if flt(budget.budget_amount):
|
||||
amount = expense_amount or get_amount(args, budget)
|
||||
amount = get_amount(args, budget)
|
||||
yearly_action, monthly_action = get_actions(args, budget)
|
||||
|
||||
if monthly_action in ["Stop", "Warn"]:
|
||||
@@ -306,7 +309,7 @@ def get_other_condition(args, budget, for_doc):
|
||||
|
||||
if args.get("fiscal_year"):
|
||||
date_field = "schedule_date" if for_doc == "Material Request" else "transaction_date"
|
||||
start_date, end_date = frappe.get_cached_value(
|
||||
start_date, end_date = frappe.db.get_value(
|
||||
"Fiscal Year", args.get("fiscal_year"), ["year_start_date", "year_end_date"]
|
||||
)
|
||||
|
||||
@@ -379,7 +382,7 @@ def get_accumulated_monthly_budget(monthly_distribution, posting_date, fiscal_ye
|
||||
):
|
||||
distribution.setdefault(d.month, d.percentage_allocation)
|
||||
|
||||
dt = frappe.get_cached_value("Fiscal Year", fiscal_year, "year_start_date")
|
||||
dt = frappe.db.get_value("Fiscal Year", fiscal_year, "year_start_date")
|
||||
accumulated_percentage = 0.0
|
||||
|
||||
while dt <= getdate(posting_date):
|
||||
|
||||
@@ -334,39 +334,6 @@ class TestBudget(unittest.TestCase):
|
||||
budget.cancel()
|
||||
jv.cancel()
|
||||
|
||||
def test_monthly_budget_against_main_cost_center(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
from erpnext.accounts.doctype.cost_center_allocation.test_cost_center_allocation import (
|
||||
create_cost_center_allocation,
|
||||
)
|
||||
|
||||
cost_centers = [
|
||||
"Main Budget Cost Center 1",
|
||||
"Sub Budget Cost Center 1",
|
||||
"Sub Budget Cost Center 2",
|
||||
]
|
||||
|
||||
for cc in cost_centers:
|
||||
create_cost_center(cost_center_name=cc, company="_Test Company")
|
||||
|
||||
create_cost_center_allocation(
|
||||
"_Test Company",
|
||||
"Main Budget Cost Center 1 - _TC",
|
||||
{"Sub Budget Cost Center 1 - _TC": 60, "Sub Budget Cost Center 2 - _TC": 40},
|
||||
)
|
||||
|
||||
make_budget(budget_against="Cost Center", cost_center="Main Budget Cost Center 1 - _TC")
|
||||
|
||||
jv = make_journal_entry(
|
||||
"_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Bank - _TC",
|
||||
400000,
|
||||
"Main Budget Cost Center 1 - _TC",
|
||||
posting_date=nowdate(),
|
||||
)
|
||||
|
||||
self.assertRaises(BudgetError, jv.submit)
|
||||
|
||||
|
||||
def set_total_expense_zero(posting_date, budget_against_field=None, budget_against_CC=None):
|
||||
if budget_against_field == "project":
|
||||
|
||||
1
erpnext/accounts/doctype/c_form/README.md
Normal file
1
erpnext/accounts/doctype/c_form/README.md
Normal file
@@ -0,0 +1 @@
|
||||
C Form (India specific only) - Will be deprecated.
|
||||
43
erpnext/accounts/doctype/c_form/c_form.js
Normal file
43
erpnext/accounts/doctype/c_form/c_form.js
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
//c-form js file
|
||||
// -----------------------------
|
||||
|
||||
frappe.ui.form.on('C-Form', {
|
||||
setup(frm) {
|
||||
frm.fields_dict.invoices.grid.get_field("invoice_no").get_query = function(doc) {
|
||||
return {
|
||||
filters: {
|
||||
"docstatus": 1,
|
||||
"customer": doc.customer,
|
||||
"company": doc.company,
|
||||
"c_form_applicable": 'Yes',
|
||||
"c_form_no": ''
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
frm.fields_dict.state.get_query = function() {
|
||||
return {
|
||||
filters: {
|
||||
country: "India"
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on('C-Form Invoice Detail', {
|
||||
invoice_no(frm, cdt, cdn) {
|
||||
let d = frappe.get_doc(cdt, cdn);
|
||||
|
||||
if (d.invoice_no) {
|
||||
frm.call('get_invoice_details', {
|
||||
invoice_no: d.invoice_no
|
||||
}).then(r => {
|
||||
frappe.model.set_value(cdt, cdn, r.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
511
erpnext/accounts/doctype/c_form/c_form.json
Normal file
511
erpnext/accounts/doctype/c_form/c_form.json
Normal file
@@ -0,0 +1,511 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "naming_series:",
|
||||
"beta": 0,
|
||||
"creation": "2013-03-07 11:55:06",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"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": "Series",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "ACC-CF-.YYYY.-",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "c_form_no",
|
||||
"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": "C-Form No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "received_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": "Received Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "customer",
|
||||
"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": "Customer",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Customer",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break1",
|
||||
"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,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "50%",
|
||||
"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%"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 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": 0,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "quarter",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Quarter",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nI\nII\nIII\nIV",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "total_amount",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Total Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "state",
|
||||
"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": "State",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break0",
|
||||
"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,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "invoices",
|
||||
"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": "Invoices",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "C-Form Invoice Detail",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "total_invoiced_amount",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Total Invoiced Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 1,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Amended From",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "C-Form",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 3,
|
||||
"modified": "2018-08-21 14:44:30.558767",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "C-Form",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"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
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"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": 0,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 1,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "All",
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_order": "DESC",
|
||||
"timeline_field": "customer",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
96
erpnext/accounts/doctype/c_form/c_form.py
Normal file
96
erpnext/accounts/doctype/c_form/c_form.py
Normal file
@@ -0,0 +1,96 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import flt
|
||||
|
||||
|
||||
class CForm(Document):
|
||||
def validate(self):
|
||||
"""Validate invoice that c-form is applicable
|
||||
and no other c-form is received for that"""
|
||||
|
||||
for d in self.get("invoices"):
|
||||
if d.invoice_no:
|
||||
inv = frappe.db.sql(
|
||||
"""select c_form_applicable, c_form_no from
|
||||
`tabSales Invoice` where name = %s and docstatus = 1""",
|
||||
d.invoice_no,
|
||||
)
|
||||
|
||||
if inv and inv[0][0] != "Yes":
|
||||
frappe.throw(_("C-form is not applicable for Invoice: {0}").format(d.invoice_no))
|
||||
|
||||
elif inv and inv[0][1] and inv[0][1] != self.name:
|
||||
frappe.throw(
|
||||
_(
|
||||
"""Invoice {0} is tagged in another C-form: {1}.
|
||||
If you want to change C-form no for this invoice,
|
||||
please remove invoice no from the previous c-form and then try again""".format(
|
||||
d.invoice_no, inv[0][1]
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
elif not inv:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Row {0}: Invoice {1} is invalid, it might be cancelled / does not exist. \
|
||||
Please enter a valid Invoice".format(
|
||||
d.idx, d.invoice_no
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def on_update(self):
|
||||
"""Update C-Form No on invoices"""
|
||||
self.set_total_invoiced_amount()
|
||||
|
||||
def on_submit(self):
|
||||
self.set_cform_in_sales_invoices()
|
||||
|
||||
def before_cancel(self):
|
||||
# remove cform reference
|
||||
frappe.db.sql("""update `tabSales Invoice` set c_form_no=null where c_form_no=%s""", self.name)
|
||||
|
||||
def set_cform_in_sales_invoices(self):
|
||||
inv = [d.invoice_no for d in self.get("invoices")]
|
||||
if inv:
|
||||
frappe.db.sql(
|
||||
"""update `tabSales Invoice` set c_form_no=%s, modified=%s where name in (%s)"""
|
||||
% ("%s", "%s", ", ".join(["%s"] * len(inv))),
|
||||
tuple([self.name, self.modified] + inv),
|
||||
)
|
||||
|
||||
frappe.db.sql(
|
||||
"""update `tabSales Invoice` set c_form_no = null, modified = %s
|
||||
where name not in (%s) and ifnull(c_form_no, '') = %s"""
|
||||
% ("%s", ", ".join(["%s"] * len(inv)), "%s"),
|
||||
tuple([self.modified] + inv + [self.name]),
|
||||
)
|
||||
else:
|
||||
frappe.throw(_("Please enter atleast 1 invoice in the table"))
|
||||
|
||||
def set_total_invoiced_amount(self):
|
||||
total = sum(flt(d.grand_total) for d in self.get("invoices"))
|
||||
frappe.db.set(self, "total_invoiced_amount", total)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_invoice_details(self, invoice_no):
|
||||
"""Pull details from invoices for referrence"""
|
||||
if invoice_no:
|
||||
inv = frappe.db.get_value(
|
||||
"Sales Invoice",
|
||||
invoice_no,
|
||||
["posting_date", "territory", "base_net_total", "base_grand_total"],
|
||||
as_dict=True,
|
||||
)
|
||||
return {
|
||||
"invoice_date": inv.posting_date,
|
||||
"territory": inv.territory,
|
||||
"net_total": inv.base_net_total,
|
||||
"grand_total": inv.base_grand_total,
|
||||
}
|
||||
10
erpnext/accounts/doctype/c_form/test_c_form.py
Normal file
10
erpnext/accounts/doctype/c_form/test_c_form.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('C-Form')
|
||||
|
||||
|
||||
class TestCForm(unittest.TestCase):
|
||||
pass
|
||||
1
erpnext/accounts/doctype/c_form_invoice_detail/README.md
Normal file
1
erpnext/accounts/doctype/c_form_invoice_detail/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Invoice detail for parent C-Form.
|
||||
@@ -0,0 +1,168 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:27:38",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "invoice_no",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Sales Invoice",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "160px",
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "160px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "invoice_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "120px",
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "120px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "",
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Territory",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Territory",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "120px",
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "120px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "net_total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Net Total",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "120px",
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "120px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "grand_total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Grand Total",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "120px",
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "120px"
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-11 03:27:58.768719",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "C-Form Invoice Detail",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class CFormInvoiceDetail(Document):
|
||||
pass
|
||||
@@ -45,14 +45,14 @@ def validate_columns(data):
|
||||
|
||||
@frappe.whitelist()
|
||||
def validate_company(company):
|
||||
parent_company, allow_account_creation_against_child_company = frappe.get_cached_value(
|
||||
"Company", company, ["parent_company", "allow_account_creation_against_child_company"]
|
||||
parent_company, allow_account_creation_against_child_company = frappe.db.get_value(
|
||||
"Company", {"name": company}, ["parent_company", "allow_account_creation_against_child_company"]
|
||||
)
|
||||
|
||||
if parent_company and (not allow_account_creation_against_child_company):
|
||||
msg = _("{} is a child company.").format(frappe.bold(company)) + " "
|
||||
msg += _("Please import accounts against parent company or enable {} in company master.").format(
|
||||
frappe.bold(_("Allow Account Creation Against Child Company"))
|
||||
frappe.bold("Allow Account Creation Against Child Company")
|
||||
)
|
||||
frappe.throw(msg, title=_("Wrong Company"))
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class CostCenter(NestedSet):
|
||||
from erpnext.accounts.utils import get_autoname_with_number
|
||||
|
||||
self.name = get_autoname_with_number(
|
||||
self.cost_center_number, self.cost_center_name, self.company
|
||||
self.cost_center_number, self.cost_center_name, None, self.company
|
||||
)
|
||||
|
||||
def validate(self):
|
||||
|
||||
@@ -29,6 +29,7 @@ def test_create_test_data():
|
||||
"item_name": "_Test Tesla Car",
|
||||
"apply_warehouse_wise_reorder_level": 0,
|
||||
"warehouse": "Stores - _TC",
|
||||
"gst_hsn_code": "999800",
|
||||
"valuation_rate": 5000,
|
||||
"standard_rate": 5000,
|
||||
"item_defaults": [
|
||||
|
||||
@@ -11,8 +11,6 @@ from frappe.utils import nowdate
|
||||
class CurrencyExchangeSettings(Document):
|
||||
def validate(self):
|
||||
self.set_parameters_and_result()
|
||||
if frappe.flags.in_test or frappe.flags.in_install or frappe.flags.in_setup_wizard:
|
||||
return
|
||||
response, value = self.validate_parameters()
|
||||
self.validate_result(response, value)
|
||||
|
||||
@@ -37,6 +35,9 @@ class CurrencyExchangeSettings(Document):
|
||||
self.append("req_params", {"key": "symbols", "value": "{to_currency}"})
|
||||
|
||||
def validate_parameters(self):
|
||||
if frappe.flags.in_test:
|
||||
return None, None
|
||||
|
||||
params = {}
|
||||
for row in self.req_params:
|
||||
params[row.key] = row.value.format(
|
||||
@@ -58,6 +59,9 @@ class CurrencyExchangeSettings(Document):
|
||||
return response, value
|
||||
|
||||
def validate_result(self, response, value):
|
||||
if frappe.flags.in_test:
|
||||
return
|
||||
|
||||
try:
|
||||
for key in self.result_key:
|
||||
value = value[
|
||||
|
||||
@@ -19,7 +19,7 @@ class Dunning(AccountsController):
|
||||
self.validate_overdue_days()
|
||||
self.validate_amount()
|
||||
if not self.income_account:
|
||||
self.income_account = frappe.get_cached_value("Company", self.company, "default_income_account")
|
||||
self.income_account = frappe.db.get_value("Company", self.company, "default_income_account")
|
||||
|
||||
def validate_overdue_days(self):
|
||||
self.overdue_days = (getdate(self.posting_date) - getdate(self.due_date)).days or 0
|
||||
|
||||
@@ -1,88 +1,322 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "ACC-ERR-.YYYY.-.#####",
|
||||
"beta": 0,
|
||||
"creation": "2018-04-13 18:25:55.943587",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"posting_date",
|
||||
"column_break_2",
|
||||
"company",
|
||||
"section_break_4",
|
||||
"get_entries",
|
||||
"accounts",
|
||||
"section_break_6",
|
||||
"total_gain_loss",
|
||||
"amended_from"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Today",
|
||||
"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": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Posting Date",
|
||||
"reqd": 1
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break"
|
||||
"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_in_quick_entry": 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",
|
||||
"reqd": 1
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break"
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "get_entries",
|
||||
"fieldtype": "Button",
|
||||
"label": "Get Entries"
|
||||
"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": "Get Entries",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "accounts",
|
||||
"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": "Exchange Rate Revaluation Account",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Exchange Rate Revaluation Account",
|
||||
"reqd": 1
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break"
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "total_gain_loss",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Total Gain/Loss",
|
||||
"options": "Company:company:default_currency",
|
||||
"read_only": 1
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Amended From",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Exchange Rate Revaluation",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2022-11-17 10:28:03.911554",
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-08-21 16:15:34.660715",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Exchange Rate Revaluation",
|
||||
"naming_rule": "Expression (old style)",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
@@ -92,10 +326,14 @@
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
@@ -107,10 +345,14 @@
|
||||
"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": 1,
|
||||
"write": 1
|
||||
@@ -122,17 +364,26 @@
|
||||
"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": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
@@ -222,7 +222,7 @@ class ExchangeRateRevaluation(Document):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_account_details(account, company, posting_date, party_type=None, party=None):
|
||||
account_currency, account_type = frappe.get_cached_value(
|
||||
account_currency, account_type = frappe.db.get_value(
|
||||
"Account", account, ["account_currency", "account_type"]
|
||||
)
|
||||
if account_type in ["Receivable", "Payable"] and not (party_type and party):
|
||||
@@ -233,10 +233,6 @@ def get_account_details(account, company, posting_date, party_type=None, party=N
|
||||
balance = get_balance_on(
|
||||
account, date=posting_date, party_type=party_type, party=party, in_account_currency=False
|
||||
)
|
||||
account_details = {
|
||||
"account_currency": account_currency,
|
||||
}
|
||||
|
||||
if balance:
|
||||
balance_in_account_currency = get_balance_on(
|
||||
account, date=posting_date, party_type=party_type, party=party
|
||||
@@ -246,14 +242,13 @@ def get_account_details(account, company, posting_date, party_type=None, party=N
|
||||
)
|
||||
new_exchange_rate = get_exchange_rate(account_currency, company_currency, posting_date)
|
||||
new_balance_in_base_currency = balance_in_account_currency * new_exchange_rate
|
||||
account_details = account_details.update(
|
||||
{
|
||||
account_details = {
|
||||
"account_currency": account_currency,
|
||||
"balance_in_base_currency": balance,
|
||||
"balance_in_account_currency": balance_in_account_currency,
|
||||
"current_exchange_rate": current_exchange_rate,
|
||||
"new_exchange_rate": new_exchange_rate,
|
||||
"new_balance_in_base_currency": new_balance_in_base_currency,
|
||||
}
|
||||
)
|
||||
|
||||
return account_details
|
||||
|
||||
@@ -1,120 +1,475 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-04-13 18:30:06.110433",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"account",
|
||||
"party_type",
|
||||
"party",
|
||||
"column_break_2",
|
||||
"account_currency",
|
||||
"balance_in_account_currency",
|
||||
"balances",
|
||||
"current_exchange_rate",
|
||||
"balance_in_base_currency",
|
||||
"column_break_9",
|
||||
"new_exchange_rate",
|
||||
"new_balance_in_base_currency",
|
||||
"gain_loss"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "account",
|
||||
"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": "Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"reqd": 1
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "party_type",
|
||||
"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": "Party Type",
|
||||
"options": "DocType"
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "party",
|
||||
"fieldtype": "Dynamic 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": "Party",
|
||||
"options": "party_type"
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "party_type",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break"
|
||||
"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_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "account_currency",
|
||||
"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": "Account Currency",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Currency",
|
||||
"read_only": 1
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "balance_in_account_currency",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Balance In Account Currency",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "account_currency",
|
||||
"read_only": 1
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "balances",
|
||||
"fieldtype": "Section Break"
|
||||
"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,
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "current_exchange_rate",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Current Exchange Rate",
|
||||
"read_only": 1
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "balance_in_base_currency",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Balance In Base Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"read_only": 1
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_9",
|
||||
"fieldtype": "Column Break"
|
||||
"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_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "new_exchange_rate",
|
||||
"fieldtype": "Float",
|
||||
"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": "New Exchange Rate",
|
||||
"reqd": 1
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "new_balance_in_base_currency",
|
||||
"fieldtype": "Currency",
|
||||
"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": "New Balance In Base Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"read_only": 1
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "gain_loss",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Gain/Loss",
|
||||
"options": "Company:company:default_currency",
|
||||
"read_only": 1
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2022-11-17 10:26:18.302728",
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-06-26 18:57:51.762345",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Exchange Rate Revaluation Account",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
@@ -9,6 +9,10 @@ from frappe.model.document import Document
|
||||
from frappe.utils import add_days, add_years, cstr, getdate
|
||||
|
||||
|
||||
class FiscalYearIncorrectDate(frappe.ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class FiscalYear(Document):
|
||||
@frappe.whitelist()
|
||||
def set_as_default(self):
|
||||
@@ -49,18 +53,23 @@ class FiscalYear(Document):
|
||||
)
|
||||
|
||||
def validate_dates(self):
|
||||
self.validate_from_to_dates("year_start_date", "year_end_date")
|
||||
if self.is_short_year:
|
||||
# Fiscal Year can be shorter than one year, in some jurisdictions
|
||||
# under certain circumstances. For example, in the USA and Germany.
|
||||
return
|
||||
|
||||
if getdate(self.year_start_date) > getdate(self.year_end_date):
|
||||
frappe.throw(
|
||||
_("Fiscal Year Start Date should be one year earlier than Fiscal Year End Date"),
|
||||
FiscalYearIncorrectDate,
|
||||
)
|
||||
|
||||
date = getdate(self.year_start_date) + relativedelta(years=1) - relativedelta(days=1)
|
||||
|
||||
if getdate(self.year_end_date) != date:
|
||||
frappe.throw(
|
||||
_("Fiscal Year End Date should be one year after Fiscal Year Start Date"),
|
||||
frappe.exceptions.InvalidDates,
|
||||
FiscalYearIncorrectDate,
|
||||
)
|
||||
|
||||
def on_update(self):
|
||||
@@ -160,6 +169,5 @@ def auto_create_fiscal_year():
|
||||
|
||||
|
||||
def get_from_and_to_date(fiscal_year):
|
||||
fields = ["year_start_date", "year_end_date"]
|
||||
cached_results = frappe.get_cached_value("Fiscal Year", fiscal_year, fields, as_dict=1)
|
||||
return dict(from_date=cached_results.year_start_date, to_date=cached_results.year_end_date)
|
||||
fields = ["year_start_date as from_date", "year_end_date as to_date"]
|
||||
return frappe.db.get_value("Fiscal Year", fiscal_year, fields, as_dict=1)
|
||||
|
||||
@@ -7,6 +7,8 @@ import unittest
|
||||
import frappe
|
||||
from frappe.utils import now_datetime
|
||||
|
||||
from erpnext.accounts.doctype.fiscal_year.fiscal_year import FiscalYearIncorrectDate
|
||||
|
||||
test_ignore = ["Company"]
|
||||
|
||||
|
||||
@@ -24,7 +26,7 @@ class TestFiscalYear(unittest.TestCase):
|
||||
}
|
||||
)
|
||||
|
||||
self.assertRaises(frappe.exceptions.InvalidDates, fy.insert)
|
||||
self.assertRaises(FiscalYearIncorrectDate, fy.insert)
|
||||
|
||||
|
||||
def test_record_generator():
|
||||
@@ -33,8 +35,8 @@ def test_record_generator():
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Short Fiscal Year 2011",
|
||||
"is_short_year": 1,
|
||||
"year_start_date": "2011-04-01",
|
||||
"year_end_date": "2011-12-31",
|
||||
"year_end_date": "2011-04-01",
|
||||
"year_start_date": "2011-12-31",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
|
||||
frappe.ui.form.on('GL Entry', {
|
||||
refresh: function(frm) {
|
||||
frm.page.btn_secondary.hide()
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -42,7 +42,7 @@ class GLEntry(Document):
|
||||
self.validate_and_set_fiscal_year()
|
||||
self.pl_must_have_cost_center()
|
||||
|
||||
if not self.flags.from_repost and self.voucher_type != "Period Closing Voucher":
|
||||
if not self.flags.from_repost:
|
||||
self.check_mandatory()
|
||||
self.validate_cost_center()
|
||||
self.check_pl_account()
|
||||
@@ -51,17 +51,13 @@ class GLEntry(Document):
|
||||
|
||||
def on_update(self):
|
||||
adv_adj = self.flags.adv_adj
|
||||
if not self.flags.from_repost and self.voucher_type != "Period Closing Voucher":
|
||||
if not self.flags.from_repost:
|
||||
self.validate_account_details(adv_adj)
|
||||
self.validate_dimensions_for_pl_and_bs()
|
||||
self.validate_allowed_dimensions()
|
||||
validate_balance_type(self.account, adv_adj)
|
||||
validate_frozen_account(self.account, adv_adj)
|
||||
|
||||
if frappe.get_cached_value("Account", self.account, "account_type") not in [
|
||||
"Receivable",
|
||||
"Payable",
|
||||
]:
|
||||
# Update outstanding amt on against voucher
|
||||
if (
|
||||
self.against_voucher_type in ["Journal Entry", "Sales Invoice", "Purchase Invoice", "Fees"]
|
||||
@@ -120,7 +116,7 @@ class GLEntry(Document):
|
||||
frappe.throw(msg, title=_("Missing Cost Center"))
|
||||
|
||||
def validate_dimensions_for_pl_and_bs(self):
|
||||
account_type = frappe.get_cached_value("Account", self.account, "report_type")
|
||||
account_type = frappe.db.get_value("Account", self.account, "report_type")
|
||||
|
||||
for dimension in get_checks_for_pl_and_bs_accounts():
|
||||
if (
|
||||
@@ -188,7 +184,7 @@ class GLEntry(Document):
|
||||
def check_pl_account(self):
|
||||
if (
|
||||
self.is_opening == "Yes"
|
||||
and frappe.get_cached_value("Account", self.account, "report_type") == "Profit and Loss"
|
||||
and frappe.db.get_value("Account", self.account, "report_type") == "Profit and Loss"
|
||||
and not self.is_cancelled
|
||||
):
|
||||
frappe.throw(
|
||||
@@ -273,15 +269,10 @@ class GLEntry(Document):
|
||||
if not self.fiscal_year:
|
||||
self.fiscal_year = get_fiscal_year(self.posting_date, company=self.company)[0]
|
||||
|
||||
def on_cancel(self):
|
||||
msg = _("Individual GL Entry cannot be cancelled.")
|
||||
msg += "<br>" + _("Please cancel related transaction.")
|
||||
frappe.throw(msg)
|
||||
|
||||
|
||||
def validate_balance_type(account, adv_adj=False):
|
||||
if not adv_adj and account:
|
||||
balance_must_be = frappe.get_cached_value("Account", account, "balance_must_be")
|
||||
balance_must_be = frappe.db.get_value("Account", account, "balance_must_be")
|
||||
if balance_must_be:
|
||||
balance = frappe.db.sql(
|
||||
"""select sum(debit) - sum(credit)
|
||||
@@ -366,7 +357,7 @@ def update_outstanding_amt(
|
||||
if against_voucher_type in ["Sales Invoice", "Purchase Invoice", "Fees"]:
|
||||
ref_doc = frappe.get_doc(against_voucher_type, against_voucher)
|
||||
|
||||
# Didn't use db_set for optimization purpose
|
||||
# Didn't use db_set for optimisation purpose
|
||||
ref_doc.outstanding_amount = bal
|
||||
frappe.db.set_value(against_voucher_type, against_voucher, "outstanding_amount", bal)
|
||||
|
||||
|
||||
82
erpnext/accounts/doctype/gst_account/gst_account.json
Normal file
82
erpnext/accounts/doctype/gst_account/gst_account.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2018-01-02 15:48:58.768352",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"company",
|
||||
"cgst_account",
|
||||
"sgst_account",
|
||||
"igst_account",
|
||||
"cess_account",
|
||||
"is_reverse_charge_account"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"columns": 1,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "cgst_account",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "CGST Account",
|
||||
"options": "Account",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "sgst_account",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "SGST Account",
|
||||
"options": "Account",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "igst_account",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "IGST Account",
|
||||
"options": "Account",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "cess_account",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "CESS Account",
|
||||
"options": "Account"
|
||||
},
|
||||
{
|
||||
"columns": 1,
|
||||
"default": "0",
|
||||
"fieldname": "is_reverse_charge_account",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Is Reverse Charge Account"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-04-09 12:30:25.889993",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "GST Account",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
||||
9
erpnext/accounts/doctype/gst_account/gst_account.py
Normal file
9
erpnext/accounts/doctype/gst_account/gst_account.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class GSTAccount(Document):
|
||||
pass
|
||||
@@ -21,7 +21,7 @@ class ItemTaxTemplate(Document):
|
||||
check_list = []
|
||||
for d in self.get("taxes"):
|
||||
if d.tax_type:
|
||||
account_type = frappe.get_cached_value("Account", d.tax_type, "account_type")
|
||||
account_type = frappe.db.get_value("Account", d.tax_type, "account_type")
|
||||
|
||||
if account_type not in [
|
||||
"Tax",
|
||||
|
||||
@@ -149,6 +149,22 @@ frappe.ui.form.on("Journal Entry", {
|
||||
}
|
||||
});
|
||||
}
|
||||
else if(frm.doc.voucher_type=="Opening Entry") {
|
||||
return frappe.call({
|
||||
type:"GET",
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_opening_accounts",
|
||||
args: {
|
||||
"company": frm.doc.company
|
||||
},
|
||||
callback: function(r) {
|
||||
frappe.model.clear_table(frm.doc, "accounts");
|
||||
if(r.message) {
|
||||
update_jv_details(frm.doc, r.message);
|
||||
}
|
||||
cur_frm.set_value("is_opening", "Yes");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -173,8 +189,8 @@ frappe.ui.form.on("Journal Entry", {
|
||||
var update_jv_details = function(doc, r) {
|
||||
$.each(r, function(i, d) {
|
||||
var row = frappe.model.add_child(doc, "Journal Entry Account", "accounts");
|
||||
frappe.model.set_value(row.doctype, row.name, "account", d.account)
|
||||
frappe.model.set_value(row.doctype, row.name, "balance", d.balance)
|
||||
row.account = d.account;
|
||||
row.balance = d.balance;
|
||||
});
|
||||
refresh_field("accounts");
|
||||
}
|
||||
@@ -224,6 +240,25 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
|
||||
me.frm.set_query("reference_name", "accounts", function(doc, cdt, cdn) {
|
||||
var jvd = frappe.get_doc(cdt, cdn);
|
||||
|
||||
// expense claim
|
||||
if(jvd.reference_type==="Expense Claim") {
|
||||
return {
|
||||
filters: {
|
||||
'total_sanctioned_amount': ['>', 0],
|
||||
'status': ['!=', 'Paid'],
|
||||
'docstatus': 1
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if(jvd.reference_type==="Employee Advance") {
|
||||
return {
|
||||
filters: {
|
||||
'docstatus': 1
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// journal entry
|
||||
if(jvd.reference_type==="Journal Entry") {
|
||||
frappe.model.validate_missing(jvd, "account");
|
||||
@@ -236,6 +271,13 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
|
||||
};
|
||||
}
|
||||
|
||||
// payroll entry
|
||||
if(jvd.reference_type==="Payroll Entry") {
|
||||
return {
|
||||
query: "erpnext.payroll.doctype.payroll_entry.payroll_entry.get_payroll_entries_for_jv",
|
||||
};
|
||||
}
|
||||
|
||||
var out = {
|
||||
filters: [
|
||||
[jvd.reference_type, "docstatus", "=", 1]
|
||||
@@ -253,6 +295,9 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
|
||||
var party_account_field = jvd.reference_type==="Sales Invoice" ? "debit_to": "credit_to";
|
||||
out.filters.push([jvd.reference_type, party_account_field, "=", jvd.account]);
|
||||
|
||||
if (in_list(['Debit Note', 'Credit Note'], doc.voucher_type)) {
|
||||
out.filters.push([jvd.reference_type, "is_return", "=", 1]);
|
||||
}
|
||||
}
|
||||
|
||||
if(in_list(["Sales Order", "Purchase Order"], jvd.reference_type)) {
|
||||
@@ -309,7 +354,8 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
|
||||
}
|
||||
}
|
||||
|
||||
get_outstanding(doctype, docname, company, child) {
|
||||
get_outstanding(doctype, docname, company, child, due_date) {
|
||||
var me = this;
|
||||
var args = {
|
||||
"doctype": doctype,
|
||||
"docname": docname,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"allow_auto_repeat": 1,
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2022-01-25 10:29:58.717206",
|
||||
"creation": "2013-03-25 10:53:52",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"engine": "InnoDB",
|
||||
@@ -13,7 +13,6 @@
|
||||
"voucher_type",
|
||||
"naming_series",
|
||||
"finance_book",
|
||||
"process_deferred_accounting",
|
||||
"reversal_of",
|
||||
"tax_withholding_category",
|
||||
"column_break1",
|
||||
@@ -137,8 +136,7 @@
|
||||
"fieldname": "finance_book",
|
||||
"fieldtype": "Link",
|
||||
"label": "Finance Book",
|
||||
"options": "Finance Book",
|
||||
"read_only": 1
|
||||
"options": "Finance Book"
|
||||
},
|
||||
{
|
||||
"fieldname": "2_add_edit_gl_entries",
|
||||
@@ -526,20 +524,13 @@
|
||||
"label": "Reversal Of",
|
||||
"options": "Journal Entry",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "process_deferred_accounting",
|
||||
"fieldtype": "Link",
|
||||
"label": "Process Deferred Accounting",
|
||||
"options": "Process Deferred Accounting",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 176,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2022-06-23 22:01:32.348337",
|
||||
"modified": "2022-01-04 13:39:36.485954",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Entry",
|
||||
@@ -587,7 +578,6 @@
|
||||
"search_fields": "voucher_type,posting_date, due_date, cheque_no",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"title_field": "title",
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -18,12 +18,14 @@ from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category
|
||||
)
|
||||
from erpnext.accounts.party import get_party_account
|
||||
from erpnext.accounts.utils import (
|
||||
check_if_stock_and_account_balance_synced,
|
||||
get_account_currency,
|
||||
get_balance_on,
|
||||
get_stock_accounts,
|
||||
get_stock_and_account_balance,
|
||||
)
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount
|
||||
|
||||
|
||||
class StockAccountInvalidTransaction(frappe.ValidationError):
|
||||
@@ -65,6 +67,7 @@ class JournalEntry(AccountsController):
|
||||
self.set_against_account()
|
||||
self.create_remarks()
|
||||
self.set_print_format_fields()
|
||||
self.validate_expense_claim()
|
||||
self.validate_credit_debit_note()
|
||||
self.validate_empty_accounts_table()
|
||||
self.set_account_and_party_balance()
|
||||
@@ -81,21 +84,30 @@ class JournalEntry(AccountsController):
|
||||
self.check_credit_limit()
|
||||
self.make_gl_entries()
|
||||
self.update_advance_paid()
|
||||
self.update_expense_claim()
|
||||
self.update_inter_company_jv()
|
||||
self.update_invoice_discounting()
|
||||
self.update_status_for_full_and_final_statement()
|
||||
check_if_stock_and_account_balance_synced(
|
||||
self.posting_date, self.company, self.doctype, self.name
|
||||
)
|
||||
|
||||
def on_cancel(self):
|
||||
from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries
|
||||
from erpnext.payroll.doctype.salary_slip.salary_slip import unlink_ref_doc_from_salary_slip
|
||||
|
||||
unlink_ref_doc_from_payment_entries(self)
|
||||
self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Payment Ledger Entry")
|
||||
unlink_ref_doc_from_salary_slip(self.name)
|
||||
self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry")
|
||||
self.make_gl_entries(1)
|
||||
self.update_advance_paid()
|
||||
self.update_expense_claim()
|
||||
self.unlink_advance_entry_reference()
|
||||
self.unlink_asset_reference()
|
||||
self.unlink_inter_company_jv()
|
||||
self.unlink_asset_adjustment_entry()
|
||||
self.update_invoice_discounting()
|
||||
self.update_status_for_full_and_final_statement()
|
||||
|
||||
def get_title(self):
|
||||
return self.pay_to_recd_from or self.accounts[0].account
|
||||
@@ -104,13 +116,21 @@ class JournalEntry(AccountsController):
|
||||
advance_paid = frappe._dict()
|
||||
for d in self.get("accounts"):
|
||||
if d.is_advance:
|
||||
if d.reference_type in frappe.get_hooks("advance_payment_doctypes"):
|
||||
if d.reference_type in ("Sales Order", "Purchase Order", "Employee Advance"):
|
||||
advance_paid.setdefault(d.reference_type, []).append(d.reference_name)
|
||||
|
||||
for voucher_type, order_list in advance_paid.items():
|
||||
for voucher_no in list(set(order_list)):
|
||||
frappe.get_doc(voucher_type, voucher_no).set_total_advance_paid()
|
||||
|
||||
def update_status_for_full_and_final_statement(self):
|
||||
for entry in self.accounts:
|
||||
if entry.reference_type == "Full and Final Statement":
|
||||
if self.docstatus == 1:
|
||||
frappe.db.set_value("Full and Final Statement", entry.reference_name, "status", "Paid")
|
||||
elif self.docstatus == 2:
|
||||
frappe.db.set_value("Full and Final Statement", entry.reference_name, "status", "Unpaid")
|
||||
|
||||
def validate_inter_company_accounts(self):
|
||||
if (
|
||||
self.voucher_type == "Inter Company Journal Entry"
|
||||
@@ -184,9 +204,7 @@ class JournalEntry(AccountsController):
|
||||
}
|
||||
)
|
||||
|
||||
tax_withholding_details, advance_taxes, voucher_wise_amount = get_party_tax_withholding_details(
|
||||
inv, self.tax_withholding_category
|
||||
)
|
||||
tax_withholding_details = get_party_tax_withholding_details(inv, self.tax_withholding_category)
|
||||
|
||||
if not tax_withholding_details:
|
||||
return
|
||||
@@ -319,7 +337,7 @@ class JournalEntry(AccountsController):
|
||||
|
||||
def validate_party(self):
|
||||
for d in self.get("accounts"):
|
||||
account_type = frappe.get_cached_value("Account", d.account, "account_type")
|
||||
account_type = frappe.db.get_value("Account", d.account, "account_type")
|
||||
if account_type in ["Receivable", "Payable"]:
|
||||
if not (d.party_type and d.party):
|
||||
frappe.throw(
|
||||
@@ -382,7 +400,7 @@ class JournalEntry(AccountsController):
|
||||
def validate_against_jv(self):
|
||||
for d in self.get("accounts"):
|
||||
if d.reference_type == "Journal Entry":
|
||||
account_root_type = frappe.get_cached_value("Account", d.account, "root_type")
|
||||
account_root_type = frappe.db.get_value("Account", d.account, "root_type")
|
||||
if account_root_type == "Asset" and flt(d.debit) > 0:
|
||||
frappe.throw(
|
||||
_(
|
||||
@@ -402,7 +420,7 @@ class JournalEntry(AccountsController):
|
||||
against_entries = frappe.db.sql(
|
||||
"""select * from `tabJournal Entry Account`
|
||||
where account = %s and docstatus = 1 and parent = %s
|
||||
and (reference_type is null or reference_type in ('', 'Sales Order', 'Purchase Order'))
|
||||
and (reference_type is null or reference_type in ("", "Sales Order", "Purchase Order"))
|
||||
""",
|
||||
(d.account, d.reference_name),
|
||||
as_dict=True,
|
||||
@@ -631,7 +649,7 @@ class JournalEntry(AccountsController):
|
||||
def validate_multi_currency(self):
|
||||
alternate_currency = []
|
||||
for d in self.get("accounts"):
|
||||
account = frappe.get_cached_value(
|
||||
account = frappe.db.get_value(
|
||||
"Account", d.account, ["account_currency", "account_type"], as_dict=1
|
||||
)
|
||||
if account:
|
||||
@@ -762,7 +780,7 @@ class JournalEntry(AccountsController):
|
||||
party_amount += d.debit_in_account_currency or d.credit_in_account_currency
|
||||
party_account_currency = d.account_currency
|
||||
|
||||
elif frappe.get_cached_value("Account", d.account, "account_type") in ["Bank", "Cash"]:
|
||||
elif frappe.db.get_value("Account", d.account, "account_type") in ["Bank", "Cash"]:
|
||||
bank_amount += d.debit_in_account_currency or d.credit_in_account_currency
|
||||
bank_account_currency = d.account_currency
|
||||
|
||||
@@ -786,7 +804,9 @@ class JournalEntry(AccountsController):
|
||||
|
||||
self.total_amount_in_words = money_in_words(amt, currency)
|
||||
|
||||
def build_gl_map(self):
|
||||
def make_gl_entries(self, cancel=0, adv_adj=0):
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
|
||||
gl_map = []
|
||||
for d in self.get("accounts"):
|
||||
if d.debit or d.credit:
|
||||
@@ -822,12 +842,7 @@ class JournalEntry(AccountsController):
|
||||
item=d,
|
||||
)
|
||||
)
|
||||
return gl_map
|
||||
|
||||
def make_gl_entries(self, cancel=0, adv_adj=0):
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
|
||||
gl_map = self.build_gl_map()
|
||||
if self.voucher_type in ("Deferred Revenue", "Deferred Expense"):
|
||||
update_outstanding = "No"
|
||||
else:
|
||||
@@ -921,6 +936,29 @@ class JournalEntry(AccountsController):
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
def update_expense_claim(self):
|
||||
for d in self.accounts:
|
||||
if d.reference_type == "Expense Claim" and d.reference_name:
|
||||
doc = frappe.get_doc("Expense Claim", d.reference_name)
|
||||
if self.docstatus == 2:
|
||||
update_reimbursed_amount(doc, -1 * d.debit)
|
||||
else:
|
||||
update_reimbursed_amount(doc, d.debit)
|
||||
|
||||
def validate_expense_claim(self):
|
||||
for d in self.accounts:
|
||||
if d.reference_type == "Expense Claim":
|
||||
sanctioned_amount, reimbursed_amount = frappe.db.get_value(
|
||||
"Expense Claim", d.reference_name, ("total_sanctioned_amount", "total_amount_reimbursed")
|
||||
)
|
||||
pending_amount = flt(sanctioned_amount) - flt(reimbursed_amount)
|
||||
if d.debit > pending_amount:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. Pending Amount is {2}"
|
||||
).format(d.idx, d.reference_name, pending_amount)
|
||||
)
|
||||
|
||||
def validate_credit_debit_note(self):
|
||||
if self.stock_entry:
|
||||
if frappe.db.get_value("Stock Entry", self.stock_entry, "docstatus") != 1:
|
||||
@@ -987,7 +1025,7 @@ def get_default_bank_cash_account(company, account_type=None, mode_of_payment=No
|
||||
account = account_list[0].name
|
||||
|
||||
if account:
|
||||
account_details = frappe.get_cached_value(
|
||||
account_details = frappe.db.get_value(
|
||||
"Account", account, ["account_currency", "account_type"], as_dict=1
|
||||
)
|
||||
|
||||
@@ -1116,7 +1154,7 @@ def get_payment_entry(ref_doc, args):
|
||||
"party_type": args.get("party_type"),
|
||||
"party": ref_doc.get(args.get("party_type").lower()),
|
||||
"cost_center": cost_center,
|
||||
"account_type": frappe.get_cached_value("Account", args.get("party_account"), "account_type"),
|
||||
"account_type": frappe.db.get_value("Account", args.get("party_account"), "account_type"),
|
||||
"account_currency": args.get("party_account_currency")
|
||||
or get_account_currency(args.get("party_account")),
|
||||
"balance": get_balance_on(args.get("party_account")),
|
||||
@@ -1167,6 +1205,24 @@ def get_payment_entry(ref_doc, args):
|
||||
return je if args.get("journal_entry") else je.as_dict()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_opening_accounts(company):
|
||||
"""get all balance sheet accounts for opening entry"""
|
||||
accounts = frappe.db.sql_list(
|
||||
"""select
|
||||
name from tabAccount
|
||||
where
|
||||
is_group=0 and report_type='Balance Sheet' and company={0} and
|
||||
name not in (select distinct account from tabWarehouse where
|
||||
account is not null and account != '')
|
||||
order by name asc""".format(
|
||||
frappe.db.escape(company)
|
||||
)
|
||||
)
|
||||
|
||||
return [{"account": a, "balance": get_balance_on(a)} for a in accounts]
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
|
||||
@@ -1187,7 +1243,7 @@ def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
|
||||
AND jv.docstatus = 1
|
||||
AND jv.`{0}` LIKE %(txt)s
|
||||
ORDER BY jv.name DESC
|
||||
LIMIT %(limit)s offset %(offset)s
|
||||
LIMIT %(offset)s, %(limit)s
|
||||
""".format(
|
||||
searchfield
|
||||
),
|
||||
@@ -1210,7 +1266,6 @@ def get_outstanding(args):
|
||||
args = json.loads(args)
|
||||
|
||||
company_currency = erpnext.get_company_currency(args.get("company"))
|
||||
due_date = None
|
||||
|
||||
if args.get("doctype") == "Journal Entry":
|
||||
condition = " and party=%(party)s" if args.get("party") else ""
|
||||
@@ -1235,12 +1290,10 @@ def get_outstanding(args):
|
||||
invoice = frappe.db.get_value(
|
||||
args["doctype"],
|
||||
args["docname"],
|
||||
["outstanding_amount", "conversion_rate", scrub(party_type), "due_date"],
|
||||
["outstanding_amount", "conversion_rate", scrub(party_type)],
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
due_date = invoice.get("due_date")
|
||||
|
||||
exchange_rate = (
|
||||
invoice.conversion_rate if (args.get("account_currency") != company_currency) else 1
|
||||
)
|
||||
@@ -1263,7 +1316,6 @@ def get_outstanding(args):
|
||||
"exchange_rate": exchange_rate,
|
||||
"party_type": party_type,
|
||||
"party": invoice.get(scrub(party_type)),
|
||||
"reference_due_date": due_date,
|
||||
}
|
||||
|
||||
|
||||
@@ -1283,7 +1335,7 @@ def get_party_account_and_balance(company, party_type, party, cost_center=None):
|
||||
"account": account,
|
||||
"balance": account_balance,
|
||||
"party_balance": party_balance,
|
||||
"account_currency": frappe.get_cached_value("Account", account, "account_currency"),
|
||||
"account_currency": frappe.db.get_value("Account", account, "account_currency"),
|
||||
}
|
||||
|
||||
|
||||
@@ -1296,7 +1348,7 @@ def get_account_balance_and_party_type(
|
||||
frappe.msgprint(_("No Permission"), raise_exception=1)
|
||||
|
||||
company_currency = erpnext.get_company_currency(company)
|
||||
account_details = frappe.get_cached_value(
|
||||
account_details = frappe.db.get_value(
|
||||
"Account", account, ["account_type", "account_currency"], as_dict=1
|
||||
)
|
||||
|
||||
@@ -1349,7 +1401,7 @@ def get_exchange_rate(
|
||||
):
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
|
||||
account_details = frappe.get_cached_value(
|
||||
account_details = frappe.db.get_value(
|
||||
"Account", account, ["account_type", "root_type", "account_currency", "company"], as_dict=1
|
||||
)
|
||||
|
||||
|
||||
17
erpnext/accounts/doctype/journal_entry/regional/india.js
Normal file
17
erpnext/accounts/doctype/journal_entry/regional/india.js
Normal file
@@ -0,0 +1,17 @@
|
||||
frappe.ui.form.on("Journal Entry", {
|
||||
refresh: function(frm) {
|
||||
frm.set_query('company_address', function(doc) {
|
||||
if(!doc.company) {
|
||||
frappe.throw(__('Please set Company'));
|
||||
}
|
||||
|
||||
return {
|
||||
query: 'frappe.contacts.doctype.address.address.address_query',
|
||||
filters: {
|
||||
link_doctype: 'Company',
|
||||
link_name: doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -202,7 +202,6 @@
|
||||
"fieldname": "reference_type",
|
||||
"fieldtype": "Select",
|
||||
"label": "Reference Type",
|
||||
"no_copy": 1,
|
||||
"options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset\nLoan\nPayroll Entry\nEmployee Advance\nExchange Rate Revaluation\nInvoice Discounting\nFees\nFull and Final Statement"
|
||||
},
|
||||
{
|
||||
@@ -210,15 +209,13 @@
|
||||
"fieldtype": "Dynamic Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Reference Name",
|
||||
"no_copy": 1,
|
||||
"options": "reference_type"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.reference_type&&!in_list(doc.reference_type, ['Expense Claim', 'Asset', 'Employee Loan', 'Employee Advance'])",
|
||||
"fieldname": "reference_due_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Reference Due Date",
|
||||
"no_copy": 1
|
||||
"fieldtype": "Select",
|
||||
"label": "Reference Due Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "project",
|
||||
@@ -277,22 +274,19 @@
|
||||
"fieldname": "reference_detail_no",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Reference Detail No",
|
||||
"no_copy": 1
|
||||
"label": "Reference Detail No"
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2022-10-26 20:03:10.906259",
|
||||
"modified": "2021-08-30 21:27:32.200299",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Entry Account",
|
||||
"naming_rule": "Random",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user